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: ($) => [
|
conflicts: ($) => [
|
||||||
[$.expression, $.pattern],
|
[$.expression, $.pattern],
|
||||||
[$.rust_path, $.expression],
|
[$.rust_path, $.expression],
|
||||||
[$.struct_pattern, $.expression],
|
|
||||||
[$.html_element],
|
[$.html_element],
|
||||||
[$.self_closing_function_tag, $.container_function_tag],
|
[$.self_closing_function_tag, $.container_function_tag],
|
||||||
],
|
],
|
||||||
|
|
@ -120,12 +119,14 @@ module.exports = grammar({
|
||||||
content_block: ($) => seq("{", repeat($.template_node), "}"),
|
content_block: ($) => seq("{", repeat($.template_node), "}"),
|
||||||
|
|
||||||
// Template nodes
|
// Template nodes
|
||||||
|
// Note: template_control_flow must come before template_expression
|
||||||
|
// to avoid @for/@if/@let being parsed as variable expressions
|
||||||
template_node: ($) =>
|
template_node: ($) =>
|
||||||
choice(
|
choice(
|
||||||
$.html_element,
|
$.html_element,
|
||||||
$.function_tag,
|
$.function_tag,
|
||||||
$.template_expression,
|
|
||||||
$.template_control_flow,
|
$.template_control_flow,
|
||||||
|
$.template_expression,
|
||||||
$.comment,
|
$.comment,
|
||||||
$.embedded_language,
|
$.embedded_language,
|
||||||
$.escape_at,
|
$.escape_at,
|
||||||
|
|
@ -133,17 +134,18 @@ module.exports = grammar({
|
||||||
),
|
),
|
||||||
|
|
||||||
// HTML elements
|
// HTML elements
|
||||||
|
// Note: attribute_or_control allows @if/@for in attribute position
|
||||||
html_element: ($) =>
|
html_element: ($) =>
|
||||||
choice(
|
choice(
|
||||||
// Self-closing tag
|
// Self-closing tag
|
||||||
seq("<", $.tag_name, repeat($.html_attribute), "/", ">"),
|
seq("<", $.tag_name, repeat($.attribute_or_control), "/", ">"),
|
||||||
// Void elements (no closing tag needed)
|
// 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
|
// Full element with content and closing tag
|
||||||
seq(
|
seq(
|
||||||
"<",
|
"<",
|
||||||
$.tag_name,
|
$.tag_name,
|
||||||
repeat($.html_attribute),
|
repeat($.attribute_or_control),
|
||||||
">",
|
">",
|
||||||
repeat($.template_node),
|
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-]*/,
|
tag_name: ($) => /[a-zA-Z][a-zA-Z0-9-]*/,
|
||||||
|
|
||||||
html_attribute: ($) =>
|
html_attribute: ($) =>
|
||||||
seq($.attribute_name, optional(seq("=", $.attribute_value))),
|
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_name: ($) => /[a-zA-Z_:@][a-zA-Z0-9_:.-]*/,
|
||||||
|
|
||||||
attribute_value: ($) =>
|
attribute_value: ($) =>
|
||||||
|
|
@ -236,7 +274,7 @@ module.exports = grammar({
|
||||||
seq(
|
seq(
|
||||||
"@for",
|
"@for",
|
||||||
optional(seq($.identifier, ":")),
|
optional(seq($.identifier, ":")),
|
||||||
$.pattern,
|
$.simple_pattern,
|
||||||
"in",
|
"in",
|
||||||
$.expression,
|
$.expression,
|
||||||
$.content_block,
|
$.content_block,
|
||||||
|
|
@ -312,14 +350,23 @@ module.exports = grammar({
|
||||||
|
|
||||||
unquoted_value: ($) => /[^\s>=\/]+/,
|
unquoted_value: ($) => /[^\s>=\/]+/,
|
||||||
|
|
||||||
// Patterns
|
// Patterns - full patterns used in match arms
|
||||||
pattern: ($) =>
|
pattern: ($) =>
|
||||||
choice(
|
choice(
|
||||||
$.wildcard_pattern,
|
$.wildcard_pattern,
|
||||||
$.tuple_pattern,
|
$.tuple_pattern,
|
||||||
$.struct_pattern,
|
$.struct_pattern,
|
||||||
$.identifier_pattern,
|
|
||||||
$.literal,
|
$.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: ($) => "_",
|
wildcard_pattern: ($) => "_",
|
||||||
|
|
|
||||||
159
src/grammar.json
159
src/grammar.json
|
|
@ -607,11 +607,11 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "template_expression"
|
"name": "template_control_flow"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "template_control_flow"
|
"name": "template_expression"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
|
|
@ -649,7 +649,7 @@
|
||||||
"type": "REPEAT",
|
"type": "REPEAT",
|
||||||
"content": {
|
"content": {
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "html_attribute"
|
"name": "attribute_or_control"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -677,7 +677,7 @@
|
||||||
"type": "REPEAT",
|
"type": "REPEAT",
|
||||||
"content": {
|
"content": {
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "html_attribute"
|
"name": "attribute_or_control"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -701,7 +701,7 @@
|
||||||
"type": "REPEAT",
|
"type": "REPEAT",
|
||||||
"content": {
|
"content": {
|
||||||
"type": "SYMBOL",
|
"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": {
|
"tag_name": {
|
||||||
"type": "PATTERN",
|
"type": "PATTERN",
|
||||||
"value": "[a-zA-Z][a-zA-Z0-9-]*"
|
"value": "[a-zA-Z][a-zA-Z0-9-]*"
|
||||||
|
|
@ -1172,7 +1294,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "pattern"
|
"name": "simple_pattern"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
|
|
@ -1578,13 +1700,34 @@
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "struct_pattern"
|
"name": "struct_pattern"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "literal"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "identifier_pattern"
|
"name": "identifier_pattern"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"simple_pattern": {
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "wildcard_pattern"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "tuple_pattern"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "literal"
|
"name": "literal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "identifier_pattern"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -2830,10 +2973,6 @@
|
||||||
"rust_path",
|
"rust_path",
|
||||||
"expression"
|
"expression"
|
||||||
],
|
],
|
||||||
[
|
|
||||||
"struct_pattern",
|
|
||||||
"expression"
|
|
||||||
],
|
|
||||||
[
|
[
|
||||||
"html_element"
|
"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",
|
"type": "attribute_list",
|
||||||
"named": true,
|
"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",
|
"type": "attribute_reference",
|
||||||
"named": true,
|
"named": true,
|
||||||
|
|
@ -542,7 +622,7 @@
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "pattern",
|
"type": "simple_pattern",
|
||||||
"named": true
|
"named": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
@ -718,7 +798,7 @@
|
||||||
"required": true,
|
"required": true,
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "html_attribute",
|
"type": "attribute_or_control",
|
||||||
"named": true
|
"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",
|
"type": "slice_type",
|
||||||
"named": true,
|
"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