diff --git a/examples/test.txt b/examples/test.txt index 3cab11b..9ce0e87 100644 --- a/examples/test.txt +++ b/examples/test.txt @@ -1,3 +1,3 @@ -Foo Bar -- Biz Baz --Bar-Foo- <- -Baz-Biz- +foo.shape: 'oval' +foo.bar.baz.shape: oval diff --git a/grammar.js b/grammar.js index ab57c27..7764a6c 100644 --- a/grammar.js +++ b/grammar.js @@ -7,18 +7,13 @@ module.exports = grammar({ // TODO: add the actual grammar rules source_file: ($) => repeat($._definition), - _definition: ($) => - choice( - choice($._root_attribute, $._shape_attribute), - $.connection, - $.shape - ), + _definition: ($) => choice($._root_attribute, $.connection, $.shape), connection: ($) => seq( $.identifier, choice( - seq(seq($.arrow, $.identifier, ":", $.label)), + seq(seq($.arrow, $.identifier, $._colon, $.label)), seq(repeat1(seq($.arrow, $.identifier))) ), $._end @@ -28,7 +23,10 @@ module.exports = grammar({ seq( $.identifier, repeat(seq($.dot, $.identifier)), - optional(seq(":", $.label)), + choice( + optional(seq($.dot, $._shape_attribute)), + optional(seq($._colon, $.label)) + ), $._end ), @@ -39,12 +37,7 @@ module.exports = grammar({ attr_value: ($) => choice($.string, $._unquoted_string), _root_attribute: ($) => - seq( - alias($._root_attr_key, $.attr_key), - ":", - alias($.label, $.attr_value), - $._end - ), + seq(alias($._root_attr_key, $.attr_key), $._colon, $.attr_value, $._end), _root_attr_key: ($) => "direction", @@ -53,19 +46,14 @@ module.exports = grammar({ alias("style", $.attr_key), $.dot, alias($._style_attr_key, $.attr_key), - ":", - $.attr_value, - $._end + $._colon, + $.attr_value ), _shape_attribute: ($) => - seq( - $.identifier, - $.dot, - choice( - seq(alias($._shape_attr_key, $.attr_key), ":", $.attr_value, $._end), - $._style_attribute - ) + choice( + seq(alias($._shape_attr_key, $.attr_key), $._colon, $.attr_value), + $._style_attribute ), _shape_attr_key: ($) => @@ -114,6 +102,8 @@ module.exports = grammar({ ) ), + _colon: ($) => seq(repeat(" "), ":", repeat(" ")), + _dash: ($) => token.immediate("-"), _word: ($) => /[\w\d]+/, @@ -128,13 +118,13 @@ module.exports = grammar({ ) ), - _unquoted_string: ($) => /[^\n;{]+/, + _unquoted_string: ($) => token.immediate(/[^'"`\n;{]+/), string: ($) => choice( - seq("'", repeat(token(/[^'\n]+/)), "'"), - seq('"', repeat(token(/[^'\n]+/)), '"'), - seq("`", repeat(token(/[^'\n]+/)), "`") + seq("'", repeat(token.immediate(/[^'\n]+/)), "'"), + seq('"', repeat(token.immediate(/[^"\n]+/)), '"'), + seq("`", repeat(token.immediate(/[^`\n]+/)), "`") ), _end: ($) => choice(";", "\n", "\0"), diff --git a/src/grammar.json b/src/grammar.json index ed3dde2..2d09c3e 100644 --- a/src/grammar.json +++ b/src/grammar.json @@ -13,17 +13,8 @@ "type": "CHOICE", "members": [ { - "type": "CHOICE", - "members": [ - { - "type": "SYMBOL", - "name": "_root_attribute" - }, - { - "type": "SYMBOL", - "name": "_shape_attribute" - } - ] + "type": "SYMBOL", + "name": "_root_attribute" }, { "type": "SYMBOL", @@ -60,8 +51,8 @@ "name": "identifier" }, { - "type": "STRING", - "value": ":" + "type": "SYMBOL", + "name": "_colon" }, { "type": "SYMBOL", @@ -127,20 +118,46 @@ "type": "CHOICE", "members": [ { - "type": "SEQ", + "type": "CHOICE", "members": [ { - "type": "STRING", - "value": ":" + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "dot" + }, + { + "type": "SYMBOL", + "name": "_shape_attribute" + } + ] }, { - "type": "SYMBOL", - "name": "label" + "type": "BLANK" } ] }, { - "type": "BLANK" + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_colon" + }, + { + "type": "SYMBOL", + "name": "label" + } + ] + }, + { + "type": "BLANK" + } + ] } ] }, @@ -193,17 +210,12 @@ "value": "attr_key" }, { - "type": "STRING", - "value": ":" + "type": "SYMBOL", + "name": "_colon" }, { - "type": "ALIAS", - "content": { - "type": "SYMBOL", - "name": "label" - }, - "named": true, - "value": "attr_value" + "type": "SYMBOL", + "name": "attr_value" }, { "type": "SYMBOL", @@ -241,64 +253,43 @@ "value": "attr_key" }, { - "type": "STRING", - "value": ":" + "type": "SYMBOL", + "name": "_colon" }, { "type": "SYMBOL", "name": "attr_value" - }, - { - "type": "SYMBOL", - "name": "_end" } ] }, "_shape_attribute": { - "type": "SEQ", + "type": "CHOICE", "members": [ { - "type": "SYMBOL", - "name": "identifier" - }, - { - "type": "SYMBOL", - "name": "dot" - }, - { - "type": "CHOICE", + "type": "SEQ", "members": [ { - "type": "SEQ", - "members": [ - { - "type": "ALIAS", - "content": { - "type": "SYMBOL", - "name": "_shape_attr_key" - }, - "named": true, - "value": "attr_key" - }, - { - "type": "STRING", - "value": ":" - }, - { - "type": "SYMBOL", - "name": "attr_value" - }, - { - "type": "SYMBOL", - "name": "_end" - } - ] + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_shape_attr_key" + }, + "named": true, + "value": "attr_key" }, { "type": "SYMBOL", - "name": "_style_attribute" + "name": "_colon" + }, + { + "type": "SYMBOL", + "name": "attr_value" } ] + }, + { + "type": "SYMBOL", + "name": "_style_attribute" } ] }, @@ -489,6 +480,29 @@ ] } }, + "_colon": { + "type": "SEQ", + "members": [ + { + "type": "REPEAT", + "content": { + "type": "STRING", + "value": " " + } + }, + { + "type": "STRING", + "value": ":" + }, + { + "type": "REPEAT", + "content": { + "type": "STRING", + "value": " " + } + } + ] + }, "_dash": { "type": "IMMEDIATE_TOKEN", "content": { @@ -578,8 +592,11 @@ } }, "_unquoted_string": { - "type": "PATTERN", - "value": "[^\\n;{]+" + "type": "IMMEDIATE_TOKEN", + "content": { + "type": "PATTERN", + "value": "[^'\"`\\n;{]+" + } }, "string": { "type": "CHOICE", @@ -594,7 +611,7 @@ { "type": "REPEAT", "content": { - "type": "TOKEN", + "type": "IMMEDIATE_TOKEN", "content": { "type": "PATTERN", "value": "[^'\\n]+" @@ -617,10 +634,10 @@ { "type": "REPEAT", "content": { - "type": "TOKEN", + "type": "IMMEDIATE_TOKEN", "content": { "type": "PATTERN", - "value": "[^'\\n]+" + "value": "[^\"\\n]+" } } }, @@ -640,10 +657,10 @@ { "type": "REPEAT", "content": { - "type": "TOKEN", + "type": "IMMEDIATE_TOKEN", "content": { "type": "PATTERN", - "value": "[^'\\n]+" + "value": "[^`\\n]+" } } }, diff --git a/src/node-types.json b/src/node-types.json index d55a06c..6e7a087 100644 --- a/src/node-types.json +++ b/src/node-types.json @@ -75,6 +75,14 @@ "multiple": true, "required": true, "types": [ + { + "type": "attr_key", + "named": true + }, + { + "type": "attr_value", + "named": true + }, { "type": "dot", "named": true @@ -110,14 +118,6 @@ "type": "connection", "named": true }, - { - "type": "dot", - "named": true - }, - { - "type": "identifier", - "named": true - }, { "type": "shape", "named": true diff --git a/src/parser.c b/src/parser.c index ada0c5d..471d95c 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 index 94c93ab..1dc817d 100644 --- a/test/corpus/attributes.txt +++ b/test/corpus/attributes.txt @@ -15,11 +15,13 @@ Inline shape attribute ================== foo.shape: oval +foo.bar.baz.shape: oval --- (source_file - (identifier) (dot) (attr_key) (attr_value) + (shape (identifier) (dot) (attr_key) (attr_value)) + (shape (identifier) (dot) (identifier) (dot) (identifier) (dot) (attr_key) (attr_value)) ) ================== @@ -31,7 +33,7 @@ foo.style.opacity: 5 --- (source_file - (identifier) (dot) (attr_key) (dot) (attr_key) (attr_value) + (shape (identifier) (dot) (attr_key) (dot) (attr_key) (attr_value)) )