tsl-devkit/lsp-server/test/tree-sitter-tsf/grammar.js

1443 lines
33 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],
],
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,
$.class_definition_statement,
$.external_method_statement,
$.matrix_iteration_statement,
),
var_statement: $ => seq(
$.var_declaration,
kSemicolon
),
static_statement: $ => seq(
$.static_declaration,
kSemicolon
),
global_statement: $ => seq(
$.global_declaration,
kSemicolon
),
const_statement: $ => seq(
kw('const'),
field('name', $.identifier),
optional($._type_annotation),
'=',
field('value', $.expression),
kSemicolon
),
var_declaration: $ => seq(
kw('var'),
$._variable_declaration,
optional($._type_annotation),
),
static_declaration: $ => seq(
kw('static'),
$._variable_declaration,
optional($._type_annotation),
),
global_declaration: $ => seq(
kw('global'),
$._variable_declaration,
optional($._type_annotation),
),
_variable_declaration: $ => sep1(field('name', $.identifier), ','),
_type_annotation: $ => seq(
':',
$.type_specification
),
type_specification: _ => field('type', /[_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'), optional($.expression), kSemicolon),
inherited_statement: $ => seq(
$.inherited_expression,
kSemicolon,
),
_built_in_expression: $ => choice(
$.echo_expression,
$.raise_expression,
$.new_expression,
),
echo_expression: $ => prec.left(1, seq(
kw('echo'),
sep1($.expression, ','),
)),
raise_expression: $ => seq(
kw('raise'),
$.expression,
),
inherited_expression: $ => seq(
kw('inherited'),
optional($.expression),
),
new_expression: $ => seq(
kw('new'),
$.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,
$.logical_or_expression,
$.logical_and_expression,
$.logical_not_expression,
$.comparison_expression,
$.bitwise_or_expression,
$.bitwise_and_expression,
$.bitwise_xor_expression,
$.bitwise_not_expression,
$.shift_expression,
$.addition_expression,
$.multiplication_expression,
$.power_expression,
$.logarithm_expression,
$.matrix_multiplication_expression,
$.matrix_power_expression,
$.matrix_concatenation_expression,
$.matrix_transpose_expression,
$.range_expression,
$.set_operation_expression,
$.concatenation_expression,
$.unary_plus_expression,
$.unary_minus_expression,
$.prefix_increment_expression,
$.prefix_decrement_expression,
$.postfix_increment_expression,
$.postfix_decrement_expression,
$.derivative_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),
)),
_with_assignment_expression: $ => choice(
$.expression,
$.assignment_expression,
$.augmented_assignment_expression,
),
ternary_expression: $ => prec.left(kPrec.kTernary, seq(
field('condition', $.expression),
'?',
optional(field('consequence', $._with_assignment_expression)),
':',
field('alternative', $._with_assignment_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),
)),
comparison_expression: $ => prec.left(kPrec.kComparsion, seq(
$.expression,
repeat1(seq(
field('operators', choice(
'=',
'<>',
'>',
'>=',
'<',
'<=',
'.=',
'.<>',
'.>',
'.>=',
'.<',
'.<=',
$.in,
kw('is'),
kw('like')
)),
$.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_plus_expression: $ => prec(kPrec.kSigned, seq(
field('operator', '+'),
field('argument', $.expression),
)),
unary_minus_expression: $ => prec(kPrec.kSigned, 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', '--'),
)),
derivative_expression: $ => prec.left(kPrec.kDerivative, seq(
field('operator', '!'),
field('argument', $.expression),
)),
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_annotation)),
optional(kSemicolon),
field('body', $.block_statement)
),
unpack_pattern: $ => prec.dynamic(1, seq(
'[',
$._unpack_vars,
']'
)),
_unpack_vars: $ => seq(
field('variable', $.identifier),
repeat1(seq(',', field('variable', $.identifier))),
),
_left_hand_side: $ => choice(
$._assignable_identifier,
$.var_declaration,
$.static_declaration,
$.global_declaration,
$.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,
$.parenthesized_expression,
$.call,
$.array,
$._literal,
$._assignable_identifier,
$._reserved_keyword,
$.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
),
_assignable_identifier: $ => 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),
'(',
field('arguments', optional($.argument_list)),
')'
)),
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('(', $._with_assignment_expression, ')'),
array: $ => prec(kPrec.kArray, seq(
kw('array'),
'(',
optional($._array_elements),
')'
)),
argument_list: $ => sep1($.argument, ','),
argument: $ => choice(
$.expression,
seq(
field('name', $.identifier),
':',
field('value', $.expression),
),
'*'
),
_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', $.expression),
':',
field('value', choice(
$.expression,
$.parenthesized_array
))
),
parenthesized_array: $ => prec(1, seq(
'(',
choice(
seq($.key_value_pair, ',', sep1($.key_value_pair, ',')),
$.key_value_pair,
seq($.expression, ',', sep1($.expression, ',')),
$.expression
),
optional(','),
')'
)),
line_comment: _ => token(seq('//', /.*/)),
block_comment:_ => token(seq(
'{',
/([^$}][^}]*)?/,
'}'
)),
nested_comment: _ => token(/[(][*]([^*]*[*]+[^)*])*[^*]*[*]+[)]/),
if_statement: $ => prec.right(kPrec.kIf, seq(
$.if_clause,
repeat(field('alternative', $.else_if_clause)),
optional(field('alternative', $.else_clause))
)),
if_clause: $ => seq(
kw('if'),
field('condition', $._with_assignment_expression),
kw('then'),
field('consequence', $._statement_suite)
),
else_if_clause: $ => prec(kPrec.kElif, seq(
kw('else'),
kw('if'),
field('condition', $._with_assignment_expression),
kw('then'),
field('consequence', $._statement_suite)
)),
else_clause: $ => seq(
kw('else'),
field('consequence', $._statement_suite)
),
_statement_suite: $ => choice(
seq($.block_statement, optional(kSemicolon)),
$.single_suite,
),
single_suite: $ => $._statement,
block_statement: $ => 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(
field('values', $.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('body', repeat1($._statement))),
kw('except'),
optional(field('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_annotation)),
kSemicolon
),
function_definition_statement: $ => seq(
kw('function'),
field('name', $.identifier),
$._parameter_signature,
field('return_type', optional($._type_annotation)),
optional(kSemicolon),
field('body', $.block_statement),
optional(kSemicolon),
),
_parameter_signature: $ => seq(
'(',
optional(field('parameters', $.parameter_list)),
')',
),
parameter_list: $ => sep1($.parameter, kSemicolon),
parameter: $ => seq(
optional(
choice(
field('var', kw('var')),
field('out', kw('out')),
)
),
field('names', sep1($.identifier, ',')),
optional(field('type', $._type_annotation)),
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(field('parents', sep1(choice($.identifier, $.attribute), ','))),
')',
),
class_body: $ => repeat1($.class_member),
class_member: $ => choice(
field('access_modifier', $.access_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('variables', $.member_variable),
kSemicolon,
),
_reference_tag: $ => seq(
'[',
field('ref_modifier', $.reference_modifier),
']'
),
reference_modifier: _ => choice(
kw('weakref'),
kw('autoref')
),
member_variable: $ => choice(
$.static_declaration,
$.nostatic_declaration,
),
nostatic_declaration: $ => seq(
$._variable_declaration,
optional($._type_annotation),
),
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_annotation)),
kSemicolon
),
method_with_modifier: $ => seq(
kw('function'),
field('name', $.method_name),
$._parameter_signature,
optional(field('return_type', $._type_annotation)),
kSemicolon,
field('modifier', $.method_modifier),
kSemicolon,
optional(seq(field('body', $.block_statement), optional(kSemicolon))),
),
method_with_implementation: $ => seq(
optional($.class),
kw('function'),
field('name', $.method_name),
$._parameter_signature,
optional(field('return_type', $._type_annotation)),
optional(kSemicolon),
field('body', $.block_statement),
optional(kSemicolon),
),
method_name: $ => choice(
$._assignable_identifier,
// $.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_annotation),
optional($._property_index),
field('accessors', $.property_accessors),
kSemicolon,
),
_property_index: $ => seq(
kw('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'),
$.identifier
),
write_only_accessor: $ => seq(
kw('write'),
$.identifier
),
read_write_accessor: $ => seq(
kw('read'),
$.identifier,
kw('write'),
$.identifier
),
write_read_accessor: $ => seq(
kw('write'),
$.identifier,
kw('read'),
$.identifier
),
// 类外方法实现
external_method_statement: $ => choice(
$.modifier_method,
$.operator_method,
$.normal_method,
),
matrix_iteration_statement: $ => seq(
field('target', $.expression),
'::',
field('body', $.block_statement),
optional(kSemicolon)
),
modifier_method: $ => seq(
kw('function'),
$._qualified_method_name,
$._parameter_signature,
optional(field('return_type', $._type_annotation)),
kSemicolon,
field('modifier', $.method_modifier),
kSemicolon,
field('body', $.block_statement),
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_annotation)),
optional(kSemicolon),
field('body', $.block_statement),
optional(kSemicolon),
),
_operator_method: $ => seq(
kw('function'),
kw('operator'),
field('class_name', $.identifier),
'.',
field('operator', $._overloadable_operator),
$._parameter_signature,
optional(field('return_type', $._type_annotation)),
optional(kSemicolon),
field('body', $.block_statement),
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_annotation)),
kSemicolon,
field('modifier', $.method_modifier),
kSemicolon,
field('body', $.block_statement),
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'),
optional(repeat($._statement)),
),
implementation_section: $ => seq(
kw('implementation'),
optional(repeat($._statement)),
),
initialization_section: $ => seq(
kw('initialization'),
optional(repeat($._statement)),
),
finalization_section: $ => seq(
kw('finalization'),
optional(repeat($._statement)),
),
uses_statement: $ => seq(
kw('uses'),
field('modules', sep1($.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()
)
}