diff --git a/grammar.js b/grammar.js index f397ded..2c28145 100644 --- a/grammar.js +++ b/grammar.js @@ -111,9 +111,12 @@ module.exports = grammar({ seq( $.shape_key, optional( - seq( - optional(seq($._colon, optional($.label))), - optional(seq(alias($._new_shape_block, $.block))) + choice( + seq($._dot, alias($._style_attribute, $.attribute)), + seq( + optional(seq($._colon, optional($.label))), + optional(seq(alias($._new_shape_block, $.block))) + ) ) ) ) @@ -132,10 +135,7 @@ module.exports = grammar({ // attributes _new_root_attribute: ($) => - prec( - PREC.ATTRIBUTE, - seq(alias($._root_attr_key, $.attr_key), $._colon, $.attr_value) - ), + seq(alias($._root_attr_key, $.attr_key), $._colon, $.attr_value), _root_attr_key: ($) => choice( @@ -147,6 +147,7 @@ module.exports = grammar({ "label", "constraint", "icon", + "style", $._common_style_attr_key, $._text_attr_key ), @@ -169,6 +170,36 @@ module.exports = grammar({ ) ), + _style_attribute: ($) => + prec( + PREC.ATTRIBUTE, + seq( + alias("style", $.attr_key), + choice( + seq($._dot, alias($._inner_style_attribute, $.attribute)), + seq($._colon, alias($._style_attribute_block, $.block)) + ) + ) + ), + + _style_attribute_block: ($) => + seq( + "{", + repeat( + choice( + $._eol, + seq(alias($._inner_style_attribute, $.attribute), $._end) + ) + ), + "}" + ), + + _inner_style_attribute: ($) => + prec( + PREC.ATTRIBUTE, + seq(alias($._style_attr_key, $.attr_key), $._colon, $.attr_value) + ), + _style_attr_key: ($) => choice($._common_style_attr_key, "3d"), _common_style_attr_key: ($) => diff --git a/src/grammar.json b/src/grammar.json index e973575..48a9f29 100644 --- a/src/grammar.json +++ b/src/grammar.json @@ -316,56 +316,79 @@ "type": "CHOICE", "members": [ { - "type": "SEQ", + "type": "CHOICE", "members": [ { - "type": "CHOICE", + "type": "SEQ", "members": [ { - "type": "SEQ", - "members": [ - { - "type": "SYMBOL", - "name": "_colon" - }, - { - "type": "CHOICE", - "members": [ - { - "type": "SYMBOL", - "name": "label" - }, - { - "type": "BLANK" - } - ] - } - ] + "type": "SYMBOL", + "name": "_dot" }, { - "type": "BLANK" + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_style_attribute" + }, + "named": true, + "value": "attribute" } ] }, { - "type": "CHOICE", + "type": "SEQ", "members": [ { - "type": "SEQ", + "type": "CHOICE", "members": [ { - "type": "ALIAS", - "content": { - "type": "SYMBOL", - "name": "_new_shape_block" - }, - "named": true, - "value": "block" + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_colon" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "label" + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "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" + } + ] } ] } @@ -458,30 +481,26 @@ } }, "_new_root_attribute": { - "type": "PREC", - "value": 0, - "content": { - "type": "SEQ", - "members": [ - { - "type": "ALIAS", - "content": { - "type": "SYMBOL", - "name": "_root_attr_key" - }, - "named": true, - "value": "attr_key" - }, - { + "type": "SEQ", + "members": [ + { + "type": "ALIAS", + "content": { "type": "SYMBOL", - "name": "_colon" + "name": "_root_attr_key" }, - { - "type": "SYMBOL", - "name": "attr_value" - } - ] - } + "named": true, + "value": "attr_key" + }, + { + "type": "SYMBOL", + "name": "_colon" + }, + { + "type": "SYMBOL", + "name": "attr_value" + } + ] }, "_root_attr_key": { "type": "CHOICE", @@ -511,6 +530,10 @@ "type": "STRING", "value": "icon" }, + { + "type": "STRING", + "value": "style" + }, { "type": "SYMBOL", "name": "_common_style_attr_key" @@ -559,6 +582,134 @@ ] } }, + "_style_attribute": { + "type": "PREC", + "value": 0, + "content": { + "type": "SEQ", + "members": [ + { + "type": "ALIAS", + "content": { + "type": "STRING", + "value": "style" + }, + "named": true, + "value": "attr_key" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_dot" + }, + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_inner_style_attribute" + }, + "named": true, + "value": "attribute" + } + ] + }, + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_colon" + }, + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_style_attribute_block" + }, + "named": true, + "value": "block" + } + ] + } + ] + } + ] + } + }, + "_style_attribute_block": { + "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": "_inner_style_attribute" + }, + "named": true, + "value": "attribute" + }, + { + "type": "SYMBOL", + "name": "_end" + } + ] + } + ] + } + }, + { + "type": "STRING", + "value": "}" + } + ] + }, + "_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": "SYMBOL", + "name": "_colon" + }, + { + "type": "SYMBOL", + "name": "attr_value" + } + ] + } + }, "_style_attr_key": { "type": "CHOICE", "members": [ diff --git a/src/node-types.json b/src/node-types.json index 17e7779..fbd7a09 100644 --- a/src/node-types.json +++ b/src/node-types.json @@ -44,6 +44,18 @@ { "type": "attr_value", "named": true + }, + { + "type": "attribute", + "named": true + }, + { + "type": "block", + "named": true + }, + { + "type": "dot", + "named": true } ] } @@ -56,6 +68,10 @@ "multiple": true, "required": false, "types": [ + { + "type": "attribute", + "named": true + }, { "type": "connection", "named": true @@ -180,10 +196,18 @@ "multiple": true, "required": true, "types": [ + { + "type": "attribute", + "named": true + }, { "type": "block", "named": true }, + { + "type": "dot", + "named": true + }, { "type": "label", "named": true diff --git a/src/parser.c b/src/parser.c index adddd4d..aa657a9 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 660ef47..733a6ec 100644 --- a/test/corpus/attributes.txt +++ b/test/corpus/attributes.txt @@ -43,3 +43,74 @@ near: abc (attribute (attr_key (reserved)) (attr_value)) ) +================================================================================ +Style attribute +================================================================================ +foo.style.opacity: 5 +foo.style.fill: red +foo.style.stroke: red +foo.style.stroke-width: 5 +foo.style.stroke-dash: 4 +foo.style.border-radius: 1 +foo.style.font-color: red +foo.style.shadow: true +foo.style.multiple: true +foo.style.animated: true +foo.style.link: https://to + +-------------------------------------------------------------------------------- + +(source_file + (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) +) + +================================================================================ +Block style attributes +================================================================================ +foo.style: { + opacity: 5 + fill: red + stroke: red + stroke-width: 5 + stroke-dash: 4 + border-radius: 1 + font-color: red + shadow: true + multiple: true + animated: true + link: https://to +} + +-------------------------------------------------------------------------------- + +(source_file + (shape + (shape_key) (dot) + (attribute + (attr_key) + (block + (attribute (attr_key) (attr_value)) + (attribute (attr_key) (attr_value)) + (attribute (attr_key) (attr_value)) + (attribute (attr_key) (attr_value)) + (attribute (attr_key) (attr_value)) + (attribute (attr_key) (attr_value)) + (attribute (attr_key) (attr_value)) + (attribute (attr_key) (attr_value)) + (attribute (attr_key) (attr_value)) + (attribute (attr_key) (attr_value)) + (attribute (attr_key) (attr_value)) + ) + ) + ) +)