diff --git a/grammar.js b/grammar.js index a5d273f..dea9031 100644 --- a/grammar.js +++ b/grammar.js @@ -8,8 +8,11 @@ module.exports = grammar({ word: ($) => $._word, conflicts: ($) => [ + [$._identifier], [$.identifier], [$.arrow], + [$._shape_block], + [$._shape_block_definition], [$._style_attr_block], [$._inner_style_attribute], ], @@ -18,7 +21,7 @@ module.exports = grammar({ source_file: ($) => repeat($._definition), _definition: ($) => - choice($._end, $._root_attribute, $.connection, $.shape), + choice(seq(spaces, $._eof), $._root_attribute, $.connection, $.shape), connection: ($) => seq( @@ -35,7 +38,14 @@ module.exports = grammar({ $._identifier, repeat(seq($.dot, $._identifier)), optional( - choice(seq($.dot, $._shape_attribute), seq($._colon, $.label)) + choice( + seq($.dot, $._shape_attribute), + seq( + $._colon, + optional($.label), + optional(alias($._shape_block, $.block)) + ) + ) ), $._end ), @@ -49,6 +59,22 @@ module.exports = grammar({ _root_attr_key: ($) => "direction", + _shape_block: ($) => + seq( + spaces, + "{", + spaces, + repeat( + choice(seq(spaces, $._eof), seq($._shape_block_definition, $._end)) + ), + optional(seq($._shape_block_definition, optional($._end))), + spaces, + "}" + ), + + _shape_block_definition: ($) => + choice($.connection, $.shape, $._shape_attribute), + _shape_attribute: ($) => choice( seq(alias($._shape_attr_key, $.attr_key), $._colon, $.attr_value), diff --git a/src/grammar.json b/src/grammar.json index 5da90b7..0493811 100644 --- a/src/grammar.json +++ b/src/grammar.json @@ -13,8 +13,20 @@ "type": "CHOICE", "members": [ { - "type": "SYMBOL", - "name": "_end" + "type": "SEQ", + "members": [ + { + "type": "REPEAT", + "content": { + "type": "STRING", + "value": " " + } + }, + { + "type": "SYMBOL", + "name": "_eof" + } + ] }, { "type": "SYMBOL", @@ -148,8 +160,33 @@ "name": "_colon" }, { - "type": "SYMBOL", - "name": "label" + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "label" + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "CHOICE", + "members": [ + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_shape_block" + }, + "named": true, + "value": "block" + }, + { + "type": "BLANK" + } + ] } ] } @@ -234,6 +271,123 @@ "type": "STRING", "value": "direction" }, + "_shape_block": { + "type": "SEQ", + "members": [ + { + "type": "REPEAT", + "content": { + "type": "STRING", + "value": " " + } + }, + { + "type": "STRING", + "value": "{" + }, + { + "type": "REPEAT", + "content": { + "type": "STRING", + "value": " " + } + }, + { + "type": "REPEAT", + "content": { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "REPEAT", + "content": { + "type": "STRING", + "value": " " + } + }, + { + "type": "SYMBOL", + "name": "_eof" + } + ] + }, + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_shape_block_definition" + }, + { + "type": "SYMBOL", + "name": "_end" + } + ] + } + ] + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_shape_block_definition" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_end" + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "REPEAT", + "content": { + "type": "STRING", + "value": " " + } + }, + { + "type": "STRING", + "value": "}" + } + ] + }, + "_shape_block_definition": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "connection" + }, + { + "type": "SYMBOL", + "name": "shape" + }, + { + "type": "SYMBOL", + "name": "_shape_attribute" + } + ] + }, "_shape_attribute": { "type": "CHOICE", "members": [ @@ -884,12 +1038,21 @@ }, "extras": [], "conflicts": [ + [ + "_identifier" + ], [ "identifier" ], [ "arrow" ], + [ + "_shape_block" + ], + [ + "_shape_block_definition" + ], [ "_style_attr_block" ], diff --git a/src/node-types.json b/src/node-types.json index 8b3cd04..7d868bf 100644 --- a/src/node-types.json +++ b/src/node-types.json @@ -39,6 +39,22 @@ { "type": "attr_value", "named": true + }, + { + "type": "block", + "named": true + }, + { + "type": "connection", + "named": true + }, + { + "type": "dot", + "named": true + }, + { + "type": "shape", + "named": true } ] } diff --git a/src/parser.c b/src/parser.c index 3674623..dcc9e33 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 8996603..a73d288 100644 --- a/test/corpus/attributes.txt +++ b/test/corpus/attributes.txt @@ -38,6 +38,7 @@ Block style attributes ================================================================================ foo.style: { opacity: 5 + fill: red; } @@ -77,8 +78,3 @@ foo.style: { opacity: 5 } ) ) - - - - - diff --git a/test/corpus/shape.txt b/test/corpus/shape.txt index f0c175e..0375213 100644 --- a/test/corpus/shape.txt +++ b/test/corpus/shape.txt @@ -83,3 +83,26 @@ bar : Foo Bar; baz (shape (identifier)) ) +================================================================================ +Shape block +================================================================================ + +foo: { + bar: { + baz: { + biz + } + } +} + +-------------------------------------------------------------------------------- + +(source_file + (shape (identifier) (block + (shape (identifier) (block + (shape (identifier) (block + (shape (identifier)) + )) + )) + )) +)