Socket
Socket
Sign inDemoInstall

tree-sitter-c-sharp

Package Overview
Dependencies
3
Maintainers
6
Versions
13
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.20.0 to 0.21.1

bindings/node/index.d.ts

18

bindings/node/index.js

@@ -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 (_) {}

@@ -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));
}
{
"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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc