tree-sitter-c-sharp
Advanced tools
Comparing version 0.20.0 to 0.21.1
@@ -1,19 +0,7 @@ | ||
try { | ||
module.exports = require("../../build/Release/tree_sitter_c_sharp_binding"); | ||
} catch (error1) { | ||
if (error1.code !== 'MODULE_NOT_FOUND') { | ||
throw error1; | ||
} | ||
try { | ||
module.exports = require("../../build/Debug/tree_sitter_c_sharp_binding"); | ||
} catch (error2) { | ||
if (error2.code !== 'MODULE_NOT_FOUND') { | ||
throw error2; | ||
} | ||
throw error1 | ||
} | ||
} | ||
const root = require("path").join(__dirname, "..", ".."); | ||
module.exports = require("node-gyp-build")(root); | ||
try { | ||
module.exports.nodeTypeInfo = require("../../src/node-types.json"); | ||
} catch (_) {} |
2598
grammar.js
@@ -0,2 +1,14 @@ | ||
/** | ||
* @file C# grammar for tree-sitter | ||
* @author Max Brunsfeld <maxbrunsfeld@gmail.com> | ||
* @author Damien Guard <damieng@gmail.com> | ||
* @author Amaan Qureshi <amaanq12@gmail.com> | ||
* @license MIT | ||
*/ | ||
/// <reference types="tree-sitter-cli/dsl" /> | ||
// @ts-check | ||
const PREC = { | ||
GENERIC: 19, | ||
DOT: 18, | ||
@@ -19,6 +31,6 @@ INVOCATION: 18, | ||
OR: 6, | ||
LOGAND: 5, | ||
LOGOR: 4, | ||
LOGICAL_AND: 5, | ||
LOGICAL_OR: 4, | ||
COALESCING: 3, | ||
COND: 2, | ||
CONDITIONAL: 2, | ||
ASSIGN: 1, | ||
@@ -30,79 +42,106 @@ SELECT: 0, | ||
const stringEncoding = /(u|U)8/; | ||
module.exports = grammar({ | ||
name: 'c_sharp', | ||
extras: $ => [ | ||
$.comment, | ||
/[\s\u00A0\uFEFF\u3000]+/, | ||
$._preprocessor_call | ||
], | ||
supertypes: $ => [ | ||
$._declaration, | ||
$._expression, | ||
$._statement, | ||
$._type, | ||
], | ||
externals: $ => [ | ||
$._preproc_directive_end, | ||
], | ||
conflicts: $ => [ | ||
[$.block, $.initializer_expression], | ||
[$._simple_name, $.generic_name], | ||
[$._simple_name, $.constructor_declaration], | ||
[$._simple_name, $.type_parameter], | ||
[$.event_declaration, $.variable_declarator], | ||
[$.tuple_element, $.type_pattern], | ||
[$.tuple_element, $.using_variable_declarator], | ||
[$.tuple_element, $.declaration_expression], | ||
[$.nullable_type, $.as_expression], | ||
[$.nullable_type, $.is_expression, $.type_pattern], | ||
[$.nullable_type, $.as_expression, $.type_pattern], | ||
[$.tuple_pattern, $.parameter], | ||
[$.tuple_pattern, $._simple_name], | ||
[$.type_pattern, $.declaration_pattern], | ||
[$.type_pattern, $.declaration_pattern, $.recursive_pattern], | ||
[$.type_pattern, $.tuple_element], | ||
[$.lvalue_expression, $._name], | ||
[$.parameter, $.lvalue_expression], | ||
[$._name, $._expression], | ||
[$._simple_name, $.type_parameter], | ||
[$._simple_name, $.generic_name], | ||
[$._simple_name, $.constructor_declaration], | ||
[$._simple_name, $.name_colon], | ||
[$.type, $.attribute], | ||
[$.type, $.nullable_type], | ||
[$.type, $.nullable_type, $.array_creation_expression], | ||
[$.type, $._array_base_type], | ||
[$.type, $._array_base_type, $.array_creation_expression], | ||
[$.type, $.array_creation_expression], | ||
[$.type, $._pointer_base_type], | ||
[$.qualified_name, $.member_access_expression], | ||
[$.qualified_name, $.explicit_interface_specifier], | ||
[$.qualified_name, $.member_access_expression], | ||
[$._contextual_keywords, $.from_clause], | ||
[$._contextual_keywords, $.global], | ||
[$._contextual_keywords, $.accessor_declaration], | ||
[$._contextual_keywords, $.type_parameter_constraint], | ||
[$._array_base_type, $.stackalloc_expression], | ||
[$._type, $.array_creation_expression], | ||
[$._type, $.attribute], | ||
[$._type, $.stack_alloc_array_creation_expression], | ||
[$._type, $._nullable_base_type], | ||
[$._type, $._nullable_base_type, $.array_creation_expression], | ||
[$._nullable_base_type, $.stack_alloc_array_creation_expression], | ||
[$.constant_pattern, $.non_lvalue_expression], | ||
[$.constant_pattern, $._expression_statement_expression], | ||
[$.constant_pattern, $.lvalue_expression], | ||
[$.constant_pattern, $._name], | ||
[$.constant_pattern, $.lvalue_expression, $._name], | ||
[$.parameter, $.this_expression], | ||
[$.parameter, $._simple_name], | ||
[$._reserved_identifier, $.modifier], | ||
[$._reserved_identifier, $.scoped_type], | ||
[$._reserved_identifier, $.implicit_type], | ||
[$._reserved_identifier, $.from_clause], | ||
[$._reserved_identifier, $.implicit_type, $.var_pattern], | ||
[$._reserved_identifier, $.type_parameter_constraint], | ||
[$._reserved_identifier, $.parameter, $.scoped_type], | ||
[$._reserved_identifier, $.parameter], | ||
[$._simple_name, $.parameter], | ||
[$.tuple_element, $.parameter, $.declaration_expression], | ||
[$.parameter, $.tuple_element], | ||
[$.parameter, $.tuple_element, $.declaration_expression], | ||
[$.parameter, $._pattern], | ||
[$.parameter, $.declaration_expression], | ||
[$.tuple_element], | ||
[$.tuple_element, $.declaration_expression], | ||
[$.tuple_element, $.variable_declarator], | ||
[$.event_declaration, $.variable_declarator], | ||
], | ||
[$.array_creation_expression, $.element_access_expression], | ||
externals: $ => [ | ||
$._optional_semi, | ||
$.interpolation_regular_start, | ||
$.interpolation_verbatim_start, | ||
$.interpolation_raw_start, | ||
$.interpolation_start_quote, | ||
$.interpolation_end_quote, | ||
$.interpolation_open_brace, | ||
$.interpolation_close_brace, | ||
$.interpolation_string_content, | ||
], | ||
[$.constant_pattern, $._name], | ||
[$.constant_pattern, $._name, $._expression], | ||
[$.constant_pattern, $._expression], | ||
extras: $ => [ | ||
/[\s\u00A0\uFEFF\u3000]+/, | ||
$.comment, | ||
$.preproc_region, | ||
$.preproc_endregion, | ||
$.preproc_line, | ||
$.preproc_pragma, | ||
$.preproc_nullable, | ||
$.preproc_error, | ||
$.preproc_define, | ||
$.preproc_undef, | ||
], | ||
inline: $ => [ | ||
$.return_type, | ||
$._identifier_or_global, | ||
$._namespace_member_declaration, | ||
$._object_creation_type, | ||
$._nullable_base_type, | ||
$._parameter_type_with_modifiers, | ||
$._top_level_item_no_statement, | ||
], | ||
precedences: $ => [ | ||
[$._anonymous_object_member_declarator, $._simple_name], | ||
[$.block, $.initializer_expression], | ||
], | ||
supertypes: $ => [ | ||
$.declaration, | ||
$.expression, | ||
$.non_lvalue_expression, | ||
$.lvalue_expression, | ||
$.literal, | ||
$.statement, | ||
$.type, | ||
$.type_declaration, | ||
$.pattern, | ||
], | ||
word: $ => $._identifier_token, | ||
@@ -112,93 +151,68 @@ | ||
compilation_unit: $ => seq( | ||
repeat($.extern_alias_directive), | ||
repeat($.using_directive), | ||
repeat($.global_attribute_list), | ||
choice( | ||
seq(repeat($.global_statement), repeat($._namespace_member_declaration)), | ||
$.file_scoped_namespace_declaration | ||
) | ||
optional($.shebang_directive), | ||
repeat($._top_level_item), | ||
), | ||
global_statement: $ => $._statement, | ||
_top_level_item: $ => prec(2, choice( | ||
$._top_level_item_no_statement, | ||
$.global_statement, | ||
)), | ||
_declaration: $ => choice( | ||
$.class_declaration, | ||
$.constructor_declaration, | ||
$.conversion_operator_declaration, | ||
$.delegate_declaration, | ||
$.destructor_declaration, | ||
$.enum_declaration, | ||
$.event_declaration, | ||
$.event_field_declaration, | ||
$.field_declaration, | ||
$.indexer_declaration, | ||
$.interface_declaration, | ||
$.method_declaration, | ||
$.namespace_declaration, | ||
$.operator_declaration, | ||
$.property_declaration, | ||
$.record_declaration, | ||
$.record_struct_declaration, | ||
$.struct_declaration, | ||
_top_level_item_no_statement: $ => choice( | ||
$.extern_alias_directive, | ||
$.using_directive, | ||
$.global_attribute, | ||
alias($.preproc_if_in_top_level, $.preproc_if), | ||
$._namespace_member_declaration, | ||
$.file_scoped_namespace_declaration, | ||
), | ||
_namespace_member_declaration: $ => choice( | ||
$.namespace_declaration, | ||
$._type_declaration | ||
), | ||
global_statement: $ => prec(1, $.statement), | ||
_type_declaration: $ => choice( | ||
$.class_declaration, | ||
$.struct_declaration, | ||
$.interface_declaration, | ||
$.enum_declaration, | ||
$.delegate_declaration, | ||
$.record_declaration, | ||
$.record_struct_declaration | ||
), | ||
extern_alias_directive: $ => seq('extern', 'alias', field('name', $.identifier), ';'), | ||
extern_alias_directive: $ => seq('extern', 'alias', $.identifier, ';'), | ||
using_directive: $ => seq( | ||
optional('global'), | ||
'using', | ||
optional(choice( | ||
'static', | ||
$.name_equals | ||
)), | ||
$._name, | ||
';' | ||
choice( | ||
seq( | ||
optional('unsafe'), | ||
field('name', $.identifier), | ||
'=', | ||
$.type, | ||
), | ||
seq( | ||
optional('static'), | ||
optional('unsafe'), | ||
$._name, | ||
), | ||
), | ||
';', | ||
), | ||
name_equals: $ => prec(1, seq($._identifier_or_global, '=')), | ||
_name: $ => choice( | ||
$.alias_qualified_name, | ||
$.qualified_name, | ||
$._simple_name | ||
global_attribute: $ => seq( | ||
'[', | ||
choice('assembly', 'module'), | ||
':', | ||
commaSep1($.attribute), | ||
optional(','), | ||
']', | ||
), | ||
alias_qualified_name: $ => seq($._identifier_or_global, '::', $._simple_name), | ||
_simple_name: $ => choice( | ||
$.generic_name, | ||
$._identifier_or_global | ||
attribute: $ => seq( | ||
field('name', $._name), | ||
optional($.attribute_argument_list), | ||
), | ||
generic_name: $ => seq($.identifier, $.type_argument_list), | ||
attribute_argument_list: $ => prec(-1, seq( | ||
'(', | ||
commaSep($.attribute_argument), | ||
')', | ||
)), | ||
// Intentionally different from Roslyn to avoid non-matching | ||
// omitted_type_argument in a lot of unnecessary places. | ||
type_argument_list: $ => seq( | ||
'<', | ||
choice( | ||
repeat(','), | ||
commaSep1($._type), | ||
), | ||
'>' | ||
), | ||
attribute_argument: $ => prec(-1, seq( | ||
optional(seq($.identifier, choice(':', '='))), | ||
$.expression, | ||
)), | ||
qualified_name: $ => prec(PREC.DOT, seq($._name, '.', $._simple_name)), | ||
attribute_list: $ => seq( | ||
@@ -209,45 +223,139 @@ '[', | ||
optional(','), | ||
']' | ||
']', | ||
), | ||
attribute_target_specifier: $ => seq( | ||
attribute_target_specifier: _ => seq( | ||
choice('field', 'event', 'method', 'param', 'property', 'return', 'type'), | ||
':' | ||
':', | ||
), | ||
attribute: $ => seq( | ||
_namespace_member_declaration: $ => choice( | ||
$.namespace_declaration, | ||
$.type_declaration, | ||
), | ||
namespace_declaration: $ => seq( | ||
'namespace', | ||
field('name', $._name), | ||
optional($.attribute_argument_list) | ||
field('body', $.declaration_list), | ||
$._optional_semi, | ||
), | ||
attribute_argument_list: $ => seq( | ||
'(', | ||
commaSep($.attribute_argument), | ||
')' | ||
file_scoped_namespace_declaration: $ => seq( | ||
'namespace', | ||
field('name', $._name), | ||
';', | ||
), | ||
attribute_argument: $ => seq( | ||
optional(choice($.name_equals, $.name_colon)), | ||
$._expression | ||
type_declaration: $ => choice( | ||
$.class_declaration, | ||
$.struct_declaration, | ||
$.enum_declaration, | ||
$.interface_declaration, | ||
$.delegate_declaration, | ||
$.record_declaration, | ||
), | ||
global_attribute_list: $ => seq( | ||
'[', | ||
choice('assembly', 'module'), | ||
':', | ||
commaSep($.attribute), | ||
']' | ||
class_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
'class', | ||
field('name', $.identifier), | ||
optional($.type_parameter_list), | ||
optional($.parameter_list), | ||
optional($.base_list), | ||
repeat($.type_parameter_constraints_clause), | ||
field('body', $.declaration_list), | ||
$._optional_semi, | ||
), | ||
name_colon: $ => seq($._identifier_or_global, ':'), | ||
struct_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
optional('ref'), | ||
'struct', | ||
field('name', $.identifier), | ||
optional($.type_parameter_list), | ||
optional($.parameter_list), | ||
optional($.base_list), | ||
repeat($.type_parameter_constraints_clause), | ||
field('body', $.declaration_list), | ||
$._optional_semi, | ||
), | ||
event_field_declaration: $ => prec.dynamic(1, seq( | ||
enum_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
'event', | ||
$.variable_declaration, | ||
';' | ||
)), | ||
'enum', | ||
field('name', $.identifier), | ||
optional($.base_list), | ||
field('body', $.enum_member_declaration_list), | ||
$._optional_semi, | ||
), | ||
modifier: $ => prec.right(choice( | ||
enum_member_declaration_list: $ => seq( | ||
'{', | ||
commaSep(choice( | ||
$.enum_member_declaration, | ||
alias($.preproc_if_in_enum_member_declaration, $.preproc_if), | ||
)), | ||
optional(','), | ||
'}', | ||
), | ||
enum_member_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
field('name', $.identifier), | ||
optional(seq('=', field('value', $.expression))), | ||
), | ||
interface_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
'interface', | ||
field('name', $.identifier), | ||
field('type_parameters', optional($.type_parameter_list)), | ||
optional($.base_list), | ||
repeat($.type_parameter_constraints_clause), | ||
field('body', $.declaration_list), | ||
$._optional_semi, | ||
), | ||
delegate_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
'delegate', | ||
field('type', $.type), | ||
field('name', $.identifier), | ||
field('type_parameters', optional($.type_parameter_list)), | ||
field('parameters', $.parameter_list), | ||
repeat($.type_parameter_constraints_clause), | ||
';', | ||
), | ||
record_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
'record', | ||
optional(choice('class', 'struct')), | ||
field('name', $.identifier), | ||
optional($.type_parameter_list), | ||
optional($.parameter_list), | ||
optional(alias($.record_base, $.base_list)), | ||
repeat($.type_parameter_constraints_clause), | ||
choice(field('body', $.declaration_list), ';'), | ||
$._optional_semi, | ||
), | ||
record_base: $ => choice( | ||
seq(':', commaSep1($._name)), | ||
seq(':', $.primary_constructor_base_type, optional(seq(',', commaSep1($._name)))), | ||
), | ||
primary_constructor_base_type: $ => seq( | ||
field('type', $._name), | ||
$.argument_list, | ||
), | ||
modifier: _ => prec.right(choice( | ||
'abstract', | ||
@@ -257,2 +365,3 @@ 'async', | ||
'extern', | ||
'file', | ||
'fixed', | ||
@@ -268,3 +377,4 @@ 'internal', | ||
'required', | ||
prec(1, 'ref'), //make sure that 'ref' is treated as a modifier for local variable declarations instead of as a ref expression | ||
// 'ref', // `ref` as a modifier can only be used on struct declarations. Other than that it's a ref type or a ref parameter in a declaration. | ||
// 'scoped', // `scoped` is either part of a scoped type or a scoped parameter. Both of which are handled outside of `modifier`. | ||
'sealed', | ||
@@ -274,116 +384,120 @@ 'static', | ||
'virtual', | ||
'volatile' | ||
'volatile', | ||
)), | ||
variable_declaration: $ => seq( | ||
field('type', $._type), | ||
commaSep1($.variable_declarator) | ||
), | ||
type_parameter_list: $ => seq('<', commaSep1($.type_parameter), '>'), | ||
variable_declarator: $ => seq( | ||
choice($.identifier, $.tuple_pattern), | ||
optional($.bracketed_argument_list), | ||
optional($.equals_value_clause) | ||
type_parameter: $ => seq( | ||
repeat($.attribute_list), | ||
optional(choice('in', 'out')), | ||
field('name', $.identifier), | ||
), | ||
bracketed_argument_list: $ => seq( | ||
'[', | ||
commaSep1($.argument), | ||
']' | ||
base_list: $ => seq(':', commaSep1($.type)), | ||
type_parameter_constraints_clause: $ => seq( | ||
'where', | ||
$.identifier, | ||
':', | ||
commaSep1($.type_parameter_constraint), | ||
), | ||
tuple_pattern: $ => seq( | ||
'(', | ||
commaSep1(choice($.identifier, $.discard, $.tuple_pattern)), | ||
')' | ||
type_parameter_constraint: $ => choice( | ||
seq('class', optional('?')), | ||
'struct', | ||
'notnull', | ||
'unmanaged', | ||
$.constructor_constraint, | ||
field('type', $.type), | ||
), | ||
argument: $ => prec(1, seq( | ||
optional($.name_colon), | ||
optional(choice('ref', 'out', 'in')), | ||
choice( | ||
$._expression, | ||
$.declaration_expression | ||
) | ||
)), | ||
constructor_constraint: _ => seq('new', '(', ')'), | ||
equals_value_clause: $ => seq('=', $._expression), | ||
field_declaration: $ => seq( | ||
operator_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
$.variable_declaration, | ||
';' | ||
field('type', $.type), | ||
optional($.explicit_interface_specifier), | ||
'operator', | ||
optional('checked'), | ||
field('operator', choice( | ||
'!', | ||
'~', | ||
'++', | ||
'--', | ||
'true', | ||
'false', | ||
'+', '-', | ||
'*', '/', | ||
'%', '^', | ||
'|', '&', | ||
'<<', '>>', '>>>', | ||
'==', '!=', | ||
'>', '<', | ||
'>=', '<=', | ||
)), | ||
field('parameters', $.parameter_list), | ||
$._function_body, | ||
), | ||
constructor_declaration: $ => seq( | ||
conversion_operator_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
field('name', $.identifier), | ||
choice( | ||
'implicit', | ||
'explicit', | ||
), | ||
optional($.explicit_interface_specifier), | ||
'operator', | ||
optional('checked'), | ||
field('type', $.type), | ||
field('parameters', $.parameter_list), | ||
optional($.constructor_initializer), | ||
$._function_body | ||
$._function_body, | ||
), | ||
// Params varies quite a lot from grammar.txt as that handles neither 'out' nor 'params' or arrays... | ||
parameter_list: $ => seq( | ||
'(', | ||
optional($._formal_parameter_list), | ||
')' | ||
declaration_list: $ => seq( | ||
'{', | ||
repeat($.declaration), | ||
'}', | ||
), | ||
_formal_parameter_list: $ => commaSep1(choice( | ||
$.parameter, | ||
$._parameter_array | ||
)), | ||
parameter: $ => seq( | ||
repeat($.attribute_list), | ||
optional(alias(choice('ref', 'out', 'this', 'in'), $.parameter_modifier)), | ||
optional(field('type', $._type)), | ||
field('name', $.identifier), | ||
optional($.equals_value_clause) | ||
declaration: $ => choice( | ||
$.class_declaration, | ||
$.struct_declaration, | ||
$.enum_declaration, | ||
$.delegate_declaration, | ||
$.field_declaration, | ||
$.method_declaration, | ||
$.event_declaration, | ||
$.event_field_declaration, | ||
$.record_declaration, | ||
$.constructor_declaration, | ||
$.destructor_declaration, | ||
$.indexer_declaration, | ||
$.interface_declaration, | ||
$.namespace_declaration, | ||
$.operator_declaration, | ||
$.conversion_operator_declaration, | ||
$.property_declaration, | ||
$.using_directive, | ||
$.preproc_if, | ||
), | ||
parameter_modifier: $ => choice('ref', 'out', 'this', 'in'), | ||
_parameter_array: $ => seq( | ||
field_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
'params', | ||
choice($.array_type, $.nullable_type), | ||
field('name', $.identifier), | ||
repeat($.modifier), | ||
$.variable_declaration, | ||
';', | ||
), | ||
constructor_initializer: $ => seq( | ||
':', | ||
choice('base', 'this'), | ||
$.argument_list | ||
), | ||
argument_list: $ => seq('(', commaSep($.argument), ')'), | ||
block: $ => seq('{', repeat($._statement), '}'), | ||
arrow_expression_clause: $ => seq('=>', $._expression), | ||
conversion_operator_declaration: $ => seq( | ||
constructor_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
choice( | ||
'implicit', | ||
'explicit' | ||
), | ||
'operator', | ||
field('type', $._type), | ||
field('name', $.identifier), | ||
field('parameters', $.parameter_list), | ||
optional($.constructor_initializer), | ||
$._function_body, | ||
), | ||
_function_body: $ => choice( | ||
field('body', $.block), | ||
seq(field('body', $.arrow_expression_clause), ';'), | ||
';' // Only applies to interfaces | ||
), | ||
destructor_declaration: $ => seq( | ||
@@ -395,3 +509,3 @@ repeat($.attribute_list), | ||
field('parameters', $.parameter_list), | ||
$._function_body | ||
$._function_body, | ||
), | ||
@@ -402,3 +516,3 @@ | ||
repeat($.modifier), | ||
field('type', $.return_type), | ||
field('returns', $.type), | ||
optional($.explicit_interface_specifier), | ||
@@ -412,59 +526,2 @@ field('name', $.identifier), | ||
explicit_interface_specifier: $ => prec(PREC.DOT, seq($._name, '.')), | ||
type_parameter_list: $ => seq('<', commaSep1($.type_parameter), '>'), | ||
type_parameter: $ => seq( | ||
repeat($.attribute_list), | ||
optional(choice('in', 'out')), | ||
field('name', $.identifier), | ||
), | ||
type_parameter_constraints_clause: $ => seq( | ||
'where', | ||
field('target', $._identifier_or_global), | ||
':', | ||
field('constraints', commaSep1($.type_parameter_constraint)), | ||
), | ||
type_parameter_constraint: $ => choice( | ||
seq('class', optional('?')), | ||
'struct', | ||
'notnull', | ||
'unmanaged', | ||
$.constructor_constraint, | ||
$.type_constraint | ||
), | ||
constructor_constraint: $ => seq('new', '(', ')'), | ||
type_constraint: $ => field('type', $._type), | ||
operator_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
field('type', $._type), | ||
'operator', | ||
field('operator', $._overloadable_operator), | ||
field('parameters', $.parameter_list), | ||
$._function_body, | ||
), | ||
_overloadable_operator: $ => choice( | ||
'!', | ||
'~', | ||
'++', | ||
'--', | ||
'true', | ||
'false', | ||
'+', '-', | ||
'*', '/', | ||
'%', '^', | ||
'|', '&', | ||
'<<', '>>', | ||
'==', '!=', | ||
'>', '<', | ||
'>=', '<=' | ||
), | ||
event_declaration: $ => seq( | ||
@@ -474,3 +531,3 @@ repeat($.attribute_list), | ||
'event', | ||
field('type', $._type), | ||
field('type', $.type), | ||
optional($.explicit_interface_specifier), | ||
@@ -480,10 +537,18 @@ field('name', $.identifier), | ||
field('accessors', $.accessor_list), | ||
';' | ||
) | ||
';', | ||
), | ||
), | ||
event_field_declaration: $ => prec.dynamic(1, seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
'event', | ||
$.variable_declaration, | ||
';', | ||
)), | ||
accessor_list: $ => seq( | ||
'{', | ||
repeat($.accessor_declaration), | ||
'}' | ||
'}', | ||
), | ||
@@ -494,4 +559,4 @@ | ||
repeat($.modifier), | ||
choice('get', 'set', 'add', 'remove', 'init', $.identifier), | ||
$._function_body | ||
field('name', choice('get', 'set', 'add', 'remove', 'init', $.identifier)), | ||
$._function_body, | ||
), | ||
@@ -502,3 +567,3 @@ | ||
repeat($.modifier), | ||
field('type', $._type), | ||
field('type', $.type), | ||
optional($.explicit_interface_specifier), | ||
@@ -509,7 +574,11 @@ 'this', | ||
field('accessors', $.accessor_list), | ||
seq(field('value', $.arrow_expression_clause), ';') | ||
) | ||
seq(field('value', $.arrow_expression_clause), ';'), | ||
), | ||
), | ||
bracketed_parameter_list: $ => seq('[', $._formal_parameter_list, ']'), | ||
bracketed_parameter_list: $ => seq( | ||
'[', | ||
sep(choice($.parameter, $._parameter_array), ','), | ||
']', | ||
), | ||
@@ -519,3 +588,3 @@ property_declaration: $ => seq( | ||
repeat($.modifier), | ||
field('type', $._type), | ||
field('type', $.type), | ||
optional($.explicit_interface_specifier), | ||
@@ -526,150 +595,145 @@ field('name', $.identifier), | ||
field('accessors', $.accessor_list), | ||
optional(seq('=', field('value', $._expression), ';')) | ||
), // grammar.txt does not allow bodyless properties. | ||
optional(seq('=', field('value', $.expression), ';')), | ||
), | ||
seq( | ||
field('value', $.arrow_expression_clause), | ||
';' | ||
) | ||
';', | ||
), | ||
), | ||
), | ||
enum_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
'enum', | ||
field('name', $.identifier), | ||
field('bases', optional($.base_list)), | ||
field('body', $.enum_member_declaration_list), | ||
optional(';') | ||
explicit_interface_specifier: $ => prec(PREC.DOT, seq( | ||
$._name, | ||
'.', | ||
)), | ||
parameter_list: $ => seq( | ||
'(', | ||
sep(choice($.parameter, $._parameter_array), ','), | ||
')', | ||
), | ||
base_list: $ => seq(':', commaSep1($._type)), | ||
enum_member_declaration_list: $ => seq( | ||
'{', | ||
commaSep($.enum_member_declaration), | ||
optional(','), | ||
'}', | ||
_parameter_type_with_modifiers: $ => seq( | ||
repeat(prec.left(alias( | ||
choice('this', 'scoped', 'ref', 'out', 'in', 'readonly'), | ||
$.modifier, | ||
))), | ||
field('type', $.type), | ||
), | ||
enum_member_declaration: $ => seq( | ||
parameter: $ => seq( | ||
repeat($.attribute_list), | ||
optional($._parameter_type_with_modifiers), | ||
field('name', $.identifier), | ||
optional(seq('=', field('value', $._expression))) | ||
optional(seq('=', $.expression)), | ||
), | ||
class_declaration: $ => seq( | ||
_parameter_array: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
'class', | ||
'params', | ||
field('type', choice($.array_type, $.nullable_type)), | ||
field('name', $.identifier), | ||
field('type_parameters', optional($.type_parameter_list)), | ||
field('bases', optional($.base_list)), | ||
repeat($.type_parameter_constraints_clause), | ||
field('body', $.declaration_list), | ||
optional(';') | ||
), | ||
declaration_list: $ => seq( | ||
'{', | ||
repeat($._declaration), | ||
'}' | ||
constructor_initializer: $ => seq( | ||
':', | ||
choice('base', 'this'), | ||
$.argument_list, | ||
), | ||
interface_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
'interface', | ||
field('name', $.identifier), | ||
field('type_parameters', optional($.type_parameter_list)), | ||
field('bases', optional($.base_list)), | ||
repeat($.type_parameter_constraints_clause), | ||
field('body', $.declaration_list), | ||
optional(';') | ||
argument_list: $ => seq('(', commaSep($.argument), ')'), | ||
tuple_pattern: $ => seq( | ||
'(', | ||
commaSep1(choice( | ||
field('name', $.identifier), | ||
$.discard, | ||
$.tuple_pattern, | ||
)), | ||
')', | ||
), | ||
struct_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
'struct', | ||
field('name', $.identifier), | ||
field('type_parameters', optional($.type_parameter_list)), | ||
field('bases', optional($.base_list)), | ||
repeat($.type_parameter_constraints_clause), | ||
field('body', $.declaration_list), | ||
optional(';') | ||
argument: $ => prec(1, seq( | ||
optional(seq(field('name', $.identifier), ':')), | ||
optional(choice('ref', 'out', 'in')), | ||
choice( | ||
$.expression, | ||
$.declaration_expression, | ||
), | ||
)), | ||
block: $ => seq('{', repeat($.statement), '}'), | ||
arrow_expression_clause: $ => seq('=>', $.expression), | ||
_function_body: $ => choice( | ||
field('body', $.block), | ||
seq(field('body', $.arrow_expression_clause), ';'), | ||
';', | ||
), | ||
delegate_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
'delegate', | ||
field('type', $.return_type), | ||
field('name', $.identifier), | ||
field('type_parameters', optional($.type_parameter_list)), | ||
field('parameters', $.parameter_list), | ||
repeat($.type_parameter_constraints_clause), | ||
';' | ||
variable_declaration: $ => seq( | ||
field('type', $.type), | ||
commaSep1($.variable_declarator), | ||
), | ||
record_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
'record', | ||
optional('class'), | ||
field('name', $.identifier), | ||
field('type_parameters', optional($.type_parameter_list)), | ||
field('parameters', optional($.parameter_list)), | ||
field('bases', optional(alias($.record_base, $.base_list))), | ||
repeat($.type_parameter_constraints_clause), | ||
field('body', $._record_body), | ||
optional(';') | ||
using_variable_declaration: $ => seq( | ||
field('type', $.type), | ||
commaSep1(alias($.using_variable_declarator, $.variable_declarator)), | ||
), | ||
record_struct_declaration: $ => seq( | ||
repeat($.attribute_list), | ||
repeat($.modifier), | ||
'record', | ||
'struct', | ||
variable_declarator: $ => seq( | ||
choice(field('name', $.identifier), $.tuple_pattern), | ||
optional($.bracketed_argument_list), | ||
optional(seq('=', $.expression)), | ||
), | ||
using_variable_declarator: $ => seq( | ||
field('name', $.identifier), | ||
field('type_parameters', optional($.type_parameter_list)), | ||
field('parameters', optional($.parameter_list)), | ||
field('bases', optional(alias($.record_base, $.base_list))), | ||
repeat($.type_parameter_constraints_clause), | ||
field('body', $._record_body), | ||
optional(';') | ||
optional(seq('=', $.expression)), | ||
), | ||
record_base: $ => choice( | ||
seq(':', commaSep1($.identifier)), | ||
seq(':', $.primary_constructor_base_type, optional(seq(',', commaSep1($.identifier)))), | ||
bracketed_argument_list: $ => seq( | ||
'[', | ||
commaSep1($.argument), | ||
']', | ||
), | ||
primary_constructor_base_type: $ => seq( | ||
$.identifier, | ||
$.argument_list | ||
qualified_identifier: $ => sep1($.identifier, '.'), | ||
_name: $ => choice( | ||
$.alias_qualified_name, | ||
$.qualified_name, | ||
$._simple_name, | ||
), | ||
_record_body: $ => choice( | ||
$.declaration_list, | ||
';' | ||
alias_qualified_name: $ => seq( | ||
field('alias', $.identifier), | ||
'::', | ||
field('name', $._simple_name), | ||
), | ||
namespace_declaration: $ => seq( | ||
'namespace', | ||
field('name', $._name), | ||
field('body', $.declaration_list), | ||
optional(';') | ||
_simple_name: $ => choice( | ||
$.identifier, | ||
$.generic_name, | ||
), | ||
file_scoped_namespace_declaration: $ => seq( | ||
'namespace', | ||
field('name', $._name), | ||
';', | ||
repeat($.extern_alias_directive), | ||
repeat($.using_directive), | ||
repeat($._type_declaration) | ||
qualified_name: $ => prec(PREC.DOT, seq( | ||
field('qualifier', $._name), | ||
'.', | ||
field('name', $._simple_name), | ||
)), | ||
generic_name: $ => seq($.identifier, $.type_argument_list), | ||
type_argument_list: $ => seq( | ||
'<', | ||
choice( | ||
repeat(','), | ||
commaSep1($.type), | ||
), | ||
'>', | ||
), | ||
_type: $ => choice( | ||
type: $ => choice( | ||
$.implicit_type, | ||
@@ -683,63 +747,83 @@ $.array_type, | ||
$.tuple_type, | ||
$.ref_type, | ||
$.scoped_type, | ||
), | ||
implicit_type: $ => 'var', | ||
implicit_type: _ => prec.dynamic(1, 'var'), | ||
array_type: $ => prec(PREC.POSTFIX, seq( | ||
field('type', $._type), | ||
field('rank', $.array_rank_specifier) | ||
)), | ||
array_type: $ => seq( | ||
field('type', $._array_base_type), | ||
field('rank', $.array_rank_specifier), | ||
), | ||
// grammar.txt marks this non-optional and includes omitted_array_size_expression in | ||
// expression but we can't match empty rules. | ||
array_rank_specifier: $ => seq('[', commaSep(optional($._expression)), ']'), | ||
_array_base_type: $ => choice( | ||
$.array_type, | ||
$._name, | ||
$.nullable_type, | ||
$.pointer_type, | ||
$.function_pointer_type, | ||
$.predefined_type, | ||
$.tuple_type, | ||
), | ||
nullable_type: $ => seq($._nullable_base_type, '?'), | ||
array_rank_specifier: $ => seq( | ||
'[', | ||
commaSep(optional($.expression)), | ||
']', | ||
), | ||
nullable_type: $ => seq(field('type', $._nullable_base_type), '?'), | ||
_nullable_base_type: $ => choice( | ||
$.array_type, | ||
$._name, | ||
$.predefined_type, | ||
$.tuple_type, | ||
), | ||
pointer_type: $ => seq(field('type', $._pointer_base_type), '*'), | ||
_pointer_base_type: $ => choice( | ||
$._name, | ||
$.nullable_type, | ||
$.pointer_type, | ||
$.function_pointer_type, | ||
$.predefined_type, | ||
$.tuple_type | ||
$.tuple_type, | ||
), | ||
pointer_type: $ => prec(PREC.POSTFIX, seq($._type, '*')), | ||
function_pointer_type: $ => seq( | ||
'delegate', | ||
'*', | ||
optional($.function_pointer_calling_convention), | ||
optional($.calling_convention), | ||
'<', | ||
commaSep1($.function_pointer_parameter), | ||
'>' | ||
repeat(seq($.function_pointer_parameter, ',')), | ||
field('returns', $.type), | ||
'>', | ||
), | ||
function_pointer_calling_convention: $ => choice( | ||
calling_convention: $ => choice( | ||
'managed', | ||
seq( | ||
'unmanaged', | ||
optional($.function_pointer_unmanaged_calling_convention_list) | ||
) | ||
optional(seq( | ||
'[', | ||
commaSep1(choice( | ||
'Cdecl', | ||
'Stdcall', | ||
'Thiscall', | ||
'Fastcall', | ||
$.identifier, | ||
)), | ||
']', | ||
)), | ||
), | ||
), | ||
function_pointer_unmanaged_calling_convention_list: $ => seq( | ||
'[', commaSep1($.function_pointer_unmanaged_calling_convention), ']' | ||
), | ||
function_pointer_unmanaged_calling_convention: $ => choice( | ||
'Cdecl', | ||
'Stdcall', | ||
'Thiscall', | ||
'Fastcall', | ||
$.identifier | ||
), | ||
function_pointer_parameter: $ => seq( | ||
optional(choice('ref', 'out', 'in', seq('ref', 'readonly'))), | ||
choice($._type, $.void_keyword) | ||
optional(choice('ref', 'out', 'in')), | ||
field('type', $._ref_base_type), | ||
), | ||
predefined_type: $ => token(choice( | ||
predefined_type: _ => token(choice( | ||
'bool', | ||
@@ -761,4 +845,4 @@ 'byte', | ||
'nint', | ||
'nuint' | ||
// void is handled in return_type for better matching | ||
'nuint', | ||
'void', | ||
)), | ||
@@ -769,19 +853,38 @@ | ||
optional('readonly'), | ||
$._type | ||
field('type', $.type), | ||
), | ||
_ref_base_type: $ => choice( | ||
$.implicit_type, | ||
$._name, | ||
$.nullable_type, | ||
$.array_type, | ||
$.pointer_type, | ||
$.function_pointer_type, | ||
$.predefined_type, | ||
$.tuple_type, | ||
), | ||
scoped_type: $ => seq( | ||
'scoped', | ||
field('type', $._scoped_base_type), | ||
), | ||
_scoped_base_type: $ => choice( | ||
$._name, | ||
$.ref_type, | ||
), | ||
tuple_type: $ => seq( | ||
'(', | ||
$.tuple_element, | ||
',', | ||
commaSep1($.tuple_element), | ||
')' | ||
commaSep2($.tuple_element), | ||
')', | ||
), | ||
tuple_element: $ => prec.left(seq( | ||
field('type', $._type), | ||
field('name', optional($.identifier)) | ||
)), | ||
tuple_element: $ => seq( | ||
field('type', $.type), | ||
field('name', optional($.identifier)), | ||
), | ||
_statement: $ => choice( | ||
statement: $ => prec(1, choice( | ||
$.block, | ||
@@ -795,11 +898,6 @@ $.break_statement, | ||
$.fixed_statement, | ||
$.for_each_statement, | ||
$.for_statement, | ||
$.goto_statement, | ||
$.if_statement, | ||
$.labeled_statement, | ||
$.local_declaration_statement, | ||
$.local_function_statement, | ||
$.return_statement, | ||
$.lock_statement, | ||
$.return_statement, | ||
$.yield_statement, | ||
$.switch_statement, | ||
@@ -810,19 +908,34 @@ $.throw_statement, | ||
$.using_statement, | ||
$.foreach_statement, | ||
$.goto_statement, | ||
$.labeled_statement, | ||
$.if_statement, | ||
$.while_statement, | ||
$.yield_statement, | ||
), | ||
$.local_declaration_statement, | ||
$.local_function_statement, | ||
// alias($.preproc_if_in_statement, $.preproc_if), | ||
alias($.preproc_if_in_top_level, $.preproc_if), | ||
)), | ||
break_statement: $ => seq('break', ';'), | ||
break_statement: _ => seq('break', ';'), | ||
checked_statement: $ => seq(choice('checked', 'unchecked'), $.block), | ||
continue_statement: $ => seq('continue', ';'), | ||
continue_statement: _ => seq('continue', ';'), | ||
do_statement: $ => seq('do', $._statement, 'while', '(', $._expression, ')', ';'), | ||
do_statement: $ => seq( | ||
'do', | ||
field('body', $.statement), | ||
'while', | ||
'(', | ||
field('condition', $.expression), | ||
')', | ||
';', | ||
), | ||
empty_statement: $ => ';', | ||
empty_statement: _ => ';', | ||
expression_statement: $ => seq($._expression, ';'), | ||
expression_statement: $ => seq($._expression_statement_expression, ';'), | ||
fixed_statement: $ => seq('fixed', '(', $.variable_declaration, ')', $._statement), | ||
fixed_statement: $ => seq('fixed', '(', $.variable_declaration, ')', $.statement), | ||
@@ -832,14 +945,99 @@ for_statement: $ => seq( | ||
'(', | ||
field('initializer', optional(choice($.variable_declaration, commaSep1($._expression)))), | ||
field('initializer', optional( | ||
choice($.variable_declaration, commaSep1($.expression)), | ||
)), | ||
';', | ||
field('condition', optional($._expression)), | ||
field('condition', optional($.expression)), | ||
';', | ||
field('update', optional(commaSep1($._expression))), | ||
field('update', optional(commaSep1($.expression))), | ||
')', | ||
field('body', $._statement) | ||
field('body', $.statement), | ||
), | ||
// Combines for_each_statement and for_each_variable_statement from grammar.txt | ||
for_each_statement: $ => seq( | ||
return_statement: $ => seq('return', optional($.expression), ';'), | ||
lock_statement: $ => seq('lock', '(', $.expression, ')', $.statement), | ||
yield_statement: $ => seq( | ||
'yield', | ||
choice( | ||
seq('return', $.expression), | ||
'break', | ||
), | ||
';', | ||
), | ||
switch_statement: $ => seq( | ||
'switch', | ||
choice( | ||
seq( | ||
'(', | ||
field('value', $.expression), | ||
')', | ||
), | ||
field('value', $.tuple_expression), | ||
), | ||
field('body', $.switch_body), | ||
), | ||
switch_body: $ => seq('{', repeat($.switch_section), '}'), | ||
switch_section: $ => prec.left(seq( | ||
choice( | ||
seq( | ||
'case', | ||
choice( | ||
$.expression, | ||
seq($.pattern, optional($.when_clause)), | ||
), | ||
), | ||
'default', | ||
), | ||
':', | ||
repeat($.statement), | ||
)), | ||
throw_statement: $ => seq('throw', optional($.expression), ';'), | ||
try_statement: $ => seq( | ||
'try', | ||
field('body', $.block), | ||
repeat($.catch_clause), | ||
optional($.finally_clause), | ||
), | ||
catch_clause: $ => seq( | ||
'catch', | ||
optional($.catch_declaration), | ||
optional($.catch_filter_clause), | ||
field('body', $.block), | ||
), | ||
catch_declaration: $ => seq( | ||
'(', | ||
field('type', $.type), | ||
optional(field('name', $.identifier)), | ||
')', | ||
), | ||
catch_filter_clause: $ => seq('when', '(', $.expression, ')'), | ||
finally_clause: $ => seq('finally', $.block), | ||
unsafe_statement: $ => seq('unsafe', $.block), | ||
using_statement: $ => seq( | ||
optional('await'), | ||
'using', | ||
'(', | ||
choice( | ||
alias($.using_variable_declaration, $.variable_declaration), | ||
$.expression, | ||
), | ||
')', | ||
field('body', $.statement), | ||
), | ||
foreach_statement: $ => seq( | ||
optional('await'), | ||
'foreach', | ||
@@ -849,11 +1047,11 @@ '(', | ||
seq( | ||
field('type', $._type), | ||
field('type', $.type), | ||
field('left', choice($.identifier, $.tuple_pattern)), | ||
), // for_each_statement | ||
field('left', $._expression), // for_each_variable_statement | ||
), | ||
field('left', $.expression), | ||
), | ||
'in', | ||
field('right', $._expression), | ||
field('right', $.expression), | ||
')', | ||
field('body', $._statement) | ||
field('body', $.statement), | ||
), | ||
@@ -864,22 +1062,30 @@ | ||
optional(choice('case', 'default')), | ||
optional($._expression), | ||
';' | ||
optional($.expression), | ||
';', | ||
), | ||
labeled_statement: $ => seq( | ||
$.identifier, | ||
':', | ||
$.statement, | ||
), | ||
if_statement: $ => prec.right(seq( | ||
'if', | ||
'(', | ||
field('condition', $._expression), | ||
field('condition', $.expression), | ||
')', | ||
field('consequence', $._statement), | ||
field('consequence', $.statement), | ||
optional(seq( | ||
'else', | ||
field('alternative', $._statement) | ||
)) | ||
field('alternative', $.statement), | ||
)), | ||
)), | ||
labeled_statement: $ => seq( | ||
$.identifier, | ||
':', | ||
$._statement | ||
while_statement: $ => seq( | ||
'while', | ||
'(', | ||
field('condition', $.expression), | ||
')', | ||
field('body', $.statement), | ||
), | ||
@@ -892,3 +1098,3 @@ | ||
$.variable_declaration, | ||
';' | ||
';', | ||
), | ||
@@ -899,3 +1105,3 @@ | ||
repeat($.modifier), | ||
field('type', $.return_type), | ||
field('type', $.type), | ||
field('name', $.identifier), | ||
@@ -905,45 +1111,6 @@ field('type_parameters', optional($.type_parameter_list)), | ||
repeat($.type_parameter_constraints_clause), | ||
$._function_body | ||
$._function_body, | ||
), | ||
lock_statement: $ => seq('lock', '(', $._expression, ')', $._statement), | ||
return_statement: $ => seq('return', optional($._expression), ';'), | ||
switch_statement: $ => seq( | ||
'switch', | ||
choice( | ||
seq( | ||
'(', | ||
field('value', $._expression), | ||
')', | ||
), | ||
field('value', $.tuple_expression) | ||
), | ||
field('body', $.switch_body) | ||
), | ||
switch_body: $ => seq( | ||
'{', | ||
repeat($.switch_section), | ||
'}' | ||
), | ||
switch_section: $ => prec.left(seq( | ||
repeat1(choice( // switch_label | ||
$.case_switch_label, | ||
$.case_pattern_switch_label, | ||
$.default_switch_label | ||
)), | ||
repeat1($._statement) | ||
)), | ||
case_pattern_switch_label: $ => seq( | ||
'case', | ||
$._pattern, | ||
optional($.when_clause), | ||
':' | ||
), | ||
_pattern: $ => choice( | ||
pattern: $ => choice( | ||
$.constant_pattern, | ||
@@ -960,39 +1127,5 @@ $.declaration_pattern, | ||
$.list_pattern, | ||
$.type_pattern | ||
$.type_pattern, | ||
), | ||
type_pattern: $ => $._type, | ||
list_pattern: $ => seq( | ||
'[', | ||
optional(seq(commaSep1(choice($._pattern, $.slice_pattern)), optional(','))), | ||
']' | ||
), | ||
slice_pattern: $ => '..', | ||
parenthesized_pattern: $ => seq('(', $._pattern, ')'), | ||
relational_pattern: $ => prec.left(choice( | ||
seq('<', $._expression), | ||
seq('<=', $._expression), | ||
seq('>', $._expression), | ||
seq('>=', $._expression) | ||
)), | ||
negated_pattern: $ => seq('not', $._pattern), | ||
and_pattern: $ => prec.left(PREC.AND, seq( | ||
field('left', $._pattern), | ||
field('operator', 'and'), | ||
field('right', $._pattern) | ||
)), | ||
or_pattern: $ => prec.left(PREC.OR, seq( | ||
field('left', $._pattern), | ||
field('operator', 'or'), | ||
field('right', $._pattern) | ||
)), | ||
//We may need to expand this list if more things can be evaluated at compile time | ||
constant_pattern: $ => choice( | ||
@@ -1005,42 +1138,39 @@ $.binary_expression, | ||
$.prefix_unary_expression, | ||
$.size_of_expression, | ||
$.sizeof_expression, | ||
$.tuple_expression, | ||
$.type_of_expression, | ||
$.typeof_expression, | ||
$.member_access_expression, | ||
$.invocation_expression, | ||
$.cast_expression, | ||
$._simple_name, | ||
$._literal | ||
$.literal, | ||
), | ||
declaration_pattern: $ => seq( | ||
field('type', $._type), | ||
$._variable_designation | ||
), | ||
discard: _ => '_', | ||
_variable_designation: $ => prec(1, choice( | ||
$.discard, | ||
$.parenthesized_variable_designation, | ||
field('name', $.identifier), | ||
)), | ||
parenthesized_pattern: $ => seq('(', $.pattern, ')'), | ||
discard: $ => '_', | ||
var_pattern: $ => seq('var', $._variable_designation), | ||
parenthesized_variable_designation: $ => seq( | ||
'(', | ||
commaSep($._variable_designation), | ||
')' | ||
type_pattern: $ => prec.right(field('type', $.type)), | ||
list_pattern: $ => seq( | ||
'[', | ||
optional(seq( | ||
commaSep1(choice($.pattern, '..')), | ||
optional(','), | ||
)), | ||
']', | ||
), | ||
recursive_pattern: $ => prec.left(seq( | ||
optional($._type), | ||
optional(field('type', $.type)), | ||
choice( | ||
seq( | ||
$.positional_pattern_clause, | ||
optional($.property_pattern_clause) | ||
optional($.property_pattern_clause), | ||
), | ||
$.property_pattern_clause | ||
$.property_pattern_clause, | ||
), | ||
optional($._variable_designation) | ||
optional($._variable_designation), | ||
)), | ||
@@ -1050,13 +1180,6 @@ | ||
'(', | ||
optional(seq($.subpattern, ',', commaSep1($.subpattern))),// we really should allow single sub patterns, but that causes conficts, and will rarely be used | ||
optional(commaSep2($.subpattern)), | ||
')', | ||
)), | ||
expression_colon: $ => seq($._expression, ':'), | ||
subpattern: $ => seq( | ||
optional($.expression_colon), | ||
$._pattern | ||
), | ||
property_pattern_clause: $ => prec(1, seq( | ||
@@ -1069,248 +1192,386 @@ '{', | ||
var_pattern: $ => prec(1, seq('var', $._variable_designation)), | ||
subpattern: $ => seq( | ||
optional(seq($.expression, ':')), | ||
$.pattern, | ||
), | ||
when_clause: $ => seq('when', $._expression), | ||
relational_pattern: $ => choice( | ||
seq('<', $.expression), | ||
seq('<=', $.expression), | ||
seq('>', $.expression), | ||
seq('>=', $.expression), | ||
), | ||
case_switch_label: $ => prec.left(1, seq('case', $._expression, ':')), | ||
negated_pattern: $ => seq('not', $.pattern), | ||
default_switch_label: $ => prec.left(1, seq('default', ':')), | ||
and_pattern: $ => prec.left(PREC.AND, seq( | ||
field('left', $.pattern), | ||
field('operator', 'and'), | ||
field('right', $.pattern), | ||
)), | ||
throw_statement: $ => seq('throw', optional($._expression), ';'), | ||
or_pattern: $ => prec.left(PREC.OR, seq( | ||
field('left', $.pattern), | ||
field('operator', 'or'), | ||
field('right', $.pattern), | ||
)), | ||
try_statement: $ => seq( | ||
'try', | ||
field('body', $.block), | ||
repeat($.catch_clause), | ||
optional($.finally_clause), | ||
declaration_pattern: $ => seq( | ||
field('type', $.type), | ||
$._variable_designation, | ||
), | ||
catch_clause: $ => seq( | ||
'catch', | ||
optional($.catch_declaration), | ||
optional($.catch_filter_clause), | ||
field('body', $.block) | ||
), | ||
_variable_designation: $ => prec(1, choice( | ||
$.discard, | ||
$.parenthesized_variable_designation, | ||
field('name', $.identifier), | ||
)), | ||
catch_declaration: $ => seq( | ||
parenthesized_variable_designation: $ => seq( | ||
'(', | ||
field('type', $._type), | ||
optional(field('name', $.identifier)), | ||
')' | ||
commaSep($._variable_designation), | ||
')', | ||
), | ||
catch_filter_clause: $ => seq('when', '(', $._expression, ')'), | ||
expression: $ => choice( | ||
$.non_lvalue_expression, | ||
$.lvalue_expression, | ||
), | ||
finally_clause: $ => seq('finally', $.block), | ||
non_lvalue_expression: $ => choice( | ||
$.binary_expression, | ||
$.interpolated_string_expression, | ||
$.conditional_expression, | ||
$.conditional_access_expression, | ||
$.literal, | ||
$._expression_statement_expression, | ||
$.is_expression, | ||
$.is_pattern_expression, | ||
$.as_expression, | ||
$.cast_expression, | ||
$.checked_expression, | ||
$.switch_expression, | ||
$.throw_expression, | ||
$.default_expression, | ||
$.lambda_expression, | ||
$.with_expression, | ||
$.sizeof_expression, | ||
$.typeof_expression, | ||
$.makeref_expression, | ||
$.ref_expression, | ||
$.reftype_expression, | ||
$.refvalue_expression, | ||
$.stackalloc_expression, | ||
$.range_expression, | ||
$.array_creation_expression, | ||
$.anonymous_method_expression, | ||
$.anonymous_object_creation_expression, | ||
$.implicit_array_creation_expression, | ||
$.implicit_object_creation_expression, | ||
$.implicit_stackalloc_expression, | ||
$.initializer_expression, | ||
$.query_expression, | ||
alias($.preproc_if_in_expression, $.preproc_if), | ||
), | ||
unsafe_statement: $ => seq('unsafe', $.block), | ||
lvalue_expression: $ => choice( | ||
'this', | ||
$.member_access_expression, | ||
$.tuple_expression, | ||
$._simple_name, | ||
$.element_access_expression, | ||
alias($.bracketed_argument_list, $.element_binding_expression), | ||
alias($._pointer_indirection_expression, $.prefix_unary_expression), | ||
alias($._parenthesized_lvalue_expression, $.parenthesized_expression), | ||
), | ||
using_statement: $ => seq( | ||
optional('await'), | ||
'using', | ||
'(', | ||
choice($.variable_declaration, $._expression), | ||
')', | ||
field('body', $._statement) | ||
// Covers error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement | ||
_expression_statement_expression: $ => choice( | ||
$.assignment_expression, | ||
$.invocation_expression, | ||
$.postfix_unary_expression, | ||
$.prefix_unary_expression, | ||
$.await_expression, | ||
$.object_creation_expression, | ||
$.parenthesized_expression, | ||
), | ||
while_statement: $ => seq('while', '(', $._expression, ')', $._statement), | ||
assignment_expression: $ => seq( | ||
field('left', $.lvalue_expression), | ||
field('operator', | ||
choice( | ||
'=', | ||
'+=', | ||
'-=', | ||
'*=', | ||
'/=', | ||
'%=', | ||
'&=', | ||
'^=', | ||
'|=', | ||
'<<=', | ||
'>>=', | ||
'>>>=', | ||
'??=', | ||
), | ||
), | ||
field('right', $.expression), | ||
), | ||
yield_statement: $ => seq( | ||
'yield', | ||
choice( // grammar.txt incorrectly allows "break expression", we do not. | ||
seq('return', $._expression), | ||
'break' | ||
binary_expression: $ => choice( | ||
...[ | ||
['&&', PREC.LOGICAL_AND], | ||
['||', PREC.LOGICAL_OR], | ||
['>>', PREC.SHIFT], | ||
['>>>', PREC.SHIFT], | ||
['<<', PREC.SHIFT], | ||
['&', PREC.AND], | ||
['^', PREC.XOR], | ||
['|', PREC.OR], | ||
['+', PREC.ADD], | ||
['-', PREC.ADD], | ||
['*', PREC.MULT], | ||
['/', PREC.MULT], | ||
['%', PREC.MULT], | ||
['<', PREC.REL], | ||
['<=', PREC.REL], | ||
['==', PREC.EQUAL], | ||
['!=', PREC.EQUAL], | ||
['>=', PREC.REL], | ||
['>', PREC.REL], | ||
].map(([operator, precedence]) => | ||
prec.left(precedence, seq( | ||
field('left', $.expression), | ||
// @ts-ignore | ||
field('operator', operator), | ||
field('right', $.expression), | ||
)), | ||
), | ||
';' | ||
prec.right(PREC.COALESCING, seq( | ||
field('left', $.expression), | ||
field('operator', '??'), | ||
field('right', $.expression), | ||
)), | ||
), | ||
anonymous_method_expression: $ => seq( | ||
optional('async'), | ||
'delegate', | ||
optional(field('parameters', $.parameter_list)), | ||
$.block | ||
postfix_unary_expression: $ => prec(PREC.POSTFIX, choice( | ||
seq($.expression, '++'), | ||
seq($.expression, '--'), | ||
seq($.expression, '!'), | ||
)), | ||
prefix_unary_expression: $ => prec(PREC.UNARY, seq( | ||
choice('++', '--', '+', '-', '!', '~', '&', '^'), | ||
$.expression, | ||
)), | ||
_pointer_indirection_expression: $ => prec.right(PREC.UNARY, seq( | ||
'*', | ||
$.lvalue_expression, | ||
)), | ||
query_expression: $ => seq($.from_clause, $._query_body), | ||
from_clause: $ => seq( | ||
'from', | ||
optional(field('type', $.type)), | ||
field('name', $.identifier), | ||
'in', | ||
$.expression, | ||
), | ||
lambda_expression: $ => prec(-1, seq( | ||
repeat($.attribute_list), | ||
optional(alias(choice('async', 'static', seq('async', 'static'), seq('static', 'async')), $.modifier)), | ||
choice(field('parameters', $.parameter_list), $.identifier), | ||
'=>', | ||
field('body', choice($.block, $._expression)) | ||
_query_body: $ => prec.right(sep1( | ||
seq( | ||
repeat($._query_clause), | ||
$._select_or_group_clause, | ||
), | ||
seq('into', $.identifier), | ||
)), | ||
anonymous_object_creation_expression: $ => seq( | ||
'new', | ||
'{', | ||
commaSep($._anonymous_object_member_declarator), | ||
optional(','), | ||
'}' | ||
_query_clause: $ => choice( | ||
$.from_clause, | ||
$.join_clause, | ||
$.let_clause, | ||
$.order_by_clause, | ||
$.where_clause, | ||
), | ||
implicit_object_creation_expression: $ => seq( | ||
'new', | ||
$.argument_list, | ||
optional($.initializer_expression) | ||
join_clause: $ => seq( | ||
'join', | ||
$._join_header, | ||
$._join_body, | ||
optional($.join_into_clause), | ||
), | ||
_anonymous_object_member_declarator: $ => choice( | ||
prec.dynamic(PREC.ASSIGN, seq($.name_equals, $._expression)), | ||
$._expression | ||
_join_header: $ => seq(optional(field('type', $.type)), $.identifier, 'in', $.expression), | ||
_join_body: $ => seq('on', $.expression, 'equals', $.expression), | ||
join_into_clause: $ => seq('into', $.identifier), | ||
let_clause: $ => seq( | ||
'let', | ||
$.identifier, | ||
'=', | ||
$.expression, | ||
), | ||
array_creation_expression: $ => prec.dynamic(PREC.UNARY, seq( | ||
'new', | ||
$.array_type, | ||
optional($.initializer_expression) | ||
)), | ||
order_by_clause: $ => seq( | ||
'orderby', | ||
commaSep1($._ordering), | ||
), | ||
initializer_expression: $ => seq( | ||
'{', | ||
commaSep($._expression), | ||
optional(','), | ||
'}' | ||
_ordering: $ => seq( | ||
$.expression, | ||
optional(choice('ascending', 'descending')), | ||
), | ||
assignment_expression: $ => prec.right(seq( | ||
field('left', $._expression), | ||
$.assignment_operator, | ||
field('right', $._expression) | ||
)), | ||
where_clause: $ => seq('where', $.expression), | ||
assignment_operator: $ => choice('=', '+=', '-=', '*=', '/=', '%=', '&=', '^=', '|=', '<<=', '>>=', '??='), | ||
_select_or_group_clause: $ => choice( | ||
$.group_clause, | ||
$.select_clause, | ||
), | ||
await_expression: $ => prec.right(PREC.UNARY, seq('await', $._expression)), | ||
group_clause: $ => seq('group', $.expression, 'by', $.expression), | ||
cast_expression: $ => prec.right(PREC.CAST, seq( | ||
'(', | ||
field('type', $._type), | ||
')', | ||
field('value', $._expression) | ||
)), | ||
select_clause: $ => seq('select', $.expression), | ||
checked_expression: $ => choice( | ||
seq('checked', '(', $._expression, ')'), | ||
seq('unchecked', '(', $._expression, ')') | ||
), | ||
conditional_access_expression: $ => prec.right(PREC.COND, seq( | ||
field('condition', $._expression), | ||
conditional_expression: $ => prec.right(PREC.CONDITIONAL, seq( | ||
field('condition', $.expression), | ||
'?', | ||
choice($.member_binding_expression, $.element_binding_expression) | ||
field('consequence', $.expression), | ||
':', | ||
field('alternative', $.expression), | ||
)), | ||
conditional_expression: $ => prec.right(PREC.COND, seq( | ||
field('condition', $._expression), | ||
conditional_access_expression: $ => prec.right(PREC.CONDITIONAL, seq( | ||
field('condition', $.expression), | ||
'?', | ||
field('consequence', $._expression), | ||
':', | ||
field('alternative', $._expression) | ||
choice( | ||
$.member_binding_expression, | ||
alias($.bracketed_argument_list, $.element_binding_expression), | ||
), | ||
)), | ||
declaration_expression: $ => seq( | ||
field('type', $._type), | ||
field('name', $.identifier) | ||
), | ||
as_expression: $ => prec(PREC.REL, seq( | ||
field('left', $.expression), | ||
field('operator', 'as'), | ||
field('right', $.type), | ||
)), | ||
default_expression: $ => prec.right(seq( | ||
'default', | ||
optional(seq( | ||
'(', | ||
field('type', $._type), | ||
')' | ||
)) | ||
is_expression: $ => prec(PREC.REL, seq( | ||
field('left', $.expression), | ||
field('operator', 'is'), | ||
field('right', $.type), | ||
)), | ||
element_access_expression: $ => prec.right(PREC.UNARY, seq( | ||
field('expression', $._expression), | ||
field('subscript', $.bracketed_argument_list) | ||
is_pattern_expression: $ => prec(PREC.REL, seq( | ||
field('expression', $.expression), | ||
'is', | ||
field('pattern', $.pattern), | ||
)), | ||
element_binding_expression: $ => $.bracketed_argument_list, | ||
cast_expression: $ => prec(PREC.CAST, prec.dynamic(1, seq( // higher than invocation, lower than binary | ||
'(', | ||
field('type', $.type), | ||
')', | ||
field('value', $.expression), | ||
))), | ||
implicit_array_creation_expression: $ => seq( | ||
'new', | ||
'[', | ||
repeat(','), | ||
']', | ||
$.initializer_expression | ||
checked_expression: $ => seq( | ||
choice('checked', 'unchecked'), | ||
'(', | ||
$.expression, | ||
')', | ||
), | ||
implicit_stack_alloc_array_creation_expression: $ => seq( | ||
'stackalloc', | ||
'[', | ||
']', | ||
$.initializer_expression | ||
invocation_expression: $ => prec(PREC.INVOCATION, seq( | ||
field('function', $.expression), | ||
field('arguments', $.argument_list), | ||
)), | ||
switch_expression: $ => prec(PREC.SWITCH, seq( | ||
$.expression, | ||
'switch', | ||
'{', | ||
commaSep($.switch_expression_arm), | ||
optional(','), | ||
'}', | ||
)), | ||
switch_expression_arm: $ => seq( | ||
$.pattern, | ||
optional($.when_clause), | ||
'=>', | ||
$.expression, | ||
), | ||
base_expression: $ => 'base', | ||
when_clause: $ => seq('when', $.expression), | ||
this_expression: $ => 'this', | ||
await_expression: $ => prec.right(PREC.UNARY, seq( | ||
'await', | ||
$.expression, | ||
)), | ||
throw_expression: $ => seq('throw', $.expression), | ||
element_access_expression: $ => prec(PREC.POSTFIX, seq( | ||
field('expression', $.expression), | ||
field('subscript', $.bracketed_argument_list), | ||
)), | ||
interpolated_string_expression: $ => choice( | ||
seq('$"', repeat($._interpolated_string_content), '"'), | ||
seq('$@"', repeat($._interpolated_verbatim_string_content), '"'), | ||
seq('@$"', repeat($._interpolated_verbatim_string_content), '"'), | ||
seq( | ||
alias($.interpolation_regular_start, $.interpolation_start), | ||
'"', | ||
repeat($._interpolated_string_content), | ||
'"', | ||
), | ||
seq( | ||
alias($.interpolation_verbatim_start, $.interpolation_start), | ||
'"', | ||
repeat($._interpolated_verbatim_string_content), | ||
'"', | ||
), | ||
seq( | ||
alias($.interpolation_raw_start, $.interpolation_start), | ||
alias($.interpolation_start_quote, $.interpolation_quote), | ||
repeat($._interpolated_raw_string_content), | ||
alias($.interpolation_end_quote, $.interpolation_quote), | ||
), | ||
), | ||
_interpolated_string_content: $ => choice( | ||
$.interpolated_string_text, | ||
$.interpolation | ||
alias($.interpolation_string_content, $.string_content), | ||
$.escape_sequence, | ||
$.interpolation, | ||
), | ||
_interpolated_verbatim_string_content: $ => choice( | ||
$.interpolated_verbatim_string_text, | ||
$.interpolation | ||
alias($.interpolation_string_content, $.string_content), | ||
$.interpolation, | ||
), | ||
interpolated_string_text: $ => choice( | ||
'{{', | ||
$._interpolated_string_text_fragment, | ||
$.escape_sequence | ||
_interpolated_raw_string_content: $ => choice( | ||
alias($.interpolation_string_content, $.string_content), | ||
$.interpolation, | ||
), | ||
_interpolated_string_text_fragment: $ => token.immediate(prec(1, /[^{"\\\n]+/)), | ||
interpolated_verbatim_string_text: $ => choice( | ||
'{{', | ||
$._interpolated_verbatim_string_text_fragment, | ||
'""' | ||
), | ||
_interpolated_verbatim_string_text_fragment: $ => token.immediate(prec(1, /[^{"]+/)), | ||
interpolation: $ => seq( | ||
'{', | ||
$._expression, | ||
alias($.interpolation_open_brace, $.interpolation_brace), | ||
$.expression, | ||
optional($.interpolation_alignment_clause), | ||
optional($.interpolation_format_clause), | ||
'}' | ||
alias($.interpolation_close_brace, $.interpolation_brace), | ||
), | ||
interpolation_alignment_clause: $ => seq(',', $._expression), | ||
interpolation_alignment_clause: $ => seq(',', $.expression), | ||
interpolation_format_clause: $ => seq(':', /[^}"]+/), | ||
interpolation_format_clause: _ => seq(':', /[^}"]+/), | ||
invocation_expression: $ => prec(PREC.INVOCATION, seq( | ||
field('function', $._expression), | ||
field('arguments', $.argument_list) | ||
)), | ||
is_pattern_expression: $ => prec.left(PREC.REL, seq( | ||
field('expression', $._expression), | ||
'is', | ||
field('pattern', $._pattern) | ||
)), | ||
make_ref_expression: $ => seq( | ||
'__makeref', | ||
'(', | ||
$._expression, | ||
')' | ||
), | ||
member_access_expression: $ => prec(PREC.DOT, seq( | ||
field('expression', choice($._expression, $.predefined_type, $._name)), | ||
field('expression', choice($.expression, $.predefined_type, $._name)), | ||
choice('.', '->'), | ||
field('name', $._simple_name) | ||
field('name', $._simple_name), | ||
)), | ||
@@ -1325,323 +1586,200 @@ | ||
'new', | ||
field('type', $._type), | ||
field('type', $.type), | ||
field('arguments', optional($.argument_list)), | ||
field('initializer', optional($.initializer_expression)) | ||
field('initializer', optional($.initializer_expression)), | ||
)), | ||
parenthesized_expression: $ => seq('(', $._expression, ')'), | ||
// inline | ||
_object_creation_type: $ => choice( | ||
$._name, | ||
$.nullable_type, | ||
$.predefined_type, | ||
), | ||
postfix_unary_expression: $ => prec.left(PREC.POSTFIX, choice( | ||
seq($._expression, '++'), | ||
seq($._expression, '--'), | ||
seq($._expression, '!') | ||
)), | ||
parenthesized_expression: $ => seq( | ||
'(', | ||
$.non_lvalue_expression, | ||
')', | ||
), | ||
prefix_unary_expression: $ => prec.right(PREC.UNARY, choice( | ||
...[ | ||
'!', | ||
'&', | ||
'*', | ||
'+', | ||
'++', | ||
'-', | ||
'--', | ||
'^', | ||
'~' | ||
].map(operator => seq(operator, $._expression)))), | ||
_parenthesized_lvalue_expression: $ => seq('(', $.lvalue_expression, ')'), | ||
query_expression: $ => seq($.from_clause, $._query_body), | ||
lambda_expression: $ => prec(-1, seq( | ||
repeat($.attribute_list), | ||
repeat(prec(-1, alias(choice('static', 'async'), $.modifier))), | ||
optional(field('type', $.type)), | ||
field('parameters', $._lambda_parameters), | ||
'=>', | ||
field('body', choice($.block, $.expression)), | ||
)), | ||
from_clause: $ => seq( | ||
'from', | ||
optional($._type), | ||
$.identifier, | ||
'in', | ||
$._expression | ||
), | ||
_lambda_parameters: $ => prec(-1, choice( | ||
$.parameter_list, | ||
alias($.identifier, $.implicit_parameter), | ||
)), | ||
_query_body: $ => prec.right(seq( | ||
repeat($._query_clause), // grammar.txt is incorrect with '+' | ||
$._select_or_group_clause, | ||
optional($.query_continuation) | ||
array_creation_expression: $ => prec.dynamic(PREC.UNARY, seq( | ||
'new', | ||
field('type', $.array_type), | ||
optional($.initializer_expression), | ||
)), | ||
_query_clause: $ => choice( | ||
$.from_clause, | ||
$.join_clause, | ||
$.let_clause, | ||
$.order_by_clause, | ||
$.where_clause | ||
anonymous_method_expression: $ => seq( | ||
repeat(prec(-1, alias(choice('static', 'async'), $.modifier))), | ||
'delegate', | ||
optional(field('parameters', $.parameter_list)), | ||
$.block, | ||
), | ||
join_clause: $ => seq( | ||
'join', | ||
optional($._type), | ||
$.identifier, | ||
'in', | ||
$._expression, | ||
'on', | ||
$._expression, | ||
'equals', | ||
$._expression, | ||
optional($.join_into_clause) | ||
anonymous_object_creation_expression: $ => seq( | ||
'new', | ||
'{', | ||
commaSep($._anonymous_object_member_declarator), | ||
optional(','), | ||
'}', | ||
), | ||
join_into_clause: $ => seq('into', $.identifier), | ||
let_clause: $ => seq( | ||
'let', | ||
$.identifier, | ||
'=', | ||
$._expression | ||
_anonymous_object_member_declarator: $ => choice( | ||
seq($.identifier, '=', $.expression), | ||
$.expression, | ||
), | ||
order_by_clause: $ => seq( | ||
'orderby', | ||
commaSep1($._ordering) | ||
implicit_array_creation_expression: $ => seq( | ||
'new', | ||
'[', | ||
repeat(','), | ||
']', | ||
$.initializer_expression, | ||
), | ||
_ordering: $ => seq( | ||
$._expression, | ||
optional(choice('ascending', 'descending')) | ||
implicit_object_creation_expression: $ => prec.right(seq( | ||
'new', | ||
$.argument_list, | ||
optional($.initializer_expression), | ||
)), | ||
implicit_stackalloc_expression: $ => seq( | ||
'stackalloc', | ||
'[', | ||
']', | ||
$.initializer_expression, | ||
), | ||
where_clause: $ => seq('where', $._expression), | ||
_select_or_group_clause: $ => choice( | ||
$.group_clause, | ||
$.select_clause | ||
initializer_expression: $ => seq( | ||
'{', | ||
commaSep($.expression), | ||
optional(','), | ||
'}', | ||
), | ||
group_clause: $ => prec.right(PREC.SELECT, seq( | ||
'group', | ||
$._expression, | ||
'by', | ||
$._expression | ||
declaration_expression: $ => prec.dynamic(1, seq( | ||
field('type', $.type), | ||
field('name', $.identifier), | ||
)), | ||
select_clause: $ => prec.right(PREC.SELECT, seq('select', $._expression)), | ||
default_expression: $ => prec.right(seq( | ||
'default', | ||
optional(seq( | ||
'(', | ||
field('type', $.type), | ||
')', | ||
)), | ||
)), | ||
query_continuation: $ => seq('into', $.identifier, $._query_body), | ||
range_expression: $ => prec.right(PREC.RANGE, seq( | ||
optional($._expression), | ||
'..', | ||
optional($._expression) | ||
with_expression: $ => prec.left(PREC.WITH, seq( | ||
$.expression, | ||
'with', | ||
'{', | ||
commaSep($.with_initializer), | ||
'}', | ||
)), | ||
ref_expression: $ => prec.right(seq('ref', $._expression)), | ||
with_initializer: $ => seq($.identifier, '=', $.expression), | ||
ref_type_expression: $ => seq( | ||
'__reftype', | ||
sizeof_expression: $ => seq( | ||
'sizeof', | ||
'(', | ||
$._expression, | ||
')' | ||
field('type', $.type), | ||
')', | ||
), | ||
ref_value_expression: $ => seq( | ||
'__refvalue', | ||
typeof_expression: $ => seq( | ||
'typeof', | ||
'(', | ||
field('value', $._expression), | ||
',', | ||
field('type', $._type), | ||
')' | ||
field('type', $.type), | ||
')', | ||
), | ||
size_of_expression: $ => seq( | ||
'sizeof', | ||
makeref_expression: $ => seq( | ||
'__makeref', | ||
'(', | ||
$._type, | ||
')' | ||
$.expression, | ||
')', | ||
), | ||
stack_alloc_array_creation_expression: $ => seq( | ||
'stackalloc', | ||
$.array_type, | ||
optional($.initializer_expression) | ||
), | ||
ref_expression: $ => seq('ref', $.expression), | ||
switch_expression: $ => prec(PREC.SWITCH, seq( | ||
$._expression, | ||
'switch', | ||
'{', | ||
commaSep($.switch_expression_arm), | ||
optional(','), | ||
'}', | ||
)), | ||
switch_expression_arm: $ => seq( | ||
$._pattern, | ||
optional($.when_clause), | ||
'=>', | ||
$._expression | ||
reftype_expression: $ => seq( | ||
'__reftype', | ||
'(', | ||
$.expression, | ||
')', | ||
), | ||
throw_expression: $ => prec.right(seq('throw', $._expression)), | ||
tuple_expression: $ => seq( | ||
refvalue_expression: $ => seq( | ||
'__refvalue', | ||
'(', | ||
$.argument, | ||
repeat1(seq( | ||
',', | ||
$.argument, | ||
)), | ||
')' | ||
field('value', $.expression), | ||
',', | ||
field('type', $.type), | ||
')', | ||
), | ||
type_of_expression: $ => seq('typeof', '(', $._type, ')'), | ||
with_expression: $ => prec.left(PREC.WITH, | ||
seq($._expression, 'with', '{', optional($.with_initializer_expression), '}')), | ||
with_initializer_expression: $ => commaSep1($.simple_assignment_expression), | ||
simple_assignment_expression: $ => seq($.identifier, '=', $._expression), | ||
_expression: $ => choice( | ||
$.anonymous_method_expression, | ||
$.anonymous_object_creation_expression, | ||
$.array_creation_expression, | ||
$.as_expression, | ||
$.assignment_expression, | ||
$.await_expression, | ||
$.base_expression, | ||
$.binary_expression, | ||
$.cast_expression, | ||
$.checked_expression, | ||
$.conditional_access_expression, | ||
$.conditional_expression, | ||
$.default_expression, | ||
$.element_access_expression, | ||
$.element_binding_expression, | ||
$.implicit_array_creation_expression, | ||
$.implicit_object_creation_expression, | ||
$.implicit_stack_alloc_array_creation_expression, | ||
$.initializer_expression, | ||
$.interpolated_string_expression, | ||
$.invocation_expression, | ||
$.is_expression, | ||
$.is_pattern_expression, | ||
$.lambda_expression, | ||
$.make_ref_expression, | ||
$.member_access_expression, | ||
// $.member_binding_expression, // Not needed as handled directly in $.conditional_access_expression | ||
$.object_creation_expression, | ||
$.parenthesized_expression, | ||
$.postfix_unary_expression, | ||
$.prefix_unary_expression, | ||
$.query_expression, | ||
$.range_expression, | ||
$.ref_expression, | ||
$.ref_type_expression, | ||
$.ref_value_expression, | ||
$.size_of_expression, | ||
$.stack_alloc_array_creation_expression, | ||
$.switch_expression, | ||
$.this_expression, | ||
$.throw_expression, | ||
$.tuple_expression, | ||
$.type_of_expression, | ||
$.with_expression, | ||
$._simple_name, | ||
$._literal | ||
), | ||
binary_expression: $ => choice( | ||
...[ | ||
['&&', PREC.LOGAND], // logical_and_expression | ||
['||', PREC.LOGOR], // logical_or_expression | ||
['>>', PREC.SHIFT], // right_shift_expression | ||
['<<', PREC.SHIFT], // left_shift_expression | ||
['&', PREC.AND], // bitwise_and_expression | ||
['^', PREC.XOR], // exclusive_or_expression | ||
['|', PREC.OR], // bitwise_or_expression | ||
['+', PREC.ADD], // add_expression | ||
['-', PREC.ADD], // subtract_expression | ||
['*', PREC.MULT], // multiply_expression | ||
['/', PREC.MULT], // divide_expression | ||
['%', PREC.MULT], // modulo_expression | ||
['<', PREC.REL], // less_than_expression | ||
['<=', PREC.REL], // less_than_or_equal_expression | ||
['==', PREC.EQUAL], // equals_expression | ||
['!=', PREC.EQUAL], // not_equals_expression | ||
['>=', PREC.REL], // greater_than_or_equal_expression | ||
['>', PREC.REL] // greater_than_expression | ||
].map(([operator, precedence]) => | ||
prec.left(precedence, seq( | ||
field('left', $._expression), | ||
field('operator', operator), | ||
field('right', $._expression) | ||
)) | ||
), | ||
prec.right(PREC.COALESCING, seq( | ||
field('left', $._expression), | ||
field('operator', '??'), // coalesce_expression | ||
field('right', $._expression) | ||
)) | ||
), | ||
as_expression: $ => prec.left(PREC.REL, seq( | ||
field('left', $._expression), | ||
field('operator', 'as'), | ||
field('right', $._type) | ||
stackalloc_expression: $ => prec.left(seq( | ||
'stackalloc', | ||
field('type', $.array_type), | ||
optional($.initializer_expression), | ||
)), | ||
is_expression: $ => prec.left(PREC.REL, seq( | ||
field('left', $._expression), | ||
field('operator', 'is'), | ||
field('right', $._type) | ||
range_expression: $ => prec.right(PREC.RANGE, seq( | ||
optional($.expression), | ||
'..', | ||
optional($.expression), | ||
)), | ||
// Unicode categories: L = Letter, Nl Letter_Number, = Nd = Decimal_Number, Pc = Connector_Punctuation, Cf = Format, Mn = Nonspacing_Mark, Mc = Spacing_Mark | ||
_identifier_token: $ => token(seq(optional('@'), /[\p{L}\p{Nl}_][\p{L}\p{Nl}\p{Nd}\p{Pc}\p{Cf}\p{Mn}\p{Mc}]*/)), | ||
identifier: $ => choice($._identifier_token, $._contextual_keywords), | ||
tuple_expression: $ => seq( | ||
'(', | ||
commaSep2($.argument), | ||
')', | ||
), | ||
global: $ => 'global', | ||
_identifier_or_global: $ => choice($.global, $.identifier), | ||
// Literals - grammar.txt is useless here as it just refs to lexical specification | ||
_literal: $ => choice( | ||
literal: $ => choice( | ||
$.null_literal, | ||
$.boolean_literal, | ||
$.character_literal, | ||
// Don't combine real and integer literals together | ||
$.integer_literal, | ||
$.real_literal, | ||
$.integer_literal, | ||
// Or strings and verbatim strings | ||
$.boolean_literal, | ||
$.string_literal, | ||
$.verbatim_string_literal | ||
$.verbatim_string_literal, | ||
$.raw_string_literal, | ||
), | ||
boolean_literal: $ => choice( | ||
'true', | ||
'false' | ||
), | ||
null_literal: _ => 'null', | ||
character_literal: $ => seq( | ||
"'", | ||
'\'', | ||
choice(token.immediate(/[^'\\]/), $.escape_sequence), | ||
"'" | ||
'\'', | ||
), | ||
escape_sequence: $ => token(choice( | ||
/\\x[0-9a-fA-F][0-9a-fA-F]?[0-9a-fA-F]?[0-9a-fA-F]?/, | ||
/\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]/, | ||
/\\U[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]/, | ||
/\\[^xuU]/, | ||
)), | ||
integer_literal: $ => token(seq( | ||
integer_literal: _ => token(seq( | ||
choice( | ||
decimalDigitSequence, // Decimal | ||
(/0[xX][0-9a-fA-F_]*[0-9a-fA-F]+/), // Hex | ||
(/0[bB][01_]*[01]+/) // Binary | ||
(/0[bB][01_]*[01]+/), // Binary | ||
), | ||
optional(/u|U|l|L|ul|UL|uL|Ul|lu|LU|Lu|lU/) | ||
optional(/([uU][lL]?|[lL][uU]?)/), | ||
)), | ||
null_literal: $ => 'null', | ||
real_literal: $ => { | ||
real_literal: _ => { | ||
const suffix = /[fFdDmM]/; | ||
@@ -1655,3 +1793,3 @@ const exponent = /[eE][+-]?[0-9][0-9_]*/; | ||
optional(exponent), | ||
optional(suffix) | ||
optional(suffix), | ||
), | ||
@@ -1662,3 +1800,3 @@ seq( | ||
optional(exponent), | ||
optional(suffix) | ||
optional(suffix), | ||
), | ||
@@ -1668,9 +1806,9 @@ seq( | ||
exponent, | ||
optional(suffix) | ||
optional(suffix), | ||
), | ||
seq( | ||
decimalDigitSequence, | ||
suffix | ||
) | ||
)) | ||
suffix, | ||
), | ||
)); | ||
}, | ||
@@ -1681,11 +1819,24 @@ | ||
repeat(choice( | ||
$._string_literal_fragment, | ||
$.escape_sequence | ||
$.string_literal_content, | ||
$.escape_sequence, | ||
)), | ||
choice('"', '"U8', '"u8') | ||
'"', | ||
optional($.string_literal_encoding), | ||
), | ||
_string_literal_fragment: $ => token.immediate(prec(1, /[^"\\\n]+/)), | ||
string_literal_content: _ => choice( | ||
token.immediate(prec(1, /[^"\\\n]+/)), | ||
prec(2, token.immediate(seq('\\', /[^abefnrtv'\"\\\?0]/))), | ||
), | ||
verbatim_string_literal: $ => token(seq( | ||
escape_sequence: _ => token(choice( | ||
/\\x[0-9a-fA-F]{2,4}/, | ||
/\\u[0-9a-fA-F]{4}/, | ||
/\\U[0-9a-fA-F]{8}/, | ||
/\\[abefnrtv'\"\\\?0]/, | ||
)), | ||
string_literal_encoding: _ => token.immediate(stringEncoding), | ||
verbatim_string_literal: _ => token(seq( | ||
'@"', | ||
@@ -1696,21 +1847,23 @@ repeat(choice( | ||
)), | ||
choice('"', '"U8', '"u8') | ||
'"', | ||
optional(stringEncoding), | ||
)), | ||
// Comments | ||
comment: $ => token(choice( | ||
seq('//', /[^\n\r]*/), | ||
seq( | ||
'/*', | ||
/[^*]*\*+([^/*][^*]*\*+)*/, | ||
'/' | ||
) | ||
raw_string_literal: _ => token(seq( | ||
/""["]+/, | ||
optional(/([^"]|("[^"])|(""[^"]))+/), | ||
/""["]+/, | ||
optional(stringEncoding), | ||
)), | ||
// Custom non-Roslyn additions beyond this point that will not sync up with grammar.txt | ||
boolean_literal: _ => choice('true', 'false'), | ||
// Contextual keywords - keywords that can also be identifiers... | ||
_contextual_keywords: $ => choice( | ||
// LINQ comprehension syntax | ||
_identifier_token: _ => token(seq(optional('@'), /[\p{L}\p{Nl}_][\p{L}\p{Nl}\p{Nd}\p{Pc}\p{Cf}\p{Mn}\p{Mc}]*/)), | ||
identifier: $ => choice( | ||
$._identifier_token, | ||
$._reserved_identifier, | ||
), | ||
_reserved_identifier: _ => choice( | ||
'alias', | ||
'ascending', | ||
@@ -1720,3 +1873,5 @@ 'by', | ||
'equals', | ||
'file', | ||
'from', | ||
'global', | ||
'group', | ||
@@ -1726,95 +1881,24 @@ 'into', | ||
'let', | ||
'notnull', | ||
'on', | ||
'orderby', | ||
'scoped', | ||
'select', | ||
'where', | ||
// Property/event handlers | ||
'add', | ||
'get', | ||
'remove', | ||
'set', | ||
// Async - These need to be more contextual | ||
// 'async', | ||
// 'await', | ||
// Misc | ||
'global', | ||
'alias', | ||
'dynamic', | ||
'nameof', | ||
'notnull', | ||
'unmanaged', | ||
'var', | ||
'when', | ||
'yield' | ||
'where', | ||
'yield', | ||
), | ||
// We use this instead of type so 'void' is only treated as type in the right contexts | ||
return_type: $ => choice($._type, $.void_keyword), | ||
void_keyword: $ => 'void', | ||
_preprocessor_call: $ => seq( | ||
$._preproc_directive_start, | ||
choice( | ||
$.nullable_directive, | ||
$.define_directive, | ||
$.undef_directive, | ||
$.if_directive, | ||
$.else_directive, | ||
$.elif_directive, | ||
$.endif_directive, | ||
$.region_directive, | ||
$.endregion_directive, | ||
$.error_directive, | ||
$.warning_directive, | ||
$.line_directive, | ||
$.pragma_directive | ||
), | ||
$._preproc_directive_end | ||
), | ||
_preproc_directive_start: $ => /#[ \t]*/, | ||
nullable_directive: $ => seq( | ||
'nullable', | ||
choice('disable', 'enable', 'restore'), | ||
optional(choice('annotations', 'warnings')) | ||
), | ||
// Preprocessor | ||
define_directive: $ => seq('define', $.identifier), | ||
undef_directive: $ => seq('undef', $.identifier), | ||
if_directive: $ => seq('if', $._preproc_expression), | ||
else_directive: $ => 'else', | ||
elif_directive: $ => seq('elif', $._preproc_expression), | ||
endif_directive: $ => 'endif', | ||
region_directive: $ => seq('region', optional($.preproc_message)), | ||
endregion_directive: $ => seq('endregion', optional($.preproc_message)), | ||
error_directive: $ => seq('error', $.preproc_message), | ||
warning_directive: $ => seq('warning', $.preproc_message), | ||
line_directive: $ => seq('line', | ||
choice( | ||
'default', | ||
'hidden', | ||
seq($.preproc_integer_literal, optional($.preproc_string_literal)) | ||
) | ||
), | ||
pragma_directive: $ => seq('pragma', | ||
choice( | ||
seq('warning', | ||
choice('disable', 'restore'), | ||
commaSep( | ||
choice( | ||
$.identifier, | ||
alias($.preproc_integer_literal, $.integer_literal), | ||
))), | ||
seq('checksum', $.preproc_string_literal, $.preproc_string_literal, $.preproc_string_literal) | ||
) | ||
), | ||
...preprocIf('', $ => $.declaration), | ||
...preprocIf('_in_top_level', $ => choice($._top_level_item_no_statement, $.statement)), | ||
...preprocIf('_in_expression', $ => $.expression, -2, false), | ||
// ...preprocIf('_in_statement', $ => $.statement, -1), | ||
...preprocIf('_in_enum_member_declaration', $ => $.enum_member_declaration, 0, false), | ||
preproc_message: $ => /[^\n\r]+/, | ||
preproc_integer_literal: $ => /[0-9]+/, | ||
preproc_string_literal: $ => /"[^"]*"/, | ||
preproc_arg: _ => token(prec(-1, /\S([^/\n]|\/[^*]|\\\r?\n)*/)), | ||
preproc_directive: _ => /#[ \t]*[a-zA-Z0-9]\w*/, | ||
@@ -1824,7 +1908,7 @@ _preproc_expression: $ => choice( | ||
$.boolean_literal, | ||
alias($.preproc_integer_literal, $.integer_literal), | ||
alias($.preproc_string_literal, $.verbatim_string_literal), | ||
alias($.preproc_unary_expression, $.prefix_unary_expression), | ||
$.integer_literal, | ||
$.character_literal, | ||
alias($.preproc_unary_expression, $.unary_expression), | ||
alias($.preproc_binary_expression, $.binary_expression), | ||
alias($.preproc_parenthesized_expression, $.parenthesized_expression) | ||
alias($.preproc_parenthesized_expression, $.parenthesized_expression), | ||
), | ||
@@ -1835,3 +1919,3 @@ | ||
$._preproc_expression, | ||
')' | ||
')', | ||
), | ||
@@ -1841,3 +1925,3 @@ | ||
field('operator', '!'), | ||
field('argument', $._preproc_expression) | ||
field('argument', $._preproc_expression), | ||
)), | ||
@@ -1847,4 +1931,4 @@ | ||
const table = [ | ||
['||', PREC.LOGOR], | ||
['&&', PREC.LOGAND], | ||
['||', PREC.LOGICAL_OR], | ||
['&&', PREC.LOGICAL_AND], | ||
['==', PREC.EQUAL], | ||
@@ -1857,22 +1941,216 @@ ['!=', PREC.EQUAL], | ||
field('left', $._preproc_expression), | ||
// @ts-ignore | ||
field('operator', operator), | ||
field('right', $._preproc_expression) | ||
)) | ||
field('right', $._preproc_expression), | ||
)); | ||
})); | ||
}, | ||
preproc_region: $ => seq( | ||
preprocessor('region'), | ||
optional(field('content', $.preproc_arg)), | ||
/\n/, | ||
), | ||
preproc_endregion: $ => seq( | ||
preprocessor('endregion'), | ||
optional(field('content', $.preproc_arg)), | ||
/\n/, | ||
), | ||
preproc_line: $ => seq( | ||
preprocessor('line'), | ||
choice( | ||
'default', | ||
'hidden', | ||
seq($.integer_literal, optional($.string_literal)), | ||
seq( | ||
'(', $.integer_literal, ',', $.integer_literal, ')', | ||
'-', | ||
'(', $.integer_literal, ',', $.integer_literal, ')', | ||
optional($.integer_literal), | ||
$.string_literal, | ||
), | ||
), | ||
/\n/, | ||
), | ||
preproc_pragma: $ => seq( | ||
preprocessor('pragma'), | ||
choice( | ||
seq('warning', | ||
choice('disable', 'restore'), | ||
commaSep( | ||
choice( | ||
$.identifier, | ||
$.integer_literal, | ||
))), | ||
seq('checksum', $.string_literal, $.string_literal, $.string_literal), | ||
), | ||
/\n/, | ||
), | ||
preproc_nullable: _ => seq( | ||
preprocessor('nullable'), | ||
choice('enable', 'disable', 'restore'), | ||
optional(choice('annotations', 'warnings')), | ||
/\n/, | ||
), | ||
preproc_error: $ => seq( | ||
preprocessor('error'), | ||
$.preproc_arg, | ||
/\n/, | ||
), | ||
preproc_define: $ => seq( | ||
preprocessor('define'), | ||
$.preproc_arg, | ||
/\n/, | ||
), | ||
preproc_undef: $ => seq( | ||
preprocessor('undef'), | ||
$.preproc_arg, | ||
/\n/, | ||
), | ||
shebang_directive: _ => token(seq('#!', /.*/)), | ||
comment: _ => token(choice( | ||
seq('//', /[^\n\r]*/), | ||
seq( | ||
'/*', | ||
/[^*]*\*+([^/*][^*]*\*+)*/, | ||
'/', | ||
), | ||
)), | ||
}, | ||
}); | ||
/** | ||
* Creates a preprocessor regex rule | ||
* | ||
* @param {RegExp|Rule|String} command | ||
* | ||
* @return {AliasRule} | ||
*/ | ||
function preprocessor(command) { | ||
return alias(new RegExp('#[ \t]*' + command), '#' + command); | ||
} | ||
/** | ||
* | ||
* @param {string} suffix | ||
* | ||
* @param {RuleBuilder<string>} content | ||
* | ||
* @param {number} precedence | ||
* | ||
* @param {boolean} rep | ||
* | ||
* @return {RuleBuilders<string, string>} | ||
*/ | ||
function preprocIf(suffix, content, precedence = 0, rep = true) { | ||
/** | ||
* | ||
* @param {GrammarSymbols<string>} $ | ||
* | ||
* @return {ChoiceRule} | ||
* | ||
*/ | ||
function alternativeBlock($) { | ||
return choice( | ||
suffix ? alias($['preproc_else' + suffix], $.preproc_else) : $.preproc_else, | ||
suffix ? alias($['preproc_elif' + suffix], $.preproc_elif) : $.preproc_elif, | ||
); | ||
} | ||
}) | ||
function commaSep(rule) { | ||
return optional(commaSep1(rule)) | ||
return { | ||
['preproc_if' + suffix]: $ => prec(precedence, seq( | ||
preprocessor('if'), | ||
field('condition', $._preproc_expression), | ||
/\n/, | ||
rep ? repeat(content($)) : optional(content($)), | ||
field('alternative', optional(alternativeBlock($))), | ||
preprocessor('endif'), | ||
)), | ||
['preproc_else' + suffix]: $ => prec(precedence, seq( | ||
preprocessor('else'), | ||
rep ? repeat(content($)) : optional(content($)), | ||
)), | ||
['preproc_elif' + suffix]: $ => prec(precedence, seq( | ||
preprocessor('elif'), | ||
field('condition', $._preproc_expression), | ||
/\n/, | ||
rep ? repeat(content($)) : optional(content($)), | ||
field('alternative', optional(alternativeBlock($))), | ||
)), | ||
}; | ||
} | ||
/** | ||
* Creates a rule to match one or more of the rules separated by a comma | ||
* | ||
* @param {Rule} rule | ||
* | ||
* @return {SeqRule} | ||
* | ||
*/ | ||
function commaSep1(rule) { | ||
return seq( | ||
rule, | ||
repeat(seq( | ||
',', | ||
rule | ||
)) | ||
) | ||
return seq(rule, repeat(seq(',', rule))); | ||
} | ||
/** | ||
* Creates a rule to match two or more of the rules separated by a comma | ||
* | ||
* @param {Rule} rule | ||
* | ||
* @return {SeqRule} | ||
* | ||
*/ | ||
function commaSep2(rule) { | ||
return seq(rule, repeat1(seq(',', rule))); | ||
} | ||
/** | ||
* Creates a rule to optionally match one or more of the rules separated by a comma | ||
* | ||
* @param {Rule} rule | ||
* | ||
* @return {ChoiceRule} | ||
* | ||
*/ | ||
function commaSep(rule) { | ||
return optional(commaSep1(rule)); | ||
} | ||
/** | ||
* Creates a rule to match one or more of the rules separated by `separator` | ||
* | ||
* @param {RuleOrLiteral} rule | ||
* | ||
* @param {RuleOrLiteral} separator | ||
* | ||
* @return {SeqRule} | ||
* | ||
*/ | ||
function sep1(rule, separator) { | ||
return seq(rule, repeat(seq(separator, rule))); | ||
} | ||
/** | ||
* Creates a rule to optionally match one or more of the rules separated by `separator` | ||
* | ||
* @param {RuleOrLiteral} rule | ||
* | ||
* @param {RuleOrLiteral} separator | ||
* | ||
* @return {ChoiceRule} | ||
* | ||
*/ | ||
function sep(rule, separator) { | ||
return optional(sep1(rule, separator)); | ||
} |
109
package.json
{ | ||
"name": "tree-sitter-c-sharp", | ||
"version": "0.20.0", | ||
"version": "0.21.1", | ||
"description": "C# grammar for tree-sitter", | ||
"repository": "github:tree-sitter/tree-sitter-rust", | ||
"license": "MIT", | ||
"author": "Max Brunsfeld <maxbrunsfeld@gmail.com", | ||
"contributors": [ | ||
"Damien Guard <damieng@gmail.com>", | ||
"Amaan Qureshi <amaanq12@gmail.com>", | ||
"Martin Midtgaard <martin.midtgaard@gmail.com>", | ||
"Sjoerd Langkemper <sjoerd-github@linuxonly.nl>" | ||
], | ||
"maintainers": [ | ||
"Amaan Qureshi <amaanq12@gmail.com>" | ||
], | ||
"main": "bindings/node", | ||
"types": "bindings/node", | ||
"keywords": [ | ||
"parser", | ||
"incremental", | ||
"parsing", | ||
"tree-sitter", | ||
"lexer" | ||
"c-sharp" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/tree-sitter/tree-sitter-c-sharp.git" | ||
}, | ||
"author": "The Tree-Sitter C# Team", | ||
"license": "MIT", | ||
"files": [ | ||
"grammar.js", | ||
"binding.gyp", | ||
"prebuilds/**", | ||
"bindings/node/*", | ||
"queries/*", | ||
"src/**" | ||
], | ||
"dependencies": { | ||
"nan": "^2.14.0" | ||
"node-addon-api": "^8.0.0", | ||
"node-gyp-build": "^4.8.1" | ||
}, | ||
"peerDependencies": { | ||
"tree-sitter": "^0.21.0" | ||
}, | ||
"peerDependenciesMeta": { | ||
"tree_sitter": { | ||
"optional": true | ||
} | ||
}, | ||
"devDependencies": { | ||
"tree-sitter-cli": "^0.20.0" | ||
"eslint": "^8.57.0", | ||
"eslint-config-google": "^0.14.0", | ||
"tree-sitter-cli": "^0.22.5", | ||
"prebuildify": "^6.0.1" | ||
}, | ||
"scripts": { | ||
"test": "tree-sitter test && node test.js" | ||
"install": "node-gyp-build", | ||
"prebuildify": "prebuildify --napi --strip", | ||
"build": "tree-sitter generate --no-bindings", | ||
"build-wasm": "tree-sitter build --wasm", | ||
"lint": "eslint grammar.js", | ||
"parse": "tree-sitter parse", | ||
"test": "tree-sitter test" | ||
}, | ||
@@ -29,7 +63,56 @@ "tree-sitter": [ | ||
"scope": "source.cs", | ||
"injection-regex": "cs", | ||
"file-types": [ | ||
"cs" | ||
], | ||
"highlights": [ | ||
"queries/highlights.scm" | ||
], | ||
"tags": [ | ||
"queries/tags.scm" | ||
] | ||
} | ||
] | ||
], | ||
"eslintConfig": { | ||
"env": { | ||
"commonjs": true, | ||
"es2021": true | ||
}, | ||
"extends": "google", | ||
"parserOptions": { | ||
"ecmaVersion": "latest", | ||
"sourceType": "module" | ||
}, | ||
"rules": { | ||
"arrow-parens": "off", | ||
"camel-case": "off", | ||
"indent": [ | ||
"error", | ||
2, | ||
{ | ||
"SwitchCase": 1 | ||
} | ||
], | ||
"max-len": [ | ||
"error", | ||
{ | ||
"code": 160, | ||
"ignoreComments": true, | ||
"ignoreUrls": true, | ||
"ignoreStrings": true | ||
} | ||
], | ||
"spaced-comment": [ | ||
"warn", | ||
"always", | ||
{ | ||
"line": { | ||
"markers": [ | ||
"/" | ||
] | ||
} | ||
} | ||
] | ||
} | ||
} | ||
} |
# tree-sitter-c-sharp | ||
[![Build Status](https://github.com/tree-sitter/tree-sitter-c-sharp/workflows/build/badge.svg)](https://github.com/tree-sitter/tree-sitter-c-sharp/actions?query=workflow%3Abuild) | ||
[![CI][ci]](https://github.com/tree-sitter/tree-sitter-c-sharp/actions/workflows/ci.yml) | ||
[![discord][discord]](https://discord.gg/w7nTvsVJhm) | ||
[![matrix][matrix]](https://matrix.to/#/#tree-sitter-chat:matrix.org) | ||
[![crates][crates]](https://crates.io/crates/tree-sitter-c-sharp) | ||
[![npm][npm]](https://www.npmjs.com/package/tree-sitter-c-sharp) | ||
[![pypi][pypi]](https://pypi.org/project/tree-sitter-c-sharp) | ||
@@ -12,53 +17,11 @@ C# grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter) based upon the Roslyn grammar with changes in order to: | ||
- Simplify the output tree | ||
- Reduce parser state count and complexity | ||
- Be in-line with tree-sitter's convention where applicable | ||
### Status | ||
Comprehensive supports C# 1 through 10.0 with the following exceptions: | ||
Comprehensive supports C# 1 through 13.0 with the following exception: | ||
- [ ] `async`, `var` and `await` cannot be used as identifiers everywhere they are valid | ||
#### C# 9.0 (complete) | ||
- [x] Covariant returns | ||
- [x] Extending partial methods | ||
- [x] Extension GetEnumerator | ||
- [x] Function pointers | ||
- [x] Init properties | ||
- [x] Lambda discard parameters | ||
- [x] Local function attributes | ||
- [x] Module initializers | ||
- [x] Native integers | ||
- [x] Patterns | ||
- [x] Simple type patterns | ||
- [x] Relational patterns | ||
- [x] Logical patterns | ||
- [x] Records | ||
- [x] Skip Locals Init | ||
- [x] Static anonymous functions | ||
- [x] Target-typed conditional expression | ||
- [x] Target-typed new | ||
- [x] Top-level statements | ||
#### C# 10.0 | ||
- [x] global using directives | ||
- [x] File-scoped namespace declaration | ||
- [x] Extended property patterns | ||
- [x] Allow const interpolated strings | ||
- [x] Record types can seal ToString() | ||
- [x] Allow both assignment and declaration in the same deconstruction | ||
- [x] Allow AsyncMethodBuilder attribute on methods | ||
- [x] Record structs | ||
- [ ] Lambda improvements | ||
#### C# 11.0 (under development) | ||
- [x] Generic attributes | ||
- [x] Static abstract members in interfaces | ||
- [x] Newlines in string interpolations | ||
- [x] List patterns | ||
- [x] Slice pattern | ||
- [x] Required members | ||
- [ ] Raw string literals | ||
### References | ||
@@ -69,1 +32,8 @@ | ||
- [SharpLab](https://sharplab.io) (web-based syntax tree playground based on Roslyn) | ||
[ci]: https://img.shields.io/github/actions/workflow/status/tree-sitter/tree-sitter-c-sharp/ci.yml?logo=github&label=CI | ||
[discord]: https://img.shields.io/discord/1063097320771698699?logo=discord&label=discord | ||
[matrix]: https://img.shields.io/matrix/tree-sitter-chat%3Amatrix.org?logo=matrix&label=matrix | ||
[npm]: https://img.shields.io/npm/v/tree-sitter-c-sharp?logo=npm | ||
[crates]: https://img.shields.io/crates/v/tree-sitter-c-sharp?logo=rust | ||
[pypi]: https://img.shields.io/pypi/v/tree-sitter-c-sharp?logo=pypi&logoColor=ffd242 |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
56211089
20292
3
4
21
38
1
+ Addednode-addon-api@^8.0.0
+ Addednode-gyp-build@^4.8.1
+ Addednode-addon-api@8.0.0(transitive)
+ Addednode-gyp-build@4.8.1(transitive)
+ Addedtree-sitter@0.21.1(transitive)
- Removednan@^2.14.0
- Removednan@2.19.0(transitive)