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 (左结合) kMultDiv: 13, // * / \ % mod div (左结合) kMatrixMultDiv: 13, // :* :/ :\ (左结合) kConcat: 14, // $ (左结合) kLogarithm: 14, // ~ (左结合) kUnaryPrefix: 15, // + - not .! .!! ## ! `(右结合) kPower: 16, // ^ :^ (右结合) kPrefixIncDec: 16, // ++ -- (右结合) kPostfixIncDec: 17, // ++ -- (左结合) kCall: 18, // func() (左结合) kAttribute: 18, // obj.attr (左结合) kSubscript: 18, // a[] a[:] a[1:] a[:1,2] (左结合) kParenthesized: 19, // (expr) kPrimary: 20, kArray: 20, }; const kSemicolon = ";"; module.exports = grammar({ name: "tsf", word: ($) => $.identifier, externals: ($) => [ $.tslx_content, $.tsl_statement_start_tag, // $.tsl_expression_start_tag, // $.tslx_end_tag, // 表示tslx块结束 ], extras: ($) => [/\s/, $.line_comment, $.block_comment, $.nested_comment], conflicts: ($) => [ [$.lvalue_expression, $._primary_expression], [$.lvalue_expression, $.expression], [$.select_expression, $.select], [$.sselect_expression, $.sselect], [$.vselect_expression, $.vselect], [$.insert_expression, $.insert], [$.update_expression, $.update], [$.delete_expression, $.delete], [$.function_declaration, $.function_definition], [$.parameter_mode, $._soft_keyword], ], inline: ($) => [$._statement], rules: { root: ($) => repeat($._statement), _statement: ($) => choice( $.unit_definition, $.class_definition, // type关键字可以二元运算 type = b $.external_method_definition, $.function_declaration, // unit里面 $.function_definition, $.tslx_block, $.compiler_directive_statement, $._conditional_compilation_statement, $.matrix_iteration_statement, $.if_statement, $._for_statement, $.while_statement, $.repeat_statement, $.case_statement, $.try_statement, $.break_statement, $.continue_statement, $.return_statement, $.block_statement, $.uses_statement, $.var_declaration, $.static_declaration, $.global_declaration, $.const_declaration, $.anonymous_function_statement, // 特殊--因为分号可选 $.expression_statement, $._empty_statement, ), unit_definition: ($) => 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)), class_definition: ($) => seq( kw("type"), field("name", $.identifier), "=", kw("class"), optional($._parent_list), optional(field("body", $.class_body)), kw("end"), ), external_method_definition: ($) => choice($.external_method, $.external_operator_method), _parent_list: ($) => seq( "(", optional( sep1( field("parent", choice($.identifier, $.attribute_expression)), ",", ), ), ")", ), class_body: ($) => seq(optional($.uses_statement), repeat1($.class_member)), class_member: ($) => choice( field("access_modifier", $.access_modifier), field("reference_modifier", $.reference_modifier), choice( $.method_declaration, $.method_definition, $.variable_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"), $._identifier_list, optional($._type_clause), optional(seq("=", field("value", $.expression))), ), field_member_variable: ($) => seq( $._identifier_list, optional($._type_clause), optional(seq("=", field("value", $.expression))), ), _method_header: ($) => seq( optional(kw("class")), choice(kw("function"), kw("procedure")), field("name", $.method_name), $._parameter_signature, optional(field("return_type", $._type_clause)), ), method_declaration: ($) => seq( $._method_header, kSemicolon, optional(seq(field("modifier", $.method_modifier), kSemicolon)), ), method_definition: ($) => seq( $._method_header, optional( seq(kSemicolon, field("modifier", $.method_modifier), kSemicolon), ), optional(kSemicolon), field("body", $.block_statement), optional(kSemicolon), ), method_name: ($) => choice($._identifier_or_keyword, $.operator_overload), external_method: ($) => seq( optional(kw("class")), choice(kw("function"), kw("procedure")), $._qualified_method_name, $._parameter_signature, optional(field("return_type", $._type_clause)), optional( seq(kSemicolon, field("modifier", $.method_modifier), kSemicolon), ), optional(kSemicolon), field("body", $.block_statement), ), external_operator_method: ($) => seq( choice(kw("function"), kw("procedure")), kw("operator"), field("class_name", $.identifier), ".", field("operator", $._overloadable_operator), $._parameter_signature, optional(field("return_type", $._type_clause)), optional( seq(kSemicolon, field("modifier", $.method_modifier), kSemicolon), ), optional(kSemicolon), field("body", $.block_statement), ), _qualified_method_name: ($) => seq( field("class_name", $.identifier), ".", field("method_name", $._identifier_or_keyword), ), _identifier_or_keyword: ($) => choice($.identifier, $._soft_keyword), 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), ), _function_header: ($) => seq( choice(kw("function"), kw("procedure")), field("name", $.identifier), $._parameter_signature, optional(field("return_type", $._type_clause)), ), function_declaration: ($) => seq( $._function_header, kSemicolon, optional(seq(kw("overload"), kSemicolon)), ), function_definition: ($) => seq( $._function_header, choice( optional(kSemicolon), seq(kSemicolon, kw("overload"), repeat1(kSemicolon)), ), field("body", $.block_statement), ), _parameter_signature: ($) => seq("(", optional(field("parameters", $.parameters)), ")"), parameters: ($) => seq( field("parameter", $.parameter), repeat(seq(choice(",", kSemicolon), field("parameter", $.parameter))), optional(kSemicolon), ), parameter: ($) => seq( optional(field("mode", $.parameter_mode)), field("name", $.identifier), optional($._type_clause), optional(seq("=", field("default_value", $.expression))), ), parameter_mode: ($) => choice(kw("var"), kw("out"), $.in, kw("const")), // TSLX 块:可以包含文本、TSL 语句、TSL 表达式的混合内容 // ,必须对应才是tsl_statement 2. 必须对应才是tsl_expression 3. 如果遇到了与其对应,应该将 prec.right( seq( $.tslx_tag, repeat( choice( $.tslx_content, // 普通文本内容 $._tsl_statement_block, // $._tsl_expression_block, // ), ), $.tslx_end_tag, ), ), _tsl_statement_block: ($) => seq( $.tsl_statement_start_tag, repeat1($._statement), $.tsl_statement_end_tag, ), _tsl_expression_block: ($) => seq($.tsl_expression_start_tag, $.expression, $.tsl_expression_end_tag), tslx_tag: (_) => seq(""), 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"), "}", ), matrix_iteration_statement: ($) => seq( field("target", $.expression), "::", field("body", $.block_statement), ), if_statement: ($) => prec.right( kPrec.kIf, seq($.if_clause, repeat($.else_if_clause), optional($.else_clause)), ), if_clause: ($) => seq( kw("if"), field("condition", $.expression), kw("then"), field("consequence", $._statement), ), else_if_clause: ($) => prec( kPrec.kElif, seq( kw("else"), kw("if"), field("condition", $.expression), kw("then"), field("consequence", $._statement), ), ), else_clause: ($) => seq(kw("else"), field("consequence", $._statement)), _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), ), 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), ), while_statement: ($) => seq( kw("while"), field("condition", $.expression), $.do, field("body", $._statement), ), repeat_statement: ($) => seq( kw("repeat"), field("body", repeat($._statement)), 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"), ), case_branch: ($) => seq( $._case_values, ":", field("consequence", $._statement), optional(kSemicolon), ), _case_values: ($) => sep1(field("value", $.expression), ","), case_else: ($) => seq(kw("else"), field("consequence", $._statement), optional(kSemicolon)), try_statement: ($) => seq( kw("try"), field("try_body", optional($.block_body)), kw("except"), field("except_body", optional($.block_body)), kw("end"), ), block_body: ($) => choice(seq(repeat1($._statement), optional($.expression)), $.expression), block_statement: ($) => seq(kw("begin"), optional(field("body", $.block_body)), kw("end")), // optional为了兼容begin end上一句可以没用分号 uses_statement: ($) => seq(kw("uses"), sep1(field("unit", $.identifier), ","), kSemicolon), break_statement: (_) => seq(kw("break"), kSemicolon), continue_statement: (_) => seq(kw("continue"), kSemicolon), return_statement: ($) => seq(kw("return"), field("value", optional($.expression)), kSemicolon), var_declaration: ($) => seq( kw("var"), $._identifier_list, optional($._type_clause), optional($._initializer), kSemicolon, ), static_declaration: ($) => seq( kw("static"), $._identifier_list, optional($._type_clause), optional($._initializer), kSemicolon, ), global_declaration: ($) => seq( kw("global"), $._identifier_list, optional($._type_clause), optional($._initializer), kSemicolon, ), const_declaration: ($) => seq( kw("const"), field("name", $.identifier), optional($._type_clause), "=", field("value", $.expression), kSemicolon, ), _identifier_list: ($) => sep1(field("name", $.identifier), ","), _initializer: ($) => seq(":=", field("initializer", $.expression)), _type_clause: ($) => seq(":", field("type", $.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_.]*/, ), ), anonymous_function_statement: ($) => seq( optional( seq( field("left", $.lvalue_expression), field("operator", $._assignment_operator), ), ), field("right", $.anonymous_function_expression), ), anonymous_function_expression: ($) => seq( optional(kw("static")), kw("function"), $._parameter_signature, optional(field("return_type", $._type_clause)), optional(kSemicolon), field("body", $.block_statement), ), _empty_statement: (_) => kSemicolon, expression_statement: ($) => seq($.expression, kSemicolon), expression: ($) => choice( $._tssql_select_expression, $._tssql_dml_expression, $.assignment_expression, $.ternary_expression, $.binary_expression, $.unary_expression, $.call_expression, $.subscript_expression, $.attribute_expression, $._primary_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", $.from_item), kw("set"), field("assignments", sep1($.update_assignment, ",")), optional(field("where", $.where_clause)), kw("end"), ), delete_expression: ($) => prec.right( seq( kw("delete"), kw("from"), field("table", $.delete_or_insert_item), optional(field("where", $.where_clause)), ), ), insert_expression: ($) => prec.right( seq( kw("insert"), optional(kw("into")), field("table", $.delete_or_insert_item), optional($.insert_fields), optional(choice($.values_clause, field("source", $.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: ($) => choice( seq(kw("drange"), "(", choice($.drange_to, $.drange_of), ")"), $.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_item, repeat(seq(",", $.select_item))), select_item: ($) => seq(field("expression", $.expression), optional($.alias_clause)), alias_clause: ($) => seq(kw("as"), $.expression), from_clause: ($) => seq(kw("from"), $.from_item), from_item: ($) => choice($.join_clause, $.sqltable, $._table_or_subquery), delete_or_insert_item: ($) => choice($.sqltable, $._table_or_subquery), join_clause: ($) => 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: ($) => prec.left( seq( kw("with"), "(", field("left_fields", sep1($.expression, ",")), kw("on"), field("right_fields", sep1($.expression, ",")), ")", ), ), sqltable: ($) => seq(kw("sqltable"), $.expression, kw("of"), $.expression), _table_or_subquery: ($) => choice( prec(0, $.expression), prec(1, seq("(", $.select_expression, ")")), ), 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)), column_reference: ($) => prec(kPrec.kPrimary, seq("[", field("value", $.expression), "]")), update_assignment: ($) => seq( field("column", $.lvalue_expression), "=", field("value", $.expression), ), insert_fields: ($) => seq(kw("insertfields"), $.parenthesized_expression), values_clause: ($) => seq(kw("values"), "(", sep1($.expression, ","), ")"), assignment_expression: ($) => prec.right( kPrec.kAssignment, seq( field("left", $.lvalue_expression), field("operator", $._assignment_operator), field("right", $.expression), ), ), lvalue_expression: ($) => choice( $._identifier_or_keyword, $.subscript_expression, $.attribute_expression, $.unpack_pattern, $.column_reference, $.sql_keyword, ), _assignment_operator: (_) => choice( ":=", "+=", "-=", "*=", "/=", "\\=", "^=", "~=", "%=", seq(kw("div"), "="), "|=", ":|=", "&=", ":*=", ":/=", ":\\=", ":^=", "::=", ".|=", ".&=", ".||=", ".&&=", ".^=", seq(kw("union"), "="), seq(kw("union2"), "="), seq(kw("intersect"), "="), seq(kw("outersect"), "="), seq(kw("minus"), "="), ), ternary_expression: ($) => prec.left( kPrec.kTernary, seq( field("condition", $.expression), "?", optional(field("consequence", $.expression)), ":", field("alternative", $.expression), ), ), binary_expression: ($) => { const operators = [ [kPrec.kLogicalOr, choice(kw("or"), ".||", "||")], [kPrec.kLogicalAnd, choice(kw("and"), ".&&", "&&")], [kPrec.kBitwiseOr, ".|"], [kPrec.kBitwiseXor, ".^"], [kPrec.kBitwiseAnd, ".&"], [ kPrec.kComparsion, choice( "=", ".=", "<>", ".<>", ">", ".>", "<", ".<", ">=", ".>=", "<=", ".<=", kw("like"), kw("in"), kw("is"), ), ], [ kPrec.kSet, choice( kw("union"), kw("union2"), kw("intersect"), kw("outersect"), kw("minus"), ), ], [kPrec.kRange, "->"], [kPrec.kMatrixConcat, choice("|", ":|")], [kPrec.kAddSub, choice("+", "-")], [kPrec.kShift, choice(kw("shl"), kw("shr"), kw("rol"), kw("ror"))], [kPrec.kMultDiv, choice("*", "/", "\\", "%", kw("mod"), kw("div"))], [kPrec.kMatrixMultDiv, choice(":*", ":/", ":\\")], [kPrec.kLogarithm, "~"], [kPrec.kConcat, "$"], ]; return choice( ...operators.map(([precedence, operator]) => prec.left( precedence, seq( field("left", $.expression), field("operator", operator), field("right", $.expression), ), ), ), // 幂运算(右结合) prec.right( kPrec.kPower, seq( field("left", $.expression), field("operator", choice("^", ":^")), field("right", $.expression), ), ), ); }, unary_expression: ($) => choice( $.unary_plus_expression, $.unary_minus_expression, $.prefix_increment_expression, $.prefix_decrement_expression, $.postfix_increment_expression, $.postfix_decrement_expression, $.logical_not_expression, $.bitwise_not_expression, $.derivative_expression, $.function_pointer_expression, $.matrix_transpose_expression, $.expr_operator_expression, ), unary_plus_expression: ($) => prec.right( kPrec.kUnaryPrefix, seq(field("operator", "+"), field("argument", $.expression)), ), unary_minus_expression: ($) => prec.right( kPrec.kUnaryPrefix, seq(field("operator", "-"), field("argument", $.expression)), ), prefix_increment_expression: ($) => prec.right( kPrec.kUnaryPrefix, seq(field("operator", "++"), field("argument", $.expression)), ), prefix_decrement_expression: ($) => prec.right( kPrec.kUnaryPrefix, seq(field("operator", "--"), field("argument", $.expression)), ), postfix_increment_expression: ($) => prec.right( kPrec.kUnaryPrefix, seq(field("argument", $.expression), field("operator", "++")), ), postfix_decrement_expression: ($) => prec.right( kPrec.kUnaryPrefix, seq(field("argument", $.expression), field("operator", "--")), ), logical_not_expression: ($) => prec.left( kPrec.kUnaryPrefix, seq( field("operator", choice(kw("not"), ".!!")), field("argument", $.expression), ), ), bitwise_not_expression: ($) => prec.left( kPrec.kUnaryPrefix, seq(field("operator", ".!"), field("argument", $.expression)), ), derivative_expression: ($) => prec.right( kPrec.kUnaryPrefix, seq(field("operator", "!"), field("argument", $.expression)), ), function_pointer_expression: ($) => prec.right( kPrec.kUnaryPrefix, seq(field("operator", "##"), field("argument", $.expression)), ), matrix_transpose_expression: ($) => prec.right( kPrec.kUnaryPrefix, seq(field("operator", "`"), field("argument", $.expression)), ), expr_operator_expression: ($) => prec.right( kPrec.kExprOperator, seq( field("operator", choice("@", "&")), field("argument", $.expression), ), ), call_expression: ($) => prec.left( kPrec.kCall, seq( field("callee", $.expression), "(", optional( sep1( field("argument", seq(optional($.parameter_mode), $.argument)), ",", ), ), ")", ), ), argument: ($) => choice($.expression, $.named_argument), named_argument: ($) => seq(field("name", $.identifier), ":", field("value", $.expression)), subscript_expression: ($) => prec.left( kPrec.kSubscript, seq( field("base", $.expression), "[", field("index", optional($.subscript_index)), "]", ), ), subscript_index: ($) => choice($.expression, $.slice, $.matrix_slice), slice: ($) => seq( optional(field("start", $.expression)), ":", optional(field("end", $.expression)), ), matrix_slice: ($) => seq( choice($.expression, $.slice), repeat1(seq(",", choice($.expression, $.slice))), ), attribute_expression: ($) => prec.left( kPrec.kAttribute, seq( field("object", $.expression), ".", field("attribute", $.expression), ), ), unpack_pattern: ($) => seq( "[", $.lvalue_expression, repeat1(seq(",", $.lvalue_expression)), "]", ), _primary_expression: ($) => choice( $._builtin_expression, $.array_expression, $.parenthesized_expression, $._identifier_or_keyword, $._literal, // 特殊符号 $.ellipsis, // 目前sql才用到 $.asterisk, $.column_reference, $.sql_keyword, ), _builtin_expression: ($) => choice( $.new_expression, $.echo_expression, $.raise_expression, $.inherited_expression, ), new_expression: ($) => seq(kw("new"), field("target", $.expression)), echo_expression: ($) => prec.left(seq(kw("echo"), sep1($.expression, ","))), raise_expression: ($) => seq(kw("raise"), field("exception", $.expression)), inherited_expression: ($) => prec.right( kPrec.kCall, seq(kw("inherited"), optional(field("class", $.call_expression))), ), array_expression: ($) => prec( kPrec.kArray, seq(kw("array"), "(", optional($._array_elements), ")"), ), _array_elements: ($) => seq(sep1($.array_element, ","), optional(",")), array_element: ($) => choice($.key_value_pair, $.expression), key_value_pair: ($) => seq(field("key", $.expression), ":", field("value", $.expression)), parenthesized_expression: ($) => prec( kPrec.kParenthesized, choice( seq("(", ")"), seq("(", sep1($._parenthesized_element, ","), optional(","), ")"), ), ), _parenthesized_element: ($) => choice($.key_value_pair, $.expression), _soft_keyword: ($) => choice( alias($.unit, $.identifier), alias($.class, $.identifier), alias($.in, $.identifier), alias($.type, $.identifier), alias($.do, $.identifier), alias($.select, $.identifier), alias($.sselect, $.identifier), alias($.vselect, $.identifier), alias($.update, $.identifier), alias($.insert, $.identifier), alias($.delete, $.identifier), ), unit: (_) => kw("unit"), class: (_) => kw("class"), in: (_) => kw("in"), type: (_) => kw("type"), do: (_) => kw("do"), select: (_) => kw("select"), sselect: (_) => kw("sselect"), vselect: (_) => kw("vselect"), update: (_) => kw("update"), insert: (_) => kw("insert"), delete: (_) => kw("delete"), sql_keyword: (_) => choice(kw("thisrow"), kw("thisrowindex")), identifier: (_) => token( prec( kPrec.kIdentifier, /[a-zA-Z_\u4e00-\u9fa5][\w\u4e00-\u9fa5]*/, // 使用Unicode中文范围 ), ), _literal: ($) => choice($.number, $.string, $.char, $.boolean, $.nil, $.nan, $.infinity), 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( "\\", choice( /./, // 任意单字符转义 (\n, \t, \", \\, 等) /x[0-9a-fA-F]{2}/, // \xHH /u[0-9a-fA-F]{4}/, // \uHHHH /U[0-9a-fA-F]{8}/, // \UHHHHHHHH ), ), ), ), '"', ), // 单引号字符串 seq( "'", repeat( choice( /[^'\\]+/, // 普通字符(允许换行) seq( "\\", choice( /./, /x[0-9a-fA-F]{2}/, /u[0-9a-fA-F]{4}/, /U[0-9a-fA-F]{8}/, ), ), ), ), "'", ), // L 字符串(保持原样) seq( "L", choice( seq("'", repeat(choice(/[^'\\]+/, /\\./)), "'"), seq('"', repeat(choice(/[^"\\]+/, /\\./)), '"'), ), ), ), ), boolean: ($) => choice($.true, $.false), char: (_) => token(seq("#", choice(/\d+/, /\$[0-9a-fA-F]+/))), true: (_) => kw("true"), false: (_) => kw("false"), nil: (_) => kw("nil"), nan: (_) => kw("nan"), infinity: ($) => choice($.minus_inf, $.plus_inf), minus_inf: (_) => kw("-inf"), plus_inf: (_) => kw("+inf"), ellipsis: (_) => "...", asterisk: (_) => "*", line_comment: (_) => token(seq("//", /.*/)), block_comment: (_) => token(seq("{", /([^$}][^}]*)?/, "}")), nested_comment: (_) => token(/[(][*]([^*]*[*]+[^)*])*[^*]*[*]+[)]/), }, }); 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()); }