1443 lines
33 KiB
JavaScript
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()
|
|
)
|
|
}
|