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], 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, $.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($.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(choice($.expression, $._tssql_dml_expression), kSemicolon), expression: ($) => choice( $._operator_expression, $._tssql_select_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( kw("function"), $._parameter_signature, field("return_type", optional($._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", $.identifier), kw("set"), field("assignments", sep1($.update_assignment, ",")), optional(field("where", $.where_clause)), kw("end"), ), delete_expression: ($) => seq( kw("delete"), kw("from"), field("table", $.identifier), optional(field("where", $.where_clause)), ), insert_expression: ($) => seq( kw("insert"), kw("into"), field("table", $.identifier), optional($.insert_fields), 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), _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)), "]"), ), ), ), // ⚠️ 简单的 SQL 字段或参数引用 _sql_field_simple: ($) => prec( kPrec.kSubscript + 2, seq("[", field("ref", choice($.string, $.number)), "]"), ), 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(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, // $.spread_argument ), named_argument: ($) => seq(field("name", $.identifier), ":", field("value", $.expression)), // spread_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), $.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_declaration_statement: ($) => seq( kw("function"), field("name", $.identifier), $._parameter_signature, optional(field("return_type", $._type_clause)), kSemicolon, ), function_definition_statement: ($) => seq( kw("function"), field("name", $.identifier), $._parameter_signature, field("return_type", optional($._type_clause)), optional(kSemicolon), field("body", $.block_suite), optional(kSemicolon), ), function_definition_with_overload_statement: ($) => seq( kw("function"), field("name", $.identifier), $._parameter_signature, field("return_type", optional($._type_clause)), 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: ($) => repeat1($.class_member), class_member: ($) => choice( field("access_modifier", $.access_modifier), field("reference_modifier", $.reference_modifier), choice( $.variable_declaration, $._method_declaration, $.property_declaration, ), $.uses_statement, ), 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_declaration_only: ($) => seq( optional($.class), kw("function"), field("name", $.method_name), $._parameter_signature, optional(field("return_type", $._type_clause)), kSemicolon, ), method_with_modifier: ($) => seq( kw("function"), field("name", $.method_name), $._parameter_signature, optional(field("return_type", $._type_clause)), kSemicolon, field("modifier", $.method_modifier), kSemicolon, optional(seq(field("body", $.block_suite), optional(kSemicolon))), ), method_with_implementation: ($) => seq( optional($.class), kw("function"), field("name", $.method_name), $._parameter_signature, optional(field("return_type", $._type_clause)), 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), ), _tslx_template_statement: ($) => choice( $.tslx_open_tag, $.tslx_close_tag, $.tslx_output_tag, $.tslx_expression_tag, $._tslx_html_tag, ), tslx_open_tag: (_) => seq(""), tslx_close_tag: (_) => seq(" seq(""), tslx_output_tag: ($) => seq(""), _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)), "", ), 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("")), _modifier_method: ($) => seq( 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_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_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()); }