diff --git a/examples/chess.d2 b/examples/chess.d2 index 8c2cedd..a1f4e36 100644 --- a/examples/chess.d2 +++ b/examples/chess.d2 @@ -1,7 +1,12 @@ # Actors hans: Hans Niemann -defendants: { +defendants: |md + # Defendants + + hello world +| { + shape: text mc: Magnus Carlsen playmagnus: Play Magnus Group chesscom: Chess.com diff --git a/grammar.js b/grammar.js index a5aa1ee..dcd8209 100644 --- a/grammar.js +++ b/grammar.js @@ -1,15 +1,3 @@ -// mkWrapCont :: string -> string -> ($ -> Rule) -> $ -> Rule -const mkWrapCont = (start, end) => (getRule) => ($) => - seq( - start, - repeat(choice($._eol, seq(getRule($), $._end))), - optional(seq(getRule($), optional($._end))), - end - ); - -const mkBlock = mkWrapCont("{", "}"); -const mkList = mkWrapCont("[", "]"); - const PREC = { COMMENT: -2, EOL: -1, @@ -25,6 +13,28 @@ const PREC = { ATTRIBUTE_KEY: 0, }; +// mkWrapCont :: string -> string -> ($ -> Rule) -> $ -> Rule +const mkWrapCont = (start, end) => (onDefinition) => ($) => + seq( + start, + repeat(choice($._eol, seq(onDefinition($), $._end))), + optional(seq(onDefinition($), optional($._end))), + end + ); +const mkBlock = mkWrapCont("{", "}"); +const mkList = mkWrapCont("[", "]"); + +// mkAlias :: ($ -> Rule) -> ($ -> Rule) -> $ -> Rule +const mkAlias = (onAlias) => (onValue) => ($) => alias(onValue($), onAlias($)); +const attrKeyAlias = mkAlias(($) => $.attr_key); +const attrAlias = mkAlias(($) => $.attribute); + +// mkAttrCont :: ($ -> Rule) -> ($ -> Rule) -> $ -> Rule +const mkAttrCont = (onValue) => (onKey) => ($) => + seq(onKey($), $._colon, onValue($)); +const mkBaseAttr = (onKey) => + mkAttrCont(($) => $.attr_value)(attrKeyAlias(onKey)); + module.exports = grammar({ name: "d2", @@ -49,6 +59,7 @@ module.exports = grammar({ [$._classes_block], [$._classes_item_block], [$.class_list], + [$._text_block_attrs], ], rules: { @@ -126,11 +137,9 @@ module.exports = grammar({ _classes_item_block: mkBlock(($) => $._classes_item_attribute), - _classes_item_attribute: ($) => - choice( - alias($._base_shape_attribute, $.attribute), - alias($._style_attribute, $.attribute) - ), + _classes_item_attribute: attrAlias(($) => + choice($._base_shape_attribute, $._style_attribute) + ), // containers @@ -164,7 +173,16 @@ module.exports = grammar({ optional( choice( seq($.dot, $._shape_attribute), - seq($._colon, choice($.label, $.text_block)) + seq( + $._colon, + choice( + $.label, + seq( + $.text_block, + optional(alias($._text_block_attrs, $.block)) + ) + ) + ) ) ) ) @@ -194,12 +212,13 @@ module.exports = grammar({ alias($._text_block_end, "|") ), + _text_block_attrs: mkBlock(attrAlias(($) => $._text_shape_attribute)), + language: ($) => /\w+/, // attributes - _root_attribute: ($) => - seq(alias($._root_attr_key, $.attr_key), $._colon, $.attr_value), + _root_attribute: mkBaseAttr(($) => $._root_attr_key), _root_attr_key: ($) => choice( @@ -220,21 +239,19 @@ module.exports = grammar({ ) ), - _shape_attribute: ($) => - alias( - choice($._class_attribute, $._base_shape_attribute, $._style_attribute), - $.attribute - ), + _shape_attribute: attrAlias(($) => + choice($._class_attribute, $._base_shape_attribute, $._style_attribute) + ), - _class_attribute: ($) => - seq($.keyword_class, $._colon, choice($.class_list, $._class_name)), + _class_attribute: mkAttrCont(($) => choice($.class_list, $._class_name))( + ($) => $.keyword_class + ), class_list: mkList(($) => $._class_name), _class_name: ($) => alias($.shape_key, $.class_name), - _base_shape_attribute: ($) => - seq(alias($._shape_attr_key, $.attr_key), $._colon, $.attr_value), + _base_shape_attribute: mkBaseAttr(($) => $._shape_attr_key), _shape_attr_key: ($) => prec( @@ -251,6 +268,7 @@ module.exports = grammar({ "icon", "width", "height", + $._text_attr_key, $._grid_attr_key ) ), @@ -267,15 +285,9 @@ module.exports = grammar({ ) ), - _style_attribute_block: mkBlock(($) => - alias($._inner_style_attribute, $.attribute) - ), + _style_attribute_block: mkBlock(attrAlias(($) => $._inner_style_attribute)), - _inner_style_attribute: ($) => - prec( - PREC.ATTRIBUTE, - seq(alias($._style_attr_key, $.attr_key), $._colon, $.attr_value) - ), + _inner_style_attribute: mkBaseAttr(($) => $._style_attr_key), _grid_attr_key: ($) => choice( @@ -311,13 +323,13 @@ module.exports = grammar({ "text-transform" ), + _text_shape_attribute: mkBaseAttr(($) => $._text_attr_key), + _text_attr_key: ($) => "near", - _connection_attribute: ($) => - choice( - alias($._connection_arrowhead_attribute, $.attribute), - alias($._style_attribute, $.attribute) - ), + _connection_attribute: attrAlias(($) => + choice($._connection_arrowhead_attribute, $._style_attribute) + ), _connection_arrowhead_attribute: ($) => seq( diff --git a/src/grammar.json b/src/grammar.json index 9ba9a9e..d8f6a17 100644 --- a/src/grammar.json +++ b/src/grammar.json @@ -566,27 +566,22 @@ ] }, "_classes_item_attribute": { - "type": "CHOICE", - "members": [ - { - "type": "ALIAS", - "content": { + "type": "ALIAS", + "content": { + "type": "CHOICE", + "members": [ + { "type": "SYMBOL", "name": "_base_shape_attribute" }, - "named": true, - "value": "attribute" - }, - { - "type": "ALIAS", - "content": { + { "type": "SYMBOL", "name": "_style_attribute" - }, - "named": true, - "value": "attribute" - } - ] + } + ] + }, + "named": true, + "value": "attribute" }, "container": { "type": "PREC", @@ -816,8 +811,30 @@ "name": "label" }, { - "type": "SYMBOL", - "name": "text_block" + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "text_block" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_text_block_attrs" + }, + "named": true, + "value": "block" + }, + { + "type": "BLANK" + } + ] + } + ] } ] } @@ -959,6 +976,83 @@ } ] }, + "_text_block_attrs": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "{" + }, + { + "type": "REPEAT", + "content": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_eol" + }, + { + "type": "SEQ", + "members": [ + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_text_shape_attribute" + }, + "named": true, + "value": "attribute" + }, + { + "type": "SYMBOL", + "name": "_end" + } + ] + } + ] + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_text_shape_attribute" + }, + "named": true, + "value": "attribute" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_end" + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": "}" + } + ] + }, "language": { "type": "PATTERN", "value": "\\w+" @@ -1224,6 +1318,10 @@ "type": "STRING", "value": "height" }, + { + "type": "SYMBOL", + "name": "_text_attr_key" + }, { "type": "SYMBOL", "name": "_grid_attr_key" @@ -1363,30 +1461,26 @@ ] }, "_inner_style_attribute": { - "type": "PREC", - "value": 0, - "content": { - "type": "SEQ", - "members": [ - { - "type": "ALIAS", - "content": { - "type": "SYMBOL", - "name": "_style_attr_key" - }, - "named": true, - "value": "attr_key" - }, - { + "type": "SEQ", + "members": [ + { + "type": "ALIAS", + "content": { "type": "SYMBOL", - "name": "_colon" + "name": "_style_attr_key" }, - { - "type": "SYMBOL", - "name": "attr_value" - } - ] - } + "named": true, + "value": "attr_key" + }, + { + "type": "SYMBOL", + "name": "_colon" + }, + { + "type": "SYMBOL", + "name": "attr_value" + } + ] }, "_grid_attr_key": { "type": "CHOICE", @@ -1507,33 +1601,50 @@ } ] }, - "_text_attr_key": { - "type": "STRING", - "value": "near" - }, - "_connection_attribute": { - "type": "CHOICE", + "_text_shape_attribute": { + "type": "SEQ", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", - "name": "_connection_arrowhead_attribute" + "name": "_text_attr_key" }, "named": true, - "value": "attribute" + "value": "attr_key" }, { - "type": "ALIAS", - "content": { - "type": "SYMBOL", - "name": "_style_attribute" - }, - "named": true, - "value": "attribute" + "type": "SYMBOL", + "name": "_colon" + }, + { + "type": "SYMBOL", + "name": "attr_value" } ] }, + "_text_attr_key": { + "type": "STRING", + "value": "near" + }, + "_connection_attribute": { + "type": "ALIAS", + "content": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_connection_arrowhead_attribute" + }, + { + "type": "SYMBOL", + "name": "_style_attribute" + } + ] + }, + "named": true, + "value": "attribute" + }, "_connection_arrowhead_attribute": { "type": "SEQ", "members": [ @@ -2055,6 +2166,9 @@ ], [ "class_list" + ], + [ + "_text_block_attrs" ] ], "precedences": [], diff --git a/src/node-types.json b/src/node-types.json index 06bca32..ed28446 100644 --- a/src/node-types.json +++ b/src/node-types.json @@ -357,6 +357,10 @@ "type": "attribute", "named": true }, + { + "type": "block", + "named": true + }, { "type": "dot", "named": true diff --git a/src/parser.c b/src/parser.c index b58392a..be8e37c 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 b753ef3..675efd8 100755 Binary files a/tree-sitter-d2.wasm and b/tree-sitter-d2.wasm differ