diff --git a/grammar.js b/grammar.js index 7e6bf9d..5a822ba 100644 --- a/grammar.js +++ b/grammar.js @@ -1,24 +1,103 @@ -const spaces = repeat(choice(" ", "\t")); +const PREC = { + COMMENT: -2, + IDENTIFIER: 11, + SHAPE: 10, + CONTAINER: 9, +}; + +spaces = /[ \t]/; module.exports = grammar({ name: "d2", - extras: ($) => [$.line_comment], + extras: ($) => [ + /[ \f\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/, + $.line_comment, + ], word: ($) => $._word, conflicts: ($) => [ - [$.shape_key], + //[$.shape_key], + /* [$._shape_path], [$._shape_block], [$._shape_block_definition], [$._style_attr_block], [$._inner_style_attribute], [$._emptyline], +*/ ], rules: { - source_file: ($) => repeat($._root_definition), + source_file: ($) => repeat($._new_root_definition), + + _new_root_definition: ($) => choice($._eol, $.shape, $.container), + + container: ($) => + prec( + PREC.CONTAINER, + seq( + alias($.shape_key, $.container_key), + choice( + seq($._dot, $.shape), + seq( + seq( + optional(seq($._colon, optional($.label))), + optional(seq(alias($._new_container_block, $.block))) + ) + ) + ) + ) + ), + + shape: ($) => + prec( + PREC.SHAPE, + seq( + $.shape_key, + optional( + seq( + optional(seq($._colon, optional($.label))), + optional(seq(alias($._new_shape_block, $.block))) + ) + ), + $._end + ) + ), + + shape_key: ($) => + choice( + $.string, + prec.left( + seq( + optional($._dash), + choice( + $._word, + token(prec(PREC.IDENTIFIER, /([\w\d]+( +|\-)[\w\d]+)+/)) + ), + optional($._dash) + ) + ) + ), + + _new_shape_block: ($) => + prec(PREC.SHAPE, seq("{", repeat($._new_shape_block_definition), "}")), + + _new_shape_block_definition: ($) => prec(PREC.SHAPE, choice($._eol)), + + _new_container_block: ($) => + prec( + PREC.CONTAINER, + seq("{", repeat($._new_container_block_definition), "}") + ), + + _new_container_block_definition: ($) => + prec(PREC.CONTAINER, choice($._eol, $.shape, $.container)), + + // -------------------------------------------- + + // source_file: ($) => repeat($._root_definition), _root_definition: ($) => choice( @@ -60,19 +139,6 @@ module.exports = grammar({ $.shape_key ), - shape_key: ($) => - choice( - $.string, - seq( - optional($._dash), - choice( - $._word, - repeat1(seq($._word, choice(repeat1(" "), $._dash), $._word)) - ), - optional($._dash) - ) - ), - _dash: ($) => token.immediate("-"), label: ($) => choice($.string, $._unquoted_string), @@ -169,15 +235,16 @@ module.exports = grammar({ _connection_attr_key: ($) => choice("source-arrowhead", "target-arrowhead"), - _colon: ($) => seq(spaces, ":"), + _colon: ($) => seq(":"), _arrow: ($) => seq(spaces, $.arrow), arrow: ($) => choice(/-+>/, /--+/, /<-+/, /<-+>/), - dot: ($) => token.immediate("."), + _dot: ($) => seq($.dot), + dot: ($) => token("."), - _unquoted_string: ($) => token.immediate(/[^'"`\n;{}]+/), + _unquoted_string: ($) => token(prec(5, /[\w\-]([^'"`\n;{}]*[\w\-])?/)), string: ($) => choice( @@ -186,12 +253,12 @@ module.exports = grammar({ seq("`", repeat(token.immediate(/[^`\n]+/)), "`") ), - line_comment: ($) => token(prec(-2, seq("#", /.*/))), + line_comment: ($) => token(prec(PREC.COMMENT, seq("#", /.*/))), _word: ($) => /[\w\d]+/, - _emptyline: ($) => seq(spaces, $._eof), - _eof: ($) => choice("\n", "\0"), - _end: ($) => seq(spaces, choice(";", $._eof)), + _emptyline: ($) => prec(-1, seq(spaces, $._eol)), + _eol: ($) => choice("\n", "\0"), + _end: ($) => seq(choice(";", $._eol)), }, }); diff --git a/src/grammar.json b/src/grammar.json index 537f9ee..d6bdea1 100644 --- a/src/grammar.json +++ b/src/grammar.json @@ -6,7 +6,346 @@ "type": "REPEAT", "content": { "type": "SYMBOL", - "name": "_root_definition" + "name": "_new_root_definition" + } + }, + "_new_root_definition": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_eol" + }, + { + "type": "SYMBOL", + "name": "shape" + }, + { + "type": "SYMBOL", + "name": "container" + } + ] + }, + "container": { + "type": "PREC", + "value": 9, + "content": { + "type": "SEQ", + "members": [ + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "shape_key" + }, + "named": true, + "value": "container_key" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_dot" + }, + { + "type": "SYMBOL", + "name": "shape" + } + ] + }, + { + "type": "SEQ", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_colon" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "label" + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_new_container_block" + }, + "named": true, + "value": "block" + } + ] + }, + { + "type": "BLANK" + } + ] + } + ] + } + ] + } + ] + } + ] + } + }, + "shape": { + "type": "PREC", + "value": 10, + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "shape_key" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_colon" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "label" + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_new_shape_block" + }, + "named": true, + "value": "block" + } + ] + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "SYMBOL", + "name": "_end" + } + ] + } + }, + "shape_key": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "string" + }, + { + "type": "PREC_LEFT", + "value": 0, + "content": { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_dash" + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_word" + }, + { + "type": "TOKEN", + "content": { + "type": "PREC", + "value": 11, + "content": { + "type": "PATTERN", + "value": "([\\w\\d]+( +|\\-)[\\w\\d]+)+" + } + } + } + ] + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_dash" + }, + { + "type": "BLANK" + } + ] + } + ] + } + } + ] + }, + "_new_shape_block": { + "type": "PREC", + "value": 10, + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "{" + }, + { + "type": "REPEAT", + "content": { + "type": "SYMBOL", + "name": "_new_shape_block_definition" + } + }, + { + "type": "STRING", + "value": "}" + } + ] + } + }, + "_new_shape_block_definition": { + "type": "PREC", + "value": 10, + "content": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_eol" + } + ] + } + }, + "_new_container_block": { + "type": "PREC", + "value": 9, + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "{" + }, + { + "type": "REPEAT", + "content": { + "type": "SYMBOL", + "name": "_new_container_block_definition" + } + }, + { + "type": "STRING", + "value": "}" + } + ] + } + }, + "_new_container_block_definition": { + "type": "PREC", + "value": 9, + "content": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_eol" + }, + { + "type": "SYMBOL", + "name": "shape" + }, + { + "type": "SYMBOL", + "name": "container" + } + ] } }, "_root_definition": { @@ -144,20 +483,8 @@ "type": "SEQ", "members": [ { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } + "type": "PATTERN", + "value": "[ \\t]" }, { "type": "SYMBOL", @@ -213,20 +540,8 @@ "type": "SEQ", "members": [ { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } + "type": "PATTERN", + "value": "[ \\t]" }, { "type": "REPEAT", @@ -243,40 +558,16 @@ "value": "container_key" }, { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } + "type": "PATTERN", + "value": "[ \\t]" }, { "type": "SYMBOL", "name": "dot" }, { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } + "type": "PATTERN", + "value": "[ \\t]" } ] } @@ -287,85 +578,6 @@ } ] }, - "shape_key": { - "type": "CHOICE", - "members": [ - { - "type": "SYMBOL", - "name": "string" - }, - { - "type": "SEQ", - "members": [ - { - "type": "CHOICE", - "members": [ - { - "type": "SYMBOL", - "name": "_dash" - }, - { - "type": "BLANK" - } - ] - }, - { - "type": "CHOICE", - "members": [ - { - "type": "SYMBOL", - "name": "_word" - }, - { - "type": "REPEAT1", - "content": { - "type": "SEQ", - "members": [ - { - "type": "SYMBOL", - "name": "_word" - }, - { - "type": "CHOICE", - "members": [ - { - "type": "REPEAT1", - "content": { - "type": "STRING", - "value": " " - } - }, - { - "type": "SYMBOL", - "name": "_dash" - } - ] - }, - { - "type": "SYMBOL", - "name": "_word" - } - ] - } - } - ] - }, - { - "type": "CHOICE", - "members": [ - { - "type": "SYMBOL", - "name": "_dash" - }, - { - "type": "BLANK" - } - ] - } - ] - } - ] - }, "_dash": { "type": "IMMEDIATE_TOKEN", "content": { @@ -390,20 +602,8 @@ "type": "SEQ", "members": [ { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } + "type": "PATTERN", + "value": "[ \\t]" }, { "type": "CHOICE", @@ -477,20 +677,8 @@ "type": "SEQ", "members": [ { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } + "type": "PATTERN", + "value": "[ \\t]" }, { "type": "STRING", @@ -509,20 +697,8 @@ "type": "SEQ", "members": [ { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } + "type": "PATTERN", + "value": "[ \\t]" }, { "type": "SYMBOL", @@ -563,20 +739,8 @@ ] }, { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } + "type": "PATTERN", + "value": "[ \\t]" }, { "type": "STRING", @@ -686,40 +850,16 @@ "type": "SEQ", "members": [ { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } + "type": "PATTERN", + "value": "[ \\t]" }, { "type": "STRING", "value": "{" }, { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } + "type": "PATTERN", + "value": "[ \\t]" }, { "type": "REPEAT", @@ -776,20 +916,8 @@ ] }, { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } + "type": "PATTERN", + "value": "[ \\t]" }, { "type": "STRING", @@ -801,20 +929,8 @@ "type": "SEQ", "members": [ { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } + "type": "PATTERN", + "value": "[ \\t]" }, { "type": "ALIAS", @@ -959,22 +1075,6 @@ "_colon": { "type": "SEQ", "members": [ - { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } - }, { "type": "STRING", "value": ":" @@ -985,20 +1085,8 @@ "type": "SEQ", "members": [ { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } + "type": "PATTERN", + "value": "[ \\t]" }, { "type": "SYMBOL", @@ -1027,18 +1115,31 @@ } ] }, + "_dot": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "dot" + } + ] + }, "dot": { - "type": "IMMEDIATE_TOKEN", + "type": "TOKEN", "content": { "type": "STRING", "value": "." } }, "_unquoted_string": { - "type": "IMMEDIATE_TOKEN", + "type": "TOKEN", "content": { - "type": "PATTERN", - "value": "[^'\"`\\n;{}]+" + "type": "PREC", + "value": 5, + "content": { + "type": "PATTERN", + "value": "[\\w\\-]([^'\"`\\n;{}]*[\\w\\-])?" + } } }, "string": { @@ -1140,31 +1241,23 @@ "value": "[\\w\\d]+" }, "_emptyline": { - "type": "SEQ", - "members": [ - { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] + "type": "PREC", + "value": -1, + "content": { + "type": "SEQ", + "members": [ + { + "type": "PATTERN", + "value": "[ \\t]" + }, + { + "type": "SYMBOL", + "name": "_eol" } - }, - { - "type": "SYMBOL", - "name": "_eof" - } - ] + ] + } }, - "_eof": { + "_eol": { "type": "CHOICE", "members": [ { @@ -1180,22 +1273,6 @@ "_end": { "type": "SEQ", "members": [ - { - "type": "REPEAT", - "content": { - "type": "CHOICE", - "members": [ - { - "type": "STRING", - "value": " " - }, - { - "type": "STRING", - "value": "\t" - } - ] - } - }, { "type": "CHOICE", "members": [ @@ -1205,7 +1282,7 @@ }, { "type": "SYMBOL", - "name": "_eof" + "name": "_eol" } ] } @@ -1213,34 +1290,16 @@ } }, "extras": [ + { + "type": "PATTERN", + "value": "[ \\f\\t\\v\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]" + }, { "type": "SYMBOL", "name": "line_comment" } ], - "conflicts": [ - [ - "shape_key" - ], - [ - "_shape_path" - ], - [ - "_shape_block" - ], - [ - "_shape_block_definition" - ], - [ - "_style_attr_block" - ], - [ - "_inner_style_attribute" - ], - [ - "_emptyline" - ] - ], + "conflicts": [], "precedences": [], "externals": [], "inline": [], diff --git a/src/node-types.json b/src/node-types.json index 2efdd90..08d15be 100644 --- a/src/node-types.json +++ b/src/node-types.json @@ -48,6 +48,10 @@ "type": "connection", "named": true }, + { + "type": "container", + "named": true + }, { "type": "container_key", "named": true @@ -60,6 +64,10 @@ "type": "label", "named": true }, + { + "type": "shape", + "named": true + }, { "type": "shape_key", "named": true @@ -106,6 +114,37 @@ ] } }, + { + "type": "container", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "block", + "named": true + }, + { + "type": "container_key", + "named": true + }, + { + "type": "dot", + "named": true + }, + { + "type": "label", + "named": true + }, + { + "type": "shape", + "named": true + } + ] + } + }, { "type": "container_key", "named": true, @@ -163,6 +202,29 @@ ] } }, + { + "type": "shape", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "block", + "named": true + }, + { + "type": "label", + "named": true + }, + { + "type": "shape_key", + "named": true + } + ] + } + }, { "type": "shape_key", "named": true, @@ -187,39 +249,11 @@ "required": false, "types": [ { - "type": "attr_key", + "type": "container", "named": true }, { - "type": "attr_value", - "named": true - }, - { - "type": "block", - "named": true - }, - { - "type": "connection", - "named": true - }, - { - "type": "container_key", - "named": true - }, - { - "type": "dot", - "named": true - }, - { - "type": "invalid", - "named": true - }, - { - "type": "label", - "named": true - }, - { - "type": "shape_key", + "type": "shape", "named": true } ] @@ -234,18 +268,10 @@ "type": "\u0000", "named": false }, - { - "type": "\t", - "named": false - }, { "type": "\n", "named": false }, - { - "type": " ", - "named": false - }, { "type": "\"", "named": false diff --git a/src/parser.c b/src/parser.c index 00ca678..a0e3f0f 100644 Binary files a/src/parser.c and b/src/parser.c differ diff --git a/tree-sitter-d2.wasm b/tree-sitter-d2.wasm index c9f5b7d..e91ec96 100755 Binary files a/tree-sitter-d2.wasm and b/tree-sitter-d2.wasm differ