Fix for loop parsing and add @if/@for in attribute positions
This commit is contained in:
parent
6d858472b2
commit
b6a168a2b6
63
grammar.js
63
grammar.js
|
|
@ -9,7 +9,6 @@ module.exports = grammar({
|
|||
conflicts: ($) => [
|
||||
[$.expression, $.pattern],
|
||||
[$.rust_path, $.expression],
|
||||
[$.struct_pattern, $.expression],
|
||||
[$.html_element],
|
||||
[$.self_closing_function_tag, $.container_function_tag],
|
||||
],
|
||||
|
|
@ -120,12 +119,14 @@ module.exports = grammar({
|
|||
content_block: ($) => seq("{", repeat($.template_node), "}"),
|
||||
|
||||
// Template nodes
|
||||
// Note: template_control_flow must come before template_expression
|
||||
// to avoid @for/@if/@let being parsed as variable expressions
|
||||
template_node: ($) =>
|
||||
choice(
|
||||
$.html_element,
|
||||
$.function_tag,
|
||||
$.template_expression,
|
||||
$.template_control_flow,
|
||||
$.template_expression,
|
||||
$.comment,
|
||||
$.embedded_language,
|
||||
$.escape_at,
|
||||
|
|
@ -133,17 +134,18 @@ module.exports = grammar({
|
|||
),
|
||||
|
||||
// HTML elements
|
||||
// Note: attribute_or_control allows @if/@for in attribute position
|
||||
html_element: ($) =>
|
||||
choice(
|
||||
// Self-closing tag
|
||||
seq("<", $.tag_name, repeat($.html_attribute), "/", ">"),
|
||||
seq("<", $.tag_name, repeat($.attribute_or_control), "/", ">"),
|
||||
// Void elements (no closing tag needed)
|
||||
seq("<", $.tag_name, repeat($.html_attribute), ">"),
|
||||
seq("<", $.tag_name, repeat($.attribute_or_control), ">"),
|
||||
// Full element with content and closing tag
|
||||
seq(
|
||||
"<",
|
||||
$.tag_name,
|
||||
repeat($.html_attribute),
|
||||
repeat($.attribute_or_control),
|
||||
">",
|
||||
repeat($.template_node),
|
||||
"</",
|
||||
|
|
@ -152,11 +154,47 @@ module.exports = grammar({
|
|||
),
|
||||
),
|
||||
|
||||
// Allow either HTML attributes or control flow (@if/@for) in attribute position
|
||||
attribute_or_control: ($) =>
|
||||
choice(
|
||||
$.html_attribute,
|
||||
$.attribute_control_flow,
|
||||
),
|
||||
|
||||
// Control flow in attribute context - produces attributes conditionally
|
||||
attribute_control_flow: ($) =>
|
||||
choice(
|
||||
$.attribute_if_statement,
|
||||
$.attribute_for_loop,
|
||||
),
|
||||
|
||||
attribute_if_statement: ($) =>
|
||||
seq(
|
||||
"@if",
|
||||
$.expression,
|
||||
"{",
|
||||
repeat($.attribute_or_control),
|
||||
"}",
|
||||
optional(seq("else", "{", repeat($.attribute_or_control), "}")),
|
||||
),
|
||||
|
||||
attribute_for_loop: ($) =>
|
||||
seq(
|
||||
"@for",
|
||||
$.simple_pattern,
|
||||
"in",
|
||||
$.expression,
|
||||
"{",
|
||||
repeat($.attribute_or_control),
|
||||
"}",
|
||||
),
|
||||
|
||||
tag_name: ($) => /[a-zA-Z][a-zA-Z0-9-]*/,
|
||||
|
||||
html_attribute: ($) =>
|
||||
seq($.attribute_name, optional(seq("=", $.attribute_value))),
|
||||
|
||||
// Attribute names: allow @ for directives like @click, but not @if/@for/@let
|
||||
attribute_name: ($) => /[a-zA-Z_:@][a-zA-Z0-9_:.-]*/,
|
||||
|
||||
attribute_value: ($) =>
|
||||
|
|
@ -236,7 +274,7 @@ module.exports = grammar({
|
|||
seq(
|
||||
"@for",
|
||||
optional(seq($.identifier, ":")),
|
||||
$.pattern,
|
||||
$.simple_pattern,
|
||||
"in",
|
||||
$.expression,
|
||||
$.content_block,
|
||||
|
|
@ -312,14 +350,23 @@ module.exports = grammar({
|
|||
|
||||
unquoted_value: ($) => /[^\s>=\/]+/,
|
||||
|
||||
// Patterns
|
||||
// Patterns - full patterns used in match arms
|
||||
pattern: ($) =>
|
||||
choice(
|
||||
$.wildcard_pattern,
|
||||
$.tuple_pattern,
|
||||
$.struct_pattern,
|
||||
$.identifier_pattern,
|
||||
$.literal,
|
||||
$.identifier_pattern,
|
||||
),
|
||||
|
||||
// Simple pattern for for loops - no struct patterns to avoid ambiguity with content_block
|
||||
simple_pattern: ($) =>
|
||||
choice(
|
||||
$.wildcard_pattern,
|
||||
$.tuple_pattern,
|
||||
$.literal,
|
||||
$.identifier_pattern,
|
||||
),
|
||||
|
||||
wildcard_pattern: ($) => "_",
|
||||
|
|
|
|||
159
src/grammar.json
159
src/grammar.json
|
|
@ -607,11 +607,11 @@
|
|||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "template_expression"
|
||||
"name": "template_control_flow"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "template_control_flow"
|
||||
"name": "template_expression"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
|
|
@ -649,7 +649,7 @@
|
|||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "html_attribute"
|
||||
"name": "attribute_or_control"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -677,7 +677,7 @@
|
|||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "html_attribute"
|
||||
"name": "attribute_or_control"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -701,7 +701,7 @@
|
|||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "html_attribute"
|
||||
"name": "attribute_or_control"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -731,6 +731,128 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"attribute_or_control": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "html_attribute"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "attribute_control_flow"
|
||||
}
|
||||
]
|
||||
},
|
||||
"attribute_control_flow": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "attribute_if_statement"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "attribute_for_loop"
|
||||
}
|
||||
]
|
||||
},
|
||||
"attribute_if_statement": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "@if"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expression"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "{"
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "attribute_or_control"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "}"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "else"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "{"
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "attribute_or_control"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"attribute_for_loop": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "@for"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "simple_pattern"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "in"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expression"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "{"
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "attribute_or_control"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"tag_name": {
|
||||
"type": "PATTERN",
|
||||
"value": "[a-zA-Z][a-zA-Z0-9-]*"
|
||||
|
|
@ -1172,7 +1294,7 @@
|
|||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "pattern"
|
||||
"name": "simple_pattern"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
|
|
@ -1578,13 +1700,34 @@
|
|||
"type": "SYMBOL",
|
||||
"name": "struct_pattern"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "literal"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier_pattern"
|
||||
}
|
||||
]
|
||||
},
|
||||
"simple_pattern": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "wildcard_pattern"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "tuple_pattern"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "literal"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "identifier_pattern"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -2830,10 +2973,6 @@
|
|||
"rust_path",
|
||||
"expression"
|
||||
],
|
||||
[
|
||||
"struct_pattern",
|
||||
"expression"
|
||||
],
|
||||
[
|
||||
"html_element"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -67,6 +67,67 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "attribute_control_flow",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"children": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "attribute_for_loop",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "attribute_if_statement",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "attribute_for_loop",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"children": {
|
||||
"multiple": true,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "attribute_or_control",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "expression",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "simple_pattern",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "attribute_if_statement",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"children": {
|
||||
"multiple": true,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "attribute_or_control",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "expression",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "attribute_list",
|
||||
"named": true,
|
||||
|
|
@ -82,6 +143,25 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "attribute_or_control",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"children": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "attribute_control_flow",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "html_attribute",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "attribute_reference",
|
||||
"named": true,
|
||||
|
|
@ -542,7 +622,7 @@
|
|||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "pattern",
|
||||
"type": "simple_pattern",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
|
|
@ -718,7 +798,7 @@
|
|||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "html_attribute",
|
||||
"type": "attribute_or_control",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
|
|
@ -1230,6 +1310,33 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "simple_pattern",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"children": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "identifier_pattern",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "literal",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "tuple_pattern",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "wildcard_pattern",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "slice_type",
|
||||
"named": true,
|
||||
|
|
|
|||
34064
src/parser.c
34064
src/parser.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue