diff --git a/grammar.js b/grammar.js index 787f484..747c955 100644 --- a/grammar.js +++ b/grammar.js @@ -15,13 +15,9 @@ const make_attr_delimited = (token_suffix) => { const make_attrs_delimited = (delim_open, delim_close, token_suffix) => { return ($) => seq( delim_open, - optional($._space_or_newline), - optional( - seq( - alias($[`_attr_delimited_${token_suffix}`], $.attr), - repeat(seq($._space_or_newline, alias($[`_attr_delimited_${token_suffix}`], $.attr))), - ) - ), + repeat(seq( + optional($._space_or_newline), alias($[`_attr_delimited_${token_suffix}`], $.attr) + )), optional($._space_or_newline), delim_close ) @@ -134,7 +130,7 @@ module.exports = grammar({ $._attrs_plain, $._attrs_delimited ), - _attrs_plain: $ => repeat1($._attr_with_space), + _attrs_plain: $ => seq($._space, repeat1(seq(optional($._space), $.attr))), _attrs_delimited: $ => choice( $._attrs_delimited_p, $._attrs_delimited_s, @@ -152,7 +148,6 @@ module.exports = grammar({ field('assignment', choice($.attr_assignment, $.attr_assignment_noescape)), field('value', $.attr_value), ), - _attr_with_space: $ => seq($._space, $.attr), attr_name: $ => $._attr_name, _attr_name: $ => /[a-zA-Z0-9_-]+/, // TODO: very wrong attr_assignment: $ => /[ \t]*=[ \t]*/, @@ -305,7 +300,7 @@ module.exports = grammar({ }, conflicts: $ => [ - [$.attrs], + [$._attrs_plain], ], extras: $ => [] diff --git a/src/grammar.json b/src/grammar.json index e594729..3674fba 100644 --- a/src/grammar.json +++ b/src/grammar.json @@ -382,11 +382,37 @@ ] }, "_attrs_plain": { - "type": "REPEAT1", - "content": { - "type": "SYMBOL", - "name": "_attr_with_space" - } + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_space" + }, + { + "type": "REPEAT1", + "content": { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_space" + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "SYMBOL", + "name": "attr" + } + ] + } + } + ] }, "_attrs_delimited": { "type": "CHOICE", @@ -413,59 +439,33 @@ "value": "(" }, { - "type": "CHOICE", - "members": [ - { - "type": "SYMBOL", - "name": "_space_or_newline" - }, - { - "type": "BLANK" - } - ] - }, - { - "type": "CHOICE", - "members": [ - { - "type": "SEQ", - "members": [ - { - "type": "ALIAS", - "content": { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { "type": "SYMBOL", - "name": "_attr_delimited_p" + "name": "_space_or_newline" }, - "named": true, - "value": "attr" - }, - { - "type": "REPEAT", - "content": { - "type": "SEQ", - "members": [ - { - "type": "SYMBOL", - "name": "_space_or_newline" - }, - { - "type": "ALIAS", - "content": { - "type": "SYMBOL", - "name": "_attr_delimited_p" - }, - "named": true, - "value": "attr" - } - ] + { + "type": "BLANK" } - } - ] - }, - { - "type": "BLANK" - } - ] + ] + }, + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_attr_delimited_p" + }, + "named": true, + "value": "attr" + } + ] + } }, { "type": "CHOICE", @@ -493,59 +493,33 @@ "value": "[" }, { - "type": "CHOICE", - "members": [ - { - "type": "SYMBOL", - "name": "_space_or_newline" - }, - { - "type": "BLANK" - } - ] - }, - { - "type": "CHOICE", - "members": [ - { - "type": "SEQ", - "members": [ - { - "type": "ALIAS", - "content": { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { "type": "SYMBOL", - "name": "_attr_delimited_s" + "name": "_space_or_newline" }, - "named": true, - "value": "attr" - }, - { - "type": "REPEAT", - "content": { - "type": "SEQ", - "members": [ - { - "type": "SYMBOL", - "name": "_space_or_newline" - }, - { - "type": "ALIAS", - "content": { - "type": "SYMBOL", - "name": "_attr_delimited_s" - }, - "named": true, - "value": "attr" - } - ] + { + "type": "BLANK" } - } - ] - }, - { - "type": "BLANK" - } - ] + ] + }, + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_attr_delimited_s" + }, + "named": true, + "value": "attr" + } + ] + } }, { "type": "CHOICE", @@ -573,59 +547,33 @@ "value": "{" }, { - "type": "CHOICE", - "members": [ - { - "type": "SYMBOL", - "name": "_space_or_newline" - }, - { - "type": "BLANK" - } - ] - }, - { - "type": "CHOICE", - "members": [ - { - "type": "SEQ", - "members": [ - { - "type": "ALIAS", - "content": { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { "type": "SYMBOL", - "name": "_attr_delimited_b" + "name": "_space_or_newline" }, - "named": true, - "value": "attr" - }, - { - "type": "REPEAT", - "content": { - "type": "SEQ", - "members": [ - { - "type": "SYMBOL", - "name": "_space_or_newline" - }, - { - "type": "ALIAS", - "content": { - "type": "SYMBOL", - "name": "_attr_delimited_b" - }, - "named": true, - "value": "attr" - } - ] + { + "type": "BLANK" } - } - ] - }, - { - "type": "BLANK" - } - ] + ] + }, + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_attr_delimited_b" + }, + "named": true, + "value": "attr" + } + ] + } }, { "type": "CHOICE", @@ -854,19 +802,6 @@ } ] }, - "_attr_with_space": { - "type": "SEQ", - "members": [ - { - "type": "SYMBOL", - "name": "_space" - }, - { - "type": "SYMBOL", - "name": "attr" - } - ] - }, "attr_name": { "type": "SYMBOL", "name": "_attr_name" @@ -1594,7 +1529,7 @@ "extras": [], "conflicts": [ [ - "attrs" + "_attrs_plain" ] ], "precedences": [], diff --git a/test/corpus/attributes.txt b/test/corpus/attributes.txt index 56c9f71..8083896 100644 --- a/test/corpus/attributes.txt +++ b/test/corpus/attributes.txt @@ -87,6 +87,27 @@ span title="example example --- +(source_file + (element + (tag_name) + (attrs + (attr + (attr_name) + (attr_assignment) + (attr_value)) + (attr + (attr_name) + (attr_assignment) + (attr_value))))) + +================================= +String attributes - without space +================================= + +a href="/"title="root" + +----- + (source_file (element (tag_name)