tsl-devkit/lsp-server/test/tree_sitter_tsf/grammar.js

1549 lines
39 KiB
JavaScript

const kPrec = {
kIdentifier: -1, // 标识符
kIf: 0,
kElif: 1,
kExprOperator: 1, // @ &
kAssignment: 2, // := += -= /= *= ...
kTernary: 3, // ?:
kLogicalOr: 4, // or .||
kLogicalAnd: 5, // and .&&
kBitwiseOr: 6, // .|
kBitwiseXor: 7, // .^
kBitwiseAnd: 8, // .&
kComparsion: 9, // = .= <> .<> > .> <= .<= >= .>= like in is
kSet: 10, // union/2 intersect outersect minus
kMatrixConcat: 10, // :| |
kRange: 10, // -> 数列初始化
kAddSub: 11, // + -
kShift: 12, // shl rol shr ror
kTimes: 13, // * / \ % mod div
kMatrixTimes: 13, // :* :/ :\
kLogarithm: 14, // ~
kDerivative: 14, // ! 求导
kConcat: 14, // $
kSigned: 15, // ±
kBitwiseNot: 16, // .!
kLogicalNot: 16, // not .!!
kMatrixInverse: 16, // ! 矩阵求逆
kMatrixTranspose: 16, // ` 矩阵转置
kFunctionPointer: 16, // ## 函数指针
kPrefix: 17, // ++ --
kMatrixPower: 17, // :^
kPower: 17, // ^
kPostfix: 18, // ++ --
kCall: 18, // func()
kAttribute: 18, // obj.attr
kSubscript: 18, // a[] a[:] a[1:] a[:1,2]
kParenthesized: 19, // (expr)
kArray: 20,
};
const kSemicolon = ";";
module.exports = grammar({
name: "tsf",
word: ($) => $.identifier,
conflicts: ($) => [
[$._left_hand_side, $._primary_expression],
[$._tssql_select_expression, $._table_or_subquery],
[$.tslx_close_tag, $.tslx_expression_tag],
[$._assignable_expression, $.array_element],
],
inline: ($) => [$._statement],
extras: ($) => [/\s/, $.line_comment, $.block_comment, $.nested_comment, $.compiler_directive_statement],
rules: {
root: ($) => choice($.unit, repeat($._statement)),
_statement: ($) => choice($._simple_statement, $._compound_statement),
_simple_statement: ($) =>
choice(
$.var_statement,
$.static_statement,
$.global_statement,
$.const_statement,
$.assignment_statement,
$.expression_statement,
$.uses_statement,
$.break_statement,
$.continue_statement,
$.return_statement,
// $.inherited_statement,
),
_compound_statement: ($) =>
choice(
$.if_statement,
$._for_statement,
$.while_statement,
$.repeat_statement,
$.case_statement,
$.try_statement,
$.anonymous_function_statement,
$.function_declaration_statement,
$.function_definition_statement,
$.function_definition_with_overload_statement,
$.class_definition_statement,
$.external_method_statement,
$._conditional_compilation_statement,
$.compiler_directive_statement,
$.matrix_iteration_statement,
$._tslx_template_statement,
),
var_statement: ($) =>
seq(field("declaration", $.var_declaration), kSemicolon),
static_statement: ($) =>
seq(field("declaration", $.static_declaration), kSemicolon),
global_statement: ($) =>
seq(field("declaration", $.global_declaration), kSemicolon),
const_statement: ($) =>
seq(
kw("const"),
field("name", $.identifier),
optional($._type_clause),
"=",
field("value", $.expression),
kSemicolon,
),
var_declaration: ($) =>
seq(
kw("var"),
$._variable_declaration,
optional($._type_clause),
optional($._initial_value),
),
static_declaration: ($) =>
seq(
kw("static"),
$._variable_declaration,
optional($._type_clause),
optional($._initial_value),
),
global_declaration: ($) =>
seq(
kw("global"),
$._variable_declaration,
optional($._type_clause),
optional($._initial_value),
),
_initial_value: ($) =>
seq(":=", field("initial_value", $._right_hand_side)),
_variable_declaration: ($) => sep1(field("name", $.identifier), ","),
_type_clause: ($) => seq(":", field("type_name", $.type_name)),
type_name: (_) =>
token(
choice(
// array of xxx
seq("array", /\s+/, "of", /\s+/, /[_a-zA-Z][_a-zA-Z0-9_.]*/),
/[_a-zA-Z][_a-zA-Z0-9_.]*/,
),
),
assignment_statement: ($) =>
choice(
seq(
choice($.assignment_expression, $.augmented_assignment_expression),
kSemicolon,
),
seq(
field("left", $._left_hand_side),
field("operator", ":="),
field("right", $.anonymous_function_statement),
),
),
break_statement: (_) => seq(kw("break"), kSemicolon),
continue_statement: (_) => seq(kw("continue"), kSemicolon),
return_statement: ($) =>
seq(kw("return"), field("value", optional(choice($.expression))), kSemicolon),
// inherited_statement: ($) => seq($._inherited_expression, kSemicolon),
_built_in_expression: ($) =>
choice(
$.echo_expression,
$.raise_expression,
$.new_expression,
$.inherited_expression,
),
echo_expression: ($) =>
prec.left(1, seq(kw("echo"), sep1(field("argument", $.expression), ","))),
raise_expression: ($) => seq(kw("raise"), field("exception", $.expression)),
inherited_expression: ($) =>
prec.left(
0,
seq(kw("inherited"), field("class", optional($.expression))),
),
new_expression: ($) => seq(kw("new"), field("class", $.expression)),
expression_statement: ($) => seq($.expression, kSemicolon),
expression: ($) =>
choice(
$._operator_expression,
$._tssql_select_expression,
$._tssql_dml_expression,
$._primary_expression,
$._built_in_expression,
),
_operator_expression: ($) =>
choice(
$.expr_expression,
$.ternary_expression,
$.binary_expression,
$.unary_expression,
$.prefix_increment_expression,
$.prefix_decrement_expression,
$.postfix_increment_expression,
$.postfix_decrement_expression,
$.function_pointer_expression,
),
expr_expression: ($) =>
prec.right(
kPrec.kExprOperator,
seq(
field("operator", choice("@", "&")),
field("argument", $.expression),
),
),
assignment_expression: ($) =>
prec.left(
kPrec.kAssignment,
seq(
field("left", $._left_hand_side),
field("operator", ":="),
field("right", $._right_hand_side),
),
),
augmented_assignment_expression: ($) =>
prec.left(
kPrec.kAssignment,
seq(
field("left", $._left_hand_side),
field(
"operator",
choice(
"+=",
"-=",
"*=",
"/=",
"\\=",
"^=",
"~=",
"%=",
seq(kw("div"), "="),
"|=",
":|=",
"&=",
":*=",
":/=",
":\\=",
":^=",
"::=",
".|=",
".&=",
".||=",
".&&=",
".^=",
seq(kw("union"), "="),
seq(kw("union2"), "="),
seq(kw("intersect"), "="),
seq(kw("outersect"), "="),
seq(kw("minus"), "="),
),
),
field("right", $._right_hand_side),
),
),
_assignable_expression: ($) =>
choice(
$.expression,
$.assignment_expression,
$.augmented_assignment_expression,
),
ternary_expression: ($) =>
prec.left(
kPrec.kTernary,
seq(
field("condition", $.expression),
"?",
optional(field("consequence", $._assignable_expression)),
":",
field("alternative", $._assignable_expression),
),
),
binary_expression: ($) =>
choice(
$._logical_or_expression,
$._logical_and_expression,
$._bitwise_or_expression,
$._bitwise_and_expression,
$._bitwise_xor_expression,
$._shift_expression,
$._addition_expression,
$._multiplication_expression,
$._power_expression,
$._logarithm_expression,
$._matrix_multiplication_expression,
$._matrix_power_expression,
$._matrix_concatenation_expression,
$._range_expression,
$._comparison_expression,
$._set_operation_expression,
$._concatenation_expression,
),
_comparison_expression: ($) =>
prec.left(
kPrec.kComparsion,
seq(
field("left", $.expression),
field(
"operator",
choice(
"=",
"<>",
">",
">=",
"<",
"<=",
".=",
".<>",
".>",
".>=",
".<",
".<=",
$.in,
kw("is"),
kw("like"),
),
),
field("right", $.expression),
),
),
_logical_or_expression: ($) =>
prec.left(
kPrec.kLogicalOr,
seq(
field("left", $.expression),
field("operator", choice(kw("or"), ".||", "||")),
field("right", $.expression),
),
),
_logical_and_expression: ($) =>
prec.left(
kPrec.kLogicalAnd,
seq(
field("left", $.expression),
field("operator", choice(kw("and"), ".&&", "&&")),
field("right", $.expression),
),
),
_logical_not_expression: ($) =>
prec.left(
kPrec.kLogicalNot,
seq(
field("operator", choice(kw("not"), ".!!")),
field("argument", $.expression),
),
),
_bitwise_or_expression: ($) =>
prec.left(
kPrec.kBitwiseOr,
seq(
field("left", $.expression),
field("operator", ".|"),
field("right", $.expression),
),
),
_bitwise_and_expression: ($) =>
prec.left(
kPrec.kBitwiseAnd,
seq(
field("left", $.expression),
field("operator", ".&"),
field("right", $.expression),
),
),
_bitwise_xor_expression: ($) =>
prec.left(
kPrec.kBitwiseXor,
seq(
field("left", $.expression),
field("operator", ".^"),
field("right", $.expression),
),
),
_bitwise_not_expression: ($) =>
prec.left(
kPrec.kBitwiseNot,
seq(field("operator", ".!"), field("argument", $.expression)),
),
_shift_expression: ($) =>
prec.left(
kPrec.kShift,
seq(
field("left", $.expression),
field("operator", choice(kw("shl"), kw("rol"), kw("shr"), kw("ror"))),
field("right", $.expression),
),
),
_addition_expression: ($) =>
prec.left(
kPrec.kAddSub,
seq(
field("left", $.expression),
field("operator", choice("+", "-")),
field("right", $.expression),
),
),
_multiplication_expression: ($) =>
prec.left(
kPrec.kTimes,
seq(
field("left", $.expression),
field("operator", choice("*", "/", "\\", "%", kw("mod"), kw("div"))),
field("right", $.expression),
),
),
_power_expression: ($) =>
prec.right(
kPrec.kPower,
seq(
field("left", $.expression),
field("operator", "^"),
field("right", $.expression),
),
),
_logarithm_expression: ($) =>
prec.left(
kPrec.kLogarithm,
seq(
field("left", $.expression),
field("operator", "~"),
field("right", $.expression),
),
),
_matrix_multiplication_expression: ($) =>
prec.left(
kPrec.kMatrixTimes,
seq(
field("left", $.expression),
field("operator", choice(":*", ":/", ":\\")),
field("right", $.expression),
),
),
_matrix_power_expression: ($) =>
prec.right(
kPrec.kMatrixPower,
seq(
field("left", $.expression),
field("operator", ":^"),
field("right", $.expression),
),
),
_matrix_concatenation_expression: ($) =>
prec.left(
kPrec.kMatrixConcat,
seq(
field("left", $.expression),
field("operator", choice(":|", "|")),
field("right", $.expression),
),
),
_range_expression: ($) =>
prec.left(
kPrec.kRange,
seq(
field("left", $.expression),
field("operator", "->"),
field("right", $.expression),
),
),
_matrix_transpose_expression: ($) =>
prec(
kPrec.kMatrixTranspose,
seq(field("operator", "`"), field("argument", $.expression)),
),
_set_operation_expression: ($) =>
prec.left(
kPrec.kSet,
seq(
field("left", $.expression),
field(
"operator",
choice(
kw("union"),
kw("union2"),
kw("intersect"),
kw("outersect"),
kw("minus"),
),
),
field("right", $.expression),
),
),
_concatenation_expression: ($) =>
prec.left(
kPrec.kConcat,
seq(
field("left", $.expression),
field("operator", "$"),
field("right", $.expression),
),
),
unary_expression: ($) =>
choice(
$._unary_plus_expression,
$._unary_minus_expression,
$._derivative_expression,
$._logical_not_expression,
$._bitwise_not_expression,
$._matrix_transpose_expression,
),
_unary_plus_expression: ($) =>
prec(
kPrec.kSigned,
seq(field("operator", "+"), field("argument", $.expression)),
),
_unary_minus_expression: ($) =>
prec(
kPrec.kSigned,
seq(field("operator", "-"), field("argument", $.expression)),
),
_derivative_expression: ($) =>
prec.left(
kPrec.kDerivative,
seq(field("operator", "!"), field("argument", $.expression)),
),
prefix_increment_expression: ($) =>
prec.right(
kPrec.kPrefix,
seq(field("operator", "++"), field("argument", $.expression)),
),
prefix_decrement_expression: ($) =>
prec.right(
kPrec.kPrefix,
seq(field("operator", "--"), field("argument", $.expression)),
),
postfix_increment_expression: ($) =>
prec.right(
kPrec.kPostfix,
seq(field("argument", $.expression), field("operator", "++")),
),
postfix_decrement_expression: ($) =>
prec.right(
kPrec.kPostfix,
seq(field("argument", $.expression), field("operator", "--")),
),
function_pointer_expression: ($) =>
prec(
kPrec.kFunctionPointer,
seq(field("operator", "##"), field("argument", $.expression)),
),
anonymous_function_expression: ($) =>
seq(
optional(kw("static")),
kw("function"),
$._parameter_signature,
optional(field("return_type", $._type_clause)),
optional(kSemicolon),
field("body", $.block_suite),
),
unpack_pattern: ($) => prec.dynamic(1, seq("[", $._unpack_vars, "]")),
_unpack_vars: ($) =>
seq(
field("name", $.identifier),
repeat1(seq(",", field("name", $.identifier))),
),
_left_hand_side: ($) =>
choice($._identifier_like, $.attribute, $.subscript, $.unpack_pattern),
_right_hand_side: ($) =>
choice(
$.expression,
$.assignment_expression,
$.augmented_assignment_expression,
),
_tssql_select_expression: ($) =>
choice(
$.select_expression,
$.sselect_expression,
$.vselect_expression,
$.mselect_expression,
),
_tssql_dml_expression: ($) =>
choice($.update_expression, $.delete_expression, $.insert_expression),
select_expression: ($) => seq(kw("select"), $._select_clause),
sselect_expression: ($) => seq(kw("sselect"), $._select_clause),
vselect_expression: ($) => seq(kw("vselect"), $._select_clause),
mselect_expression: ($) => seq(kw("mselect"), $._select_clause),
update_expression: ($) =>
seq(
kw("update"),
field("table", choice($.identifier, $.sqltable)),
kw("set"),
field("assignments", sep1($.update_assignment, ",")),
optional(field("where", $.where_clause)),
kw("end"),
),
delete_expression: ($) =>
prec.right(
1,
seq(
kw("delete"),
kw("from"),
field("table", choice($.identifier, $.sqltable)),
optional(field("where", $.where_clause)),
),
),
insert_expression: ($) =>
prec.right(
1,
seq(
kw("insert"),
kw("into"),
field("table", choice($.identifier, $.sqltable)),
optional($.insert_fields),
optional(choice($.values_clause, field("source", $.identifier))),
),
),
insert_fields: ($) =>
seq(kw("insertfields"), "(", sep1($.sql_field, ","), ")"),
values_clause: ($) => seq(kw("values"), "(", sep1($.expression, ","), ")"),
update_assignment: ($) =>
seq(
field("column", $._primary_expression),
"=",
field("value", $.expression),
),
_select_clause: ($) =>
seq(
optional(field("distinct", kw("distinct"))),
optional(field("drange", $.drange_clause)),
optional(field("columns", $.select_list)),
field("from", $.from_clause),
optional(field("where", $.where_clause)),
optional(field("group_by", $.group_by_clause)),
optional(field("order_by", $.order_by_clause)),
optional(field("having", $.having_clause)),
kw("end"),
),
drange_clause: ($) =>
seq(kw("drange"), "(", choice($.drange_to, $.drange_of), ")"),
drange_to: ($) =>
seq(field("start", $.expression), kw("to"), field("end", $.expression)),
drange_of: ($) =>
seq(field("part", $.expression), kw("of"), field("total", $.expression)),
select_list: ($) =>
seq($.select_list_item, repeat(seq(",", $.select_list_item))),
select_list_item: ($) => choice(prec(10, "*"), $.select_item),
select_item: ($) =>
seq(field("expression", $.expression), optional($.alias_clause)),
alias_clause: ($) => seq(kw("as"), choice(field("alias", $.string), $.nil)),
from_clause: ($) => seq(kw("from"), $.from_item),
from_item: ($) => choice($._table_or_subquery, $.join_clause, $.sqltable),
sqltable: ($) => seq(kw("sqltable"), $.expression, kw("of"), $.expression),
_table_or_subquery: ($) =>
choice($.expression, seq("(", $.select_expression, ")")),
table_name: ($) => $.identifier,
sql_field: ($) =>
choice(
$._sql_field_with_table, // ⚠️ 带表前缀的字段:[1].* 或 [1].["field"]
$._sql_field_simple, // ⚠️ 简单字段:["field"]
),
_sql_field_with_table: ($) =>
prec(
kPrec.kSubscript + 3,
seq(
"[",
field("table_index", $.number),
"]",
".",
choice(
"*",
seq(
"[",
field("field_name", choice($.string, $.number, $.identifier)),
"]",
),
),
),
),
// ⚠️ 简单的 SQL 字段或参数引用
_sql_field_simple: ($) =>
prec(
kPrec.kSubscript + 2,
seq(
"[",
field("ref", choice($.string, $.number, $.identifier, $.call)),
"]",
),
),
where_clause: ($) => seq(kw("where"), field("condition", $.expression)),
group_by_clause: ($) =>
seq(kw("group"), kw("by"), field("expressions", sep1($.expression, ","))),
order_by_clause: ($) =>
seq(
kw("order"),
kw("by"),
field("expressions", sep1($._order_by_item, ",")),
),
_order_by_item: ($) =>
seq(
field("expression", $.expression),
optional(field("direction", choice(kw("asc"), kw("desc")))),
),
having_clause: ($) => seq(kw("having"), field("condition", $.expression)),
join_clause: ($) =>
prec.left(1, seq($._table_or_subquery, repeat1($._join_part))),
_join_part: ($) =>
seq(
field("join_type", $.join_type),
field("right", $._table_or_subquery),
optional(field("condition", choice($.on_condition, $.with_condition))),
),
join_type: (_) =>
choice(
kw("join"),
seq(kw("left"), kw("join")),
seq(kw("right"), kw("join")),
seq(kw("full"), kw("join")),
seq(kw("cross"), kw("join")),
",", // comma join
),
on_condition: ($) => seq(kw("on"), field("condition", $.expression)),
with_condition: ($) =>
seq(
kw("with"),
"(",
field("left_fields", sep1($.sql_field, ",")),
kw("on"),
field("right_fields", sep1($.sql_field, ",")),
")",
),
_primary_expression: ($) =>
choice(
$.attribute,
$.subscript,
$.call,
$.array,
$.literal,
$.reserved_keyword,
$._parenthesized_expression,
$._identifier_like,
$.sql_field,
),
// identifier: _ => /[a-zA-Z_][a-zA-Z0-9_]*/,
identifier: (_) => token(prec(kPrec.kIdentifier, /[a-zA-Z_][a-zA-Z0-9_]*/)),
literal: ($) =>
choice($.number, $.string, $.boolean, $.nil, $.infinity, $.ellipsis),
_identifier_like: ($) => choice($.identifier, $.type, $.do),
reserved_keyword: ($) => choice($.class, $.in),
type: (_) => kw("type"),
class: (_) => kw("class"),
in: (_) => kw("in"),
do: (_) => kw("do"),
number: (_) =>
token(
choice(
/0[xX][0-9a-fA-F]+/,
/0[bB][01]+/,
/0[oO][0-7]+/,
/[+-]?\d+\.\d*(?:[eE][+-]?\d+)?/, // 123.456, 123., +123.
/[+-]?\.\d+(?:[eE][+-]?\d+)?/, // .456, +.456
/[+-]?\d+(?:[eE][+-]?\d+)?/, // 123, +123, 123e10
),
),
string: (_) =>
token(
choice(
seq(
'"',
repeat(
choice(
/[^"\\]/,
seq("\\", /./), // escape sequence
),
),
'"',
),
seq(
"'",
repeat(
choice(
/[^'\\]/,
seq("\\", /./), // escape sequence
),
),
"'",
),
),
),
escape_sequence: (_) => token(seq("\\", /./)),
boolean: ($) => choice($.true, $.false),
true: (_) => kw("true"),
false: (_) => kw("false"),
nil: (_) => kw("nil"),
infinity: ($) => choice($.minus_inf, $.plus_inf),
minus_inf: (_) => kw("-inf"),
plus_inf: (_) => kw("+inf"),
ellipsis: (_) => "...",
call: ($) =>
prec(
kPrec.kCall,
seq(
field("function", $._primary_expression),
"(",
optional(sep1(seq(optional(kw("const")), field("argument", $.argument)), ",")),
")",
),
),
attribute: ($) =>
prec(
kPrec.kAttribute,
seq(
field("object", choice($._primary_expression)),
".",
field("attribute", $.identifier),
),
),
subscript: ($) =>
prec.dynamic(
2,
prec(
kPrec.kSubscript,
seq(
field("value", $._primary_expression),
"[",
field("subscript", $._index_spec),
"]",
),
),
),
_parenthesized_expression: ($) =>
seq("(", optional($._assignable_expression), ")"),
array: ($) =>
prec(
kPrec.kArray,
seq(kw("array"), "(", optional($._array_elements), ")"),
),
argument: ($) =>
choice($.expression, $.named_argument, $.asterisk_argument),
named_argument: ($) =>
seq(field("name", $.identifier), ":", field("value", $.expression)),
asterisk_argument: (_) => "*",
_index_spec: ($) => choice($._multi_index, $._single_index),
_multi_index: ($) => seq($._index_item, repeat1(seq(",", $._index_item))),
_single_index: ($) => $._index_item,
_index_item: ($) =>
choice(
$.expression, // string, array都在里面
$.slice,
$.empty_slice,
),
empty_slice: (_) => ":",
slice: ($) =>
choice($.range_slice, $.start_slice, $.end_slice, $.step_slice),
range_slice: ($) => seq($.expression, ":", $.expression),
start_slice: ($) => seq($.expression, ":"),
end_slice: ($) => seq(":", $.expression),
step_slice: ($) => seq($.expression, ":", $.expression, ":", $.expression),
_array_elements: ($) => seq(sep1($.array_element, ","), optional(",")),
array_element: ($) =>
choice($.key_value_pair, prec(1, $.parenthesized_array), $.expression),
key_value_pair: ($) =>
seq(
field("key", choice($.expression)),
":",
field("value", choice($.parenthesized_array, $.expression)),
),
parenthesized_array: ($) =>
prec(1, seq("(", sep1($.array_element, ","), optional(","), ")")),
line_comment: (_) => token(seq("//", /.*/)),
block_comment: (_) => token(seq("{", /([^$}][^}]*)?/, "}")),
nested_comment: (_) => token(/[(][*]([^*]*[*]+[^)*])*[^*]*[*]+[)]/),
if_statement: ($) =>
prec.right(
kPrec.kIf,
seq($.if_clause, repeat($.else_if_clause), optional($.else_clause)),
),
if_clause: ($) =>
seq(
kw("if"),
field("condition", $._assignable_expression),
kw("then"),
field("consequence", $._statement_suite),
),
else_if_clause: ($) =>
prec(
kPrec.kElif,
seq(
kw("else"),
kw("if"),
field("condition", $._assignable_expression),
kw("then"),
field("consequence", $._statement_suite),
),
),
else_clause: ($) =>
seq(kw("else"), field("consequence", $._statement_suite)),
_statement_suite: ($) =>
choice(seq($.block_suite, optional(kSemicolon)), $.single_suite),
single_suite: ($) => $._statement,
block_suite: ($) => seq(kw("begin"), repeat($._statement), kw("end")),
_for_statement: ($) => choice($.for_in_statement, $.for_to_statement),
for_in_statement: ($) =>
seq(
kw("for"),
field("key", $.identifier),
",",
field("value", $.identifier),
kw("in"),
field("collection", $.expression),
$.do,
field("body", $._statement_suite),
),
for_to_statement: ($) =>
seq(
kw("for"),
field("counter", $.identifier),
":=",
field("start", $.expression),
field("direction", choice(kw("to"), kw("downto"))),
field("end", $.expression),
optional(seq(kw("step"), field("step", $.expression))),
$.do,
field("body", $._statement_suite),
),
while_statement: ($) =>
seq(
kw("while"),
field("condition", $.expression),
$.do,
field("body", $._statement_suite),
),
repeat_statement: ($) =>
seq(
kw("repeat"),
field("body", repeat($.single_suite)),
kw("until"),
field("condition", $.expression),
kSemicolon,
),
case_statement: ($) =>
seq(
kw("case"),
field("discriminant", $.expression), // 被匹配的表达式
kw("of"),
field("branches", repeat($.case_branch)),
field("default", optional($.case_else)),
kw("end"),
optional(kSemicolon),
),
case_branch: ($) =>
seq($._case_values, ":", field("consequence", $._statement_suite)),
_case_values: ($) => sep1(field("value", $.expression), ","),
case_else: ($) => seq(kw("else"), field("consequence", $._statement_suite)),
try_statement: ($) =>
seq(
kw("try"),
optional(field("try_body", repeat1($._statement))),
kw("except"),
optional(field("except_body", repeat1($._statement))),
kw("end"),
optional(kSemicolon),
),
anonymous_function_statement: ($) =>
seq($.anonymous_function_expression, optional(kSemicolon)),
_function_header: ($) =>
seq(
kw("function"),
field("name", $.identifier),
$._parameter_signature,
optional(field("return_type", $._type_clause)),
),
function_declaration_statement: ($) => seq($._function_header, kSemicolon),
function_definition_statement: ($) =>
seq(
$._function_header,
optional(kSemicolon),
field("body", $.block_suite),
optional(kSemicolon),
),
function_definition_with_overload_statement: ($) =>
seq(
$._function_header,
kSemicolon,
kw("overload"),
kSemicolon,
field("body", $.block_suite),
optional(kSemicolon),
),
_parameter_signature: ($) =>
seq("(", optional(field("parameters", $.parameters)), ")"),
parameters: ($) => sep1(field("parameter", $.parameter), kSemicolon),
parameter: ($) =>
seq(
optional(choice(kw("var"), kw("out"))),
sep1(field("name", $.identifier), ","),
optional($._type_clause),
optional(seq("=", field("default", $.expression))),
),
class_definition_statement: ($) =>
seq(
$.type,
field("name", $.identifier),
"=",
$.class,
optional($._parent_list),
optional(field("body", $.class_body)),
kw("end"),
optional(kSemicolon),
),
_parent_list: ($) =>
seq(
"(",
optional(sep1(field("parent", choice($.identifier, $.attribute)), ",")),
")",
),
class_body: ($) => seq(optional($.uses_statement), repeat1($.class_member)),
class_member: ($) =>
choice(
field("access_modifier", $.access_modifier),
field("reference_modifier", $.reference_modifier),
choice(
$.variable_declaration,
$._method_declaration,
$.property_declaration,
),
),
access_modifier: (_) =>
choice(kw("public"), kw("protected"), kw("private")),
variable_declaration: ($) =>
seq(
optional($._reference_tag),
field("variable", $.member_variable),
kSemicolon,
),
_reference_tag: ($) =>
seq("[", field("ref_modifier", $.reference_modifier), "]"),
reference_modifier: (_) => choice(kw("weakref"), kw("autoref")),
member_variable: ($) =>
choice($.static_member_variable, $.field_member_variable),
static_member_variable: ($) =>
seq(
kw("static"),
$._variable_declaration,
optional($._type_clause),
optional(seq("=", field("initial_value", $._right_hand_side))),
),
field_member_variable: ($) =>
seq(
$._variable_declaration,
optional($._type_clause),
optional(seq("=", field("initial_value", $._right_hand_side))),
),
_method_declaration: ($) =>
choice(
$.method_declaration_only,
$.method_with_modifier,
$.method_with_implementation,
),
_method_header: ($) =>
seq(
optional($.class),
kw("function"),
field("name", $.method_name),
$._parameter_signature,
optional(field("return_type", $._type_clause)),
),
method_declaration_only: ($) => seq($._method_header, kSemicolon),
method_with_modifier: ($) =>
seq(
$._method_header,
kSemicolon,
field("modifier", $.method_modifier),
kSemicolon,
optional(seq(field("body", $.block_suite), optional(kSemicolon))),
),
method_with_implementation: ($) =>
seq(
$._method_header,
optional(kSemicolon),
field("body", $.block_suite),
optional(kSemicolon),
),
method_name: ($) =>
choice(
$._identifier_like,
// $.identifier,
$.operator_overload,
),
operator_overload: ($) =>
seq(kw("operator"), field("operator", $._overloadable_operator)),
_overloadable_operator: (_) => choice("+", "-", "*", "/", "\\", "[]"),
method_modifier: (_) =>
choice(kw("virtual"), kw("override"), kw("overload")),
property_declaration: ($) =>
seq(
kw("property"),
field("name", $.identifier),
optional($._type_clause),
optional($._property_index),
field("accessors", $.property_accessors),
kSemicolon,
),
_property_index: ($) =>
seq(kw("index"), field("index", choice($.number, $.string))),
property_accessors: ($) =>
choice(
$._read_only_accessor,
$._write_only_accessor,
$._read_write_accessor,
$._write_read_accessor,
),
_read_only_accessor: ($) => seq(kw("read"), field("read", $.identifier)),
_write_only_accessor: ($) => seq(kw("write"), field("write", $.identifier)),
_read_write_accessor: ($) =>
seq(
kw("read"),
field("read", $.identifier),
kw("write"),
field("write", $.identifier),
),
_write_read_accessor: ($) =>
seq(
kw("write"),
field("write", $.identifier),
kw("read"),
field("read", $.identifier),
),
// 类外方法实现
external_method_statement: ($) =>
choice($._modifier_method, $._operator_method, $._normal_method),
matrix_iteration_statement: ($) =>
seq(
field("target", $.expression),
"::",
field("body", $.block_suite),
optional(kSemicolon),
),
compiler_directive_statement: ($) =>
seq(
"{$",
field("name", $.identifier),
optional(field("switch", choice("+", "-"))),
"}",
),
_conditional_compilation_statement: $ => choice(
$.conditional_block_statement,
$.conditional_directive_statement,
),
conditional_directive_statement: $ => seq(
"{$",
choice(kw("define"), kw("undef")),
field('name', $.identifier),
"}"
),
conditional_block_statement: $ => seq(
"{$",
field('keyword', choice(kw("ifdef"), kw("ifndef"))),
field('name', $.identifier),
"}",
repeat(field("consequence", $._statement)),
optional(seq(
"{$",
kw("else"),
"}",
repeat(field('alternative', $._statement))
)),
"{$",
kw("endif"),
"}"
),
_tslx_template_statement: ($) =>
choice(
$.tslx_open_tag,
$.tslx_close_tag,
$.tslx_output_tag,
$.tslx_expression_tag,
$._tslx_html_tag,
),
tslx_open_tag: (_) => seq("<?", kw("tslx"), ">"),
tslx_close_tag: (_) => seq("<?", kw("tsl")),
tslx_expression_tag: ($) =>
seq("<?", kw("tsl"), repeat($._statement), "?>"),
tslx_output_tag: ($) => seq("<?=", sep1($.expression, ","), "?>"),
_tslx_html_tag: ($) =>
choice($.html_self_closing_tag, $.html_paired_tag, $.html_comment),
html_self_closing_tag: ($) =>
seq(
"<",
field("tag_name", $.html_tag_name),
repeat(field("attribute", $.html_attribute)),
"/>",
),
html_paired_tag: ($) =>
seq(
"<",
field("tag_name", $.html_tag_name),
repeat(field("attribute", $.html_attribute)),
">",
field("content", repeat($._tslx_template_statement)),
"</",
field("tag_name", $.html_tag_name),
">",
),
html_attribute: ($) =>
seq(
field("name", /[a-zA-Z:_][a-zA-Z0-9:_.-]*/),
"=",
field("value", $.string),
),
html_tag_name: (_) => /[a-zA-Z][a-zA-Z0-9-]*/,
html_comment: (_) =>
token(seq("<!--", repeat(choice(/[^-]/, /-[^-]/, /--[^>]/)), "-->")),
_modifier_method: ($) =>
seq(
optional($.class),
kw("function"),
$._qualified_method_name,
$._parameter_signature,
optional(field("return_type", $._type_clause)),
kSemicolon,
field("modifier", $.method_modifier),
kSemicolon,
field("body", $.block_suite),
optional(kSemicolon),
),
_operator_method: ($) =>
choice($._operator_overload_method, $._operator_method_with_modifier),
_normal_method: ($) =>
seq(
optional($.class),
kw("function"),
$._qualified_method_name,
$._parameter_signature,
optional(field("return_type", $._type_clause)),
optional(kSemicolon),
field("body", $.block_suite),
optional(kSemicolon),
),
_operator_overload_method: ($) =>
seq(
kw("function"),
kw("operator"),
field("class_name", $.identifier),
".",
field("operator", $._overloadable_operator),
$._parameter_signature,
optional(field("return_type", $._type_clause)),
optional(kSemicolon),
field("body", $.block_suite),
optional(kSemicolon),
),
_operator_method_with_modifier: ($) =>
seq(
kw("function"),
kw("operator"),
field("class_name", $.identifier),
".",
field("operator", $._overloadable_operator),
$._parameter_signature,
optional(field("return_type", $._type_clause)),
kSemicolon,
field("modifier", $.method_modifier),
kSemicolon,
field("body", $.block_suite),
optional(kSemicolon),
),
_qualified_method_name: ($) =>
seq(
field("class_name", $.identifier),
".",
field("method_name", $.identifier),
),
// unit
unit: ($) =>
seq(
kw("unit"),
field("name", $.identifier),
kSemicolon,
field("interface", $.interface_section),
field("implementation", $.implementation_section),
optional(field("initialization", $.initialization_section)),
optional(field("finalization", $.finalization_section)),
kw("end"),
".",
),
interface_section: ($) => seq(kw("interface"), repeat($._statement)),
implementation_section: ($) =>
seq(kw("implementation"), repeat($._statement)),
initialization_section: ($) =>
seq(kw("initialization"), repeat($._statement)),
finalization_section: ($) => seq(kw("finalization"), repeat($._statement)),
uses_statement: ($) =>
seq(kw("uses"), sep1(field("unit", $.identifier), ","), kSemicolon),
},
});
// 辅助函数:用分隔符分隔的序列
function sep1(rule, separator) {
return seq(rule, repeat(seq(separator, rule)));
}
function kw(keyword) {
const escapedKeyword = keyword.replace(/[.*+?^${}()|[\]\\-]/g, "\\$&");
return alias(new RustRegex(`(?i)${escapedKeyword}`), keyword.toLowerCase());
}