Add if/match expressions and fix import statement grammar

- Make 'as alias' optional in import_statement
- Add if_expression for if/else as values in @let statements
- Add match_expression for match as values
- Add macro_call support for format!(), vec![], etc.
- Use simple_pattern in let_statement to avoid conflicts with { }
- Reorder primary_expression to prioritize if/match over rust_path

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Michael Netshipise 2026-01-20 11:42:06 +02:00
parent ce7162699f
commit 6a0318bcb5
2 changed files with 390 additions and 14 deletions

View File

@ -41,8 +41,9 @@ module.exports = grammar({
),
// Template imports - supports both quoted "path" and unquoted /path
// The "as alias" part is optional
import_statement: ($) =>
seq(seq("@", "import"), choice($.string_literal, $.import_path), "as", $.identifier),
seq(seq("@", "import"), choice($.string_literal, $.import_path), optional(seq("as", $.identifier))),
import_path: ($) => /\/[^\s]+/,
@ -255,8 +256,9 @@ module.exports = grammar({
),
// Let binding: @let name = expression
// Use simple_pattern to avoid confusion with if/match expressions containing { }
let_statement: ($) =>
seq(seq("@", "let"), $.pattern, "=", $.expression),
seq(seq("@", "let"), $.simple_pattern, "=", $.expression),
if_statement: ($) =>
seq(
@ -407,16 +409,87 @@ module.exports = grammar({
primary_expression: ($) =>
choice(
// if/match expressions must come first to match the keywords before rust_path
$.if_expression,
$.match_expression,
$.literal,
$.rust_path,
$.macro_call,
$.method_call,
$.field_access,
$.index_access,
$.parenthesized_expression,
$.array_literal,
$.closure_expression,
// rust_path last as fallback for identifiers
$.rust_path,
),
// If expression (returns a value): if cond { expr } else { expr }
if_expression: ($) =>
prec.right(
10,
seq(
"if",
$.expression,
"{",
$.expression,
"}",
"else",
choice(
$.if_expression,
seq("{", $.expression, "}"),
),
),
),
// Match expression (returns a value): match expr { pat => expr, ... }
match_expression: ($) =>
prec.right(
10,
seq(
"match",
$.expression,
"{",
repeat($.expression_match_arm),
"}",
),
),
expression_match_arm: ($) =>
seq(
$.pattern,
optional(seq("if", $.expression)),
"=>",
$.expression,
optional(","),
),
// Rust macro calls: format!(), vec![], println!(), etc.
macro_call: ($) =>
prec(
5,
seq(
$.identifier,
"!",
choice(
seq("(", optional($.macro_args), ")"),
seq("[", optional($.macro_args), "]"),
seq("{", optional($.macro_args), "}"),
),
),
),
// Macro arguments
macro_args: ($) =>
seq(
$.macro_arg,
repeat(seq(",", $.macro_arg)),
optional(","),
),
// Macro argument - just use expression
macro_arg: ($) => $.expression,
method_call: ($) =>
prec.left(
3,

View File

@ -139,12 +139,25 @@
]
},
{
"type": "STRING",
"value": "as"
},
{
"type": "SYMBOL",
"name": "identifier"
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "as"
},
{
"type": "SYMBOL",
"name": "identifier"
}
]
},
{
"type": "BLANK"
}
]
}
]
},
@ -1249,7 +1262,7 @@
},
{
"type": "SYMBOL",
"name": "pattern"
"name": "simple_pattern"
},
{
"type": "STRING",
@ -2087,13 +2100,21 @@
"primary_expression": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "if_expression"
},
{
"type": "SYMBOL",
"name": "match_expression"
},
{
"type": "SYMBOL",
"name": "literal"
},
{
"type": "SYMBOL",
"name": "rust_path"
"name": "macro_call"
},
{
"type": "SYMBOL",
@ -2118,9 +2139,292 @@
{
"type": "SYMBOL",
"name": "closure_expression"
},
{
"type": "SYMBOL",
"name": "rust_path"
}
]
},
"if_expression": {
"type": "PREC_RIGHT",
"value": 10,
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "if"
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "STRING",
"value": "{"
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "STRING",
"value": "}"
},
{
"type": "STRING",
"value": "else"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "if_expression"
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "{"
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "STRING",
"value": "}"
}
]
}
]
}
]
}
},
"match_expression": {
"type": "PREC_RIGHT",
"value": 10,
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "match"
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "STRING",
"value": "{"
},
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "expression_match_arm"
}
},
{
"type": "STRING",
"value": "}"
}
]
}
},
"expression_match_arm": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "pattern"
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "if"
},
{
"type": "SYMBOL",
"name": "expression"
}
]
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "=>"
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "BLANK"
}
]
}
]
},
"macro_call": {
"type": "PREC",
"value": 5,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "STRING",
"value": "!"
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "("
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "macro_args"
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": ")"
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "["
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "macro_args"
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "]"
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "{"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "macro_args"
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "}"
}
]
}
]
}
]
}
},
"macro_args": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "macro_arg"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "SYMBOL",
"name": "macro_arg"
}
]
}
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "BLANK"
}
]
}
]
},
"macro_arg": {
"type": "SYMBOL",
"name": "expression"
},
"method_call": {
"type": "PREC_LEFT",
"value": 3,
@ -3367,6 +3671,5 @@
"precedences": [],
"externals": [],
"inline": [],
"supertypes": [],
"reserved": {}
"supertypes": []
}