diff --git a/grammar.js b/grammar.js index f8314e0..d2d3bcf 100644 --- a/grammar.js +++ b/grammar.js @@ -1,13 +1,33 @@ module.exports = grammar({ name: "d2", + word: ($) => $._word, + rules: { // TODO: add the actual grammar rules source_file: ($) => repeat($._definition), - _definition: ($) => choice($.connection, $.shape), + _definition: ($) => choice($.attribute, $.connection, $.shape), - _end: ($) => choice(";", "\n"), + _end: ($) => choice(";", "\n", "\0"), + + attribute: ($) => + choice( + seq( + $.identifier, + repeat1(seq($.dot, $.keyword)), + ":", + alias($.label, $.attribute_value), + $._end + ), + seq( + $.keyword, + repeat(seq($.dot, $.keyword)), + ":", + alias($.label, $.attribute_value), + $._end + ) + ), connection: ($) => seq( @@ -33,6 +53,8 @@ module.exports = grammar({ identifier: ($) => $._identifier, + keyword: ($) => choice("direction"), + _identifier: ($) => prec.right( seq( diff --git a/src/grammar.json b/src/grammar.json index 5dc698c..8cc9d28 100644 --- a/src/grammar.json +++ b/src/grammar.json @@ -1,5 +1,6 @@ { "name": "d2", + "word": "_word", "rules": { "source_file": { "type": "REPEAT", @@ -11,6 +12,10 @@ "_definition": { "type": "CHOICE", "members": [ + { + "type": "SYMBOL", + "name": "attribute" + }, { "type": "SYMBOL", "name": "connection" @@ -31,6 +36,99 @@ { "type": "STRING", "value": "\n" + }, + { + "type": "STRING", + "value": "\u0000" + } + ] + }, + "attribute": { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "identifier" + }, + { + "type": "REPEAT1", + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "dot" + }, + { + "type": "SYMBOL", + "name": "keyword" + } + ] + } + }, + { + "type": "STRING", + "value": ":" + }, + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "label" + }, + "named": true, + "value": "attribute_value" + }, + { + "type": "SYMBOL", + "name": "_end" + } + ] + }, + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "keyword" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "dot" + }, + { + "type": "SYMBOL", + "name": "keyword" + } + ] + } + }, + { + "type": "STRING", + "value": ":" + }, + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "label" + }, + "named": true, + "value": "attribute_value" + }, + { + "type": "SYMBOL", + "name": "_end" + } + ] } ] }, @@ -170,6 +268,15 @@ "type": "SYMBOL", "name": "_identifier" }, + "keyword": { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "direction" + } + ] + }, "_identifier": { "type": "PREC_RIGHT", "value": 0, diff --git a/src/node-types.json b/src/node-types.json index 8d2a165..987344d 100644 --- a/src/node-types.json +++ b/src/node-types.json @@ -4,6 +4,48 @@ "named": true, "fields": {} }, + { + "type": "attribute", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "attribute_value", + "named": true + }, + { + "type": "dot", + "named": true + }, + { + "type": "identifier", + "named": true + }, + { + "type": "keyword", + "named": true + } + ] + } + }, + { + "type": "attribute_value", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": false, + "types": [ + { + "type": "string", + "named": true + } + ] + } + }, { "type": "connection", "named": true, @@ -32,6 +74,11 @@ "named": true, "fields": {} }, + { + "type": "keyword", + "named": true, + "fields": {} + }, { "type": "label", "named": true, @@ -78,6 +125,10 @@ "multiple": true, "required": false, "types": [ + { + "type": "attribute", + "named": true + }, { "type": "connection", "named": true @@ -94,6 +145,10 @@ "named": true, "fields": {} }, + { + "type": "\u0000", + "named": false + }, { "type": "\n", "named": false @@ -138,6 +193,10 @@ "type": "`", "named": false }, + { + "type": "direction", + "named": false + }, { "type": "dot", "named": true diff --git a/src/parser.c b/src/parser.c index ee2eca5..7594851 100644 Binary files a/src/parser.c and b/src/parser.c differ diff --git a/test/corpus/attributes.txt b/test/corpus/attributes.txt new file mode 100644 index 0000000..9a2c11d --- /dev/null +++ b/test/corpus/attributes.txt @@ -0,0 +1,12 @@ +================== +Keywords +================== + +direction: value + +--- + +(source_file + (attribute (keyword) (attribute_value)) +) +