Socket
Socket
Sign inDemoInstall

tree-sitter-c-sharp

Package Overview
Dependencies
13
Maintainers
4
Versions
13
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.13.0 to 0.15.0

grammar.txt

1836

grammar.js
const PREC = {
DOT: 17,
SELECT: 16,
POSTFIX: 16,

@@ -21,4 +23,2 @@ PREFIX: 15,

const BYTE_ORDER_MARK = '\xEF\xBB\xBF';
module.exports = grammar({

@@ -29,95 +29,66 @@ name: 'c_sharp',

$.comment,
/\s+/
/[\s\u00A0]+/,
$.preprocessor_directive
],
conflicts: $ => [
[$.overloadable_unary_operator, $.overloadable_binary_operator],
[$.generic_name, $._expression],
[$.if_statement]
[$.block, $.initializer_expression],
[$.element_access_expression, $.enum_member_declaration],
[$.event_declaration, $.variable_declarator],
[$._expression, $.declaration_pattern],
[$._expression, $._simple_name],
[$._expression, $._simple_name, $.generic_name],
[$._expression, $._simple_name, $.parameter],
[$.from_clause, $._reserved_identifier],
[$._simple_name, $.enum_member_declaration],
[$._simple_name, $.type_parameter],
[$._simple_name, $.generic_name],
[$.qualified_name, $.explicit_interface_specifier],
[$._type, $.array_creation_expression],
[$._type, $.stack_alloc_array_creation_expression],
[$._type, $.attribute],
],
inline: $ => [
$.class_type,
$.return_type
$.return_type,
$._identifier_or_global,
],
word: $ => $.identifier_name,
word: $ => $.identifier,
rules: {
compilation_unit: $ => seq(
optional(BYTE_ORDER_MARK),
repeat($.extern_alias_directive),
repeat($.using_directive),
repeat($._global_attributes),
repeat(choice(
$.namespace_declaration,
$._type_declaration
))
),
// Intentionally deviates from spec so that we can syntax highlight fragments of code
compilation_unit: $ => repeat($._declaration),
// types
_type_declaration: $ => choice(
_declaration: $ => choice(
$.global_attribute_list,
$.class_declaration,
$.constructor_declaration,
$.conversion_operator_declaration,
$.delegate_declaration,
$.destructor_declaration,
$.enum_declaration,
$.event_declaration,
$.extern_alias_directive,
$.event_field_declaration,
$.field_declaration,
$.indexer_declaration,
$.interface_declaration,
$.method_declaration,
$.namespace_declaration,
$.operator_declaration,
$.property_declaration,
$.struct_declaration,
$.enum_declaration,
$.delegate_declaration,
$.interface_declaration
$.using_directive,
),
_type: $ => choice(
$.predefined_type,
$.identifier_name,
$.generic_name
),
extern_alias_directive: $ => seq('extern', 'alias', $.identifier, ';'),
predefined_type: $ => choice(
'bool',
'byte',
'char',
'decimal',
'double',
'float',
'int',
'long',
'object',
'sbyte',
'short',
'string',
'uint',
'ulong',
'ushort'
),
type_parameter_list: $ => seq('<', commaSep1($.type_parameter), '>'),
type_parameter: $ => $._type,
// modifiers
modifiers: $ => repeat1(
choice(
'abstract',
'async',
'extern',
'internal',
'new',
'override',
'private',
'protected',
'public',
'readonly',
'sealed',
'static',
'unsafe',
'virtual',
'volatile'
)
),
// extern
extern_alias_directive: $ => seq('extern', 'alias', $.identifier_name, ';'),
// using
using_directive: $ => seq(

@@ -129,213 +100,264 @@ 'using',

)),
choice(
$.qualified_name,
$.identifier_name
),
$._name,
';'
),
name_equals: $ => seq($.identifier_name, '='),
name_equals: $ => prec(1, seq($._identifier_or_global, '=')),
// namespace
identifier: $ => token(seq(optional('@'), /[a-zA-Z_][a-zA-Z_0-9]*/)), // identifier_token in Roslyn
global: $ => 'global',
_identifier_or_global: $ => choice($.global, $.identifier),
namespace_declaration: $ => seq(
'namespace',
_name: $ => choice(
$.alias_qualified_name,
$.qualified_name,
$._simple_name
),
alias_qualified_name: $ => seq($._identifier_or_global, '::', $._simple_name),
_simple_name: $ => choice(
$.generic_name,
$._identifier_or_global
),
generic_name: $ => seq($.identifier, $.type_argument_list),
// Intentionally different from Roslyn to avoid non-matching
// omitted_type_argument in a lot of unnecessary places.
type_argument_list: $ => seq(
'<',
choice(
$.qualified_name,
$.identifier_name
repeat(','),
commaSep1($._type),
),
'{',
repeat(choice(
$.namespace_declaration,
$.using_directive,
$._type_declaration
)),
'}',
optional(';')
'>'
),
// properties
qualified_name: $ => prec(PREC.DOT, seq($._name, '.', $._simple_name)),
property_declaration: $ => seq(
optional($._attributes),
optional($.modifiers),
$._type,
$.identifier_name,
$._property_body
attribute_list: $ => seq('[', optional($.attribute_target_specifier), commaSep1($.attribute), ']'),
attribute_target_specifier: $ => seq(
choice('field', 'event', 'method', 'param', 'property', 'return', 'type'),
':'
),
attribute: $ => seq($._name, optional($.attribute_argument_list)),
_property_body: $ => choice(
seq('{', $._accessor_declarations, '}', optional($._property_initializer)),
seq('=>', $._expression, ';')
attribute_argument_list: $ => seq(
'(',
commaSep($.attribute_argument),
')'
),
_property_initializer: $ => seq('=', $.variable_initializer, ';'),
_accessor_declarations: $ => choice(
seq($.get_accessor_declaration, optional($.set_accessor_declaration)),
seq($.set_accessor_declaration, optional($.get_accessor_declaration))
attribute_argument: $ => seq(
optional(choice($.name_equals,$.name_colon)),
$._expression
),
get_accessor_declaration: $ => seq(
optional($._attributes),
optional($.accessor_modifier),
'get',
choice($.statement_block, ';')
global_attribute_list: $ => seq(
'[',
choice('assembly', 'module'),
':',
commaSep($.attribute),
']'
),
set_accessor_declaration: $ => seq(
optional($._attributes),
optional($.accessor_modifier),
'set',
choice($.statement_block, ';')
name_colon: $ => seq($._identifier_or_global, ':'),
event_field_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
'event',
$.variable_declaration,
';'
),
accessor_modifier: $ => choice(
'protected',
modifier: $ => prec.right(choice(
'abstract',
'async',
'const',
'extern',
'fixed',
'internal',
'new',
'override',
'partial',
'private',
seq('protected', 'internal'),
seq('internal', 'protected')
'protected',
'public',
'readonly',
'ref',
'sealed',
'static',
'unsafe',
'virtual',
'volatile'
)),
variable_declaration: $ => seq($._type, commaSep1($.variable_declarator)),
variable_declarator: $ => seq(
$.identifier,
optional($.bracketed_argument_list),
optional($.equals_value_clause)
),
// class
bracketed_argument_list: $ => seq(
'[',
commaSep1($.argument),
']'
),
class_declaration: $ => seq(
optional($._attributes),
optional($.modifiers),
optional('partial'),
'class',
$.identifier_name,
optional($.type_parameter_list),
optional($.class_base),
repeat($.type_parameter_constraints_clause),
'{',
repeat(
choice(
$.constant_declaration,
$.field_declaration,
$.method_declaration,
$.property_declaration,
$.event_declaration,
$.indexer_declaration,
$.operator_declaration,
$.constructor_declaration,
$.destructor_declaration,
$._type_declaration
),
argument: $ => prec(1, seq(
optional($.name_colon),
choice(
seq(
optional(choice('ref','out', 'in')),
$._expression
),
'}',
optional(';')
),
seq(
'out',
$._type,
$.identifier
)
)
)),
class_base: $ => seq(
':',
$.class_type,
optional(seq(', ', commaSep1($.identifier_name)))
equals_value_clause: $ => seq('=', $._expression),
field_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
$.variable_declaration,
';'
),
class_type: $ => choice(
$.identifier_name,
'object',
'dynamic',
'string'
constructor_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
$.identifier,
$.parameter_list,
optional($.constructor_initializer),
$._function_body
),
type_parameter_constraints_clause: $ => seq(
'where', $.identifier_name, ':', $.type_parameter_constraints
// Params varies quite a lot from grammar.txt as that handles neither 'out' nor 'params' or arrays...
parameter_list: $ => seq(
'(',
optional($._formal_parameter_list),
')'
),
type_parameter_constraints: $ => choice(
$.constructor_constraint,
seq(
choice(
$.class_type,
'class',
'struct'
),
optional(seq(',', commaSep1($.identifier_name))),
optional(seq(',', $.constructor_constraint))
)
_formal_parameter_list: $ => commaSep1(choice(
$.parameter,
$.parameter_array
)),
parameter: $ => seq(
repeat($.attribute_list),
optional($.parameter_modifier),
optional($._type),
$.identifier,
optional($.equals_value_clause)
),
constructor_constraint: $ => seq('new', '(', ')'),
parameter_modifier: $ => prec.right(choice('ref', 'out', 'this', 'in')),
// indexers
parameter_array: $ => seq(
repeat($.attribute_list),
'params',
$.array_type,
$.identifier
),
indexer_declaration: $ => seq(
optional($._attributes),
optional($.modifiers),
$._indexer_declarator,
$._indexer_body
constructor_initializer: $ => seq(
':',
choice('base', 'this'),
$.argument_list
),
_indexer_declarator: $ => choice(
seq($._type, 'this', '[', $._formal_parameter_list, ']'),
seq(
$._type,
$.identifier_name,
'.',
'this',
'[',
$._formal_parameter_list,
']'
argument_list: $ => seq('(', commaSep($.argument), ')'),
block: $ => seq('{', repeat($._statement), '}'),
arrow_expression_clause: $ => seq('=>', $._expression),
conversion_operator_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
choice(
'implicit',
'explicit'
),
'operator',
$._type,
$.parameter_list,
$._function_body,
),
_indexer_body: $ => choice(
seq('{', $._accessor_declarations, '}'),
seq('=>', $._expression, ';'),
_function_body: $ => choice(
$.block,
seq($.arrow_expression_clause, ';'),
';' // Only applies to interfaces
),
// events
destructor_declaration: $ => seq(
repeat($.attribute_list),
optional('extern'),
'~',
$.identifier,
$.parameter_list,
$._function_body
),
event_declaration: $ => seq(
optional($._attributes),
optional($.modifiers),
'event',
$._type,
$.identifier_name,
'{',
choice(
seq($.add_accessor_declaration, $.remove_accessor_declaration),
seq($.remove_accessor_declaration, $.add_accessor_declaration)
),
'}'
),
method_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
$.return_type,
optional($.explicit_interface_specifier),
$.identifier,
optional($.type_parameter_list),
$.parameter_list,
repeat($.type_parameter_constraints_clause),
$._function_body,
),
add_accessor_declaration: $ => seq(optional($._attributes), 'add', $.statement_block),
remove_accessor_declaration: $ => seq(optional($._attributes), 'remove', $.statement_block),
explicit_interface_specifier: $ => prec(PREC.DOT, seq($._name, '.')),
// operator declarations
type_parameter_list: $ => seq('<', commaSep1($.type_parameter), '>'),
operator_declaration: $ => seq(
optional($._attributes),
optional($.modifiers),
$._operator_declarator,
choice(
$.statement_block,
seq('=>', $._expression, ';'),
';'
)
type_parameter: $ => seq(
optional($.attribute_list),
optional(choice('in', 'out')),
$.identifier
),
_operator_declarator: $ => choice(
$._unary_operator_declarator,
$._binary_operator_declarator,
$._conversion_operator_declarator
type_parameter_constraints_clause: $ => seq(
'where', $._identifier_or_global, ':', commaSep1($.type_parameter_constraint)
),
_unary_operator_declarator: $ => seq(
type_parameter_constraint: $ => choice(
'class',
'struct',
'unmanaged',
$.constructor_constraint,
$.type_constraint
),
constructor_constraint: $ => seq('new', '(', ')'),
type_constraint: $ => $._type,
operator_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
$._type,
'operator',
$.overloadable_unary_operator,
'(',
$._type,
$.identifier_name,
')'
$._overloadable_operator,
$.parameter_list,
$._function_body,
),
overloadable_unary_operator: $ => choice(
'+',
'-',
_overloadable_operator: $ => choice(
'!',

@@ -346,19 +368,3 @@ '~',

'true',
'false'
),
_binary_operator_declarator: $ => seq(
$._type,
'operator',
$.overloadable_binary_operator,
'(',
$._type,
$.identifier_name,
',',
$._type,
$.identifier_name,
')'
),
overloadable_binary_operator: $=> choice(
'false',
'+', '-',

@@ -374,677 +380,1015 @@ '*', '/',

_conversion_operator_declarator: $=> seq(
$.overloadable_conversion_operator,
'operator',
event_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
'event',
$._type,
'(',
optional($.explicit_interface_specifier),
$.identifier,
choice(
$._accessor_list,
';'
)
),
_accessor_list: $ => seq(
'{',
repeat($.accessor_declaration),
'}'
),
accessor_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
choice('get', 'set', 'add', 'remove', $.identifier),
$._function_body
),
indexer_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
$._type,
$.identifier_name,
')'
optional($.explicit_interface_specifier),
'this',
$.bracketed_parameter_list,
choice(
$._accessor_list,
seq($.arrow_expression_clause, ';')
)
),
overloadable_conversion_operator: $ => choice(
'implicit',
'explicit'
bracketed_parameter_list: $ => seq('[', commaSep1($.parameter), ']'),
property_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
$._type,
optional($.explicit_interface_specifier),
$.identifier,
choice(
seq($._accessor_list, optional(seq('=', $._expression, ';'))), // grammar.txt does not allow bodyless properties.
seq($.arrow_expression_clause, ';')
),
),
// interface
enum_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
'enum',
$.identifier,
optional($.base_list),
$.enum_member_declaration_list,
optional(';')
),
interface_declaration: $ => seq(
optional($._attributes),
optional($.modifiers),
optional('partial'),
'interface',
$.identifier_name,
optional($.type_parameter_list),
optional($.interface_base),
repeat($.type_parameter_constraints_clause),
base_list: $ => seq(':', commaSep1($._type)),
enum_member_declaration_list: $ => seq(
'{',
repeat(
choice(
$.interface_method_declaration,
$.interface_event_declaration,
$.interface_property_declaration,
$.interface_indexer_declaration
)
),
commaSep($.enum_member_declaration),
optional(','),
'}',
optional(';')
),
interface_base: $ => seq(
':',
$.identifier_name,
optional(seq(',', commaSep1($.identifier_name)))
enum_member_declaration: $ => seq(
repeat($.attribute_list),
$.identifier,
optional(seq('=', $._expression))
),
interface_method_declaration: $ => seq(
optional($._attributes),
optional('new'),
$.return_type,
$.identifier_name,
class_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
'class',
$.identifier,
optional($.type_parameter_list),
optional($.parameter_list),
optional($.base_list),
repeat($.type_parameter_constraints_clause),
';'
$.declaration_list,
optional(';')
),
interface_event_declaration: $ => seq(
optional($._attributes),
optional('new'),
'event',
$._type,
$.identifier_name,
';'
),
interface_property_declaration: $ => seq(
optional($._attributes),
optional('new'),
$._type,
$.identifier_name,
declaration_list: $ => seq(
'{',
repeat1($.interface_accessor),
repeat($._declaration),
'}'
),
interface_accessor: $ => seq(optional($._attributes), choice('get', 'set'), ';'),
interface_indexer_declaration: $ => seq(
optional($._attributes),
optional('new'),
$._type,
'this',
'[',
$._formal_parameter_list,
']',
'{',
repeat1($.interface_accessor),
'}'
interface_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
'interface',
$.identifier,
optional($.type_parameter_list),
optional($.base_list),
repeat($.type_parameter_constraints_clause),
$.declaration_list,
optional(';')
),
// struct
struct_declaration: $ => seq(
optional($._attributes),
optional($.modifiers),
optional('partial'),
repeat($.attribute_list),
repeat($.modifier),
'struct',
$.identifier_name,
$.identifier,
optional($.type_parameter_list),
optional($.struct_interfaces),
optional($.base_list),
repeat($.type_parameter_constraints_clause),
'{',
repeat(
choice(
$.constant_declaration,
$.field_declaration,
$.method_declaration,
$.property_declaration,
$.event_declaration,
$.indexer_declaration,
$.operator_declaration,
$.constructor_declaration,
$._type_declaration
)
),
'}',
$.declaration_list,
optional(';')
),
struct_interfaces: $ => seq(':', commaSep1($.identifier_name)),
delegate_declaration: $ => seq(
repeat($.attribute_list),
repeat($.modifier),
'delegate',
$.return_type,
$.identifier,
optional($.type_parameter_list),
$.parameter_list,
repeat($.type_parameter_constraints_clause),
';'
),
// enum
enum_declaration: $ => seq(
optional($._attributes),
optional($.modifiers),
'enum',
$.identifier_name,
optional(seq(':', $._integral_type)),
'{',
commaSep1($.enum_member_declaration),
'}',
namespace_declaration: $ => seq(
'namespace',
$._name,
$.declaration_list,
optional(';')
),
enum_member_declaration: $ => seq(
optional($._attributes),
$.identifier_name,
optional(seq('=', $.constant_expression))
_type: $ => choice(
$.implicit_type,
$.array_type,
$._name,
$.nullable_type,
$.pointer_type,
$.predefined_type,
// $.ref_type, // TODO: Conflicts with 'ref' modifier...
// $.tuple_type, // TODO: Conflicts with everything
),
_integral_type: $ => choice(
implicit_type: $ => 'var',
array_type: $ => prec(PREC.POSTFIX, seq($._type, $.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)), ']'),
nullable_type: $ => prec(1, seq($._type, '?')),
pointer_type: $ => prec(1, seq($._type, '*')),
predefined_type: $ => choice(
'bool',
'byte',
'char',
'decimal',
'double',
'float',
'int',
'long',
'object',
'sbyte',
'byte',
'short',
'ushort',
'int',
'string',
'uint',
'long',
'ulong',
'char'
'ushort',
// void is handled in return_type for better matching
),
// delegate
delegate_declaration: $ => seq(
optional($._attributes),
optional($.modifiers),
'delegate',
$.return_type,
$.identifier_name,
// TODO: Variant type parameters
$.parameter_list,
';'
ref_type: $ => seq(
'ref',
optional('readonly'),
$._type
),
return_type: $ => choice($._type, $.void_keyword),
void_keyword: $ => 'void',
// parameters
parameter_list: $ => seq(
tuple_type: $ => seq(
'(',
optional($._formal_parameter_list),
$.tuple_element,
repeat1(seq(
',',
$.argument,
)),
')'
),
_formal_parameter_list: $ => choice(
commaSep1($.parameter),
seq(commaSep1($.parameter), $.parameter_array),
$.parameter_array
),
tuple_element: $ => seq($._type, optional($.identifier)),
parameter: $ => seq(
optional($._attributes),
optional($.parameter_modifier),
$._type,
$.identifier_name,
optional($.default_argument)
_statement: $ => choice(
$.block,
$.break_statement,
$.checked_statement,
$.continue_statement,
$.do_statement,
$.empty_statement,
$.expression_statement,
$.fixed_statement,
$.for_each_statement,
$.for_statement,
$.goto_statement,
$.if_statement,
$.labeled_statement,
$.local_declaration_statement,
$.local_function_statement,
$.lock_statement,
$.return_statement,
$.switch_statement,
$.throw_statement,
$.try_statement,
$.unsafe_statement,
$.using_statement,
$.while_statement,
$.yield_statement,
),
default_argument: $ => seq('=', $._expression),
parameter_modifier: $ => choice('ref', 'out', 'this'),
break_statement: $ => seq('break', ';'),
parameter_array: $ => seq(
optional($._attributes),
'params',
$.array_type,
$.identifier_name
),
checked_statement: $ => seq(choice('checked', 'unchecked'), $.block),
// arrays
continue_statement: $ => seq('continue', ';'),
array_type: $ => seq($._type, $.array_rank_specifier),
array_rank_specifier: $ => seq('[', repeat(','), ']'),
do_statement: $ => seq('do', $._statement, 'while', '(', $._expression, ')', ';'),
// attributes
empty_statement: $ => ';',
_attributes: $ => repeat1($._attribute_section),
_attribute_section: $ => seq('[', $.attribute_list, ']'),
attribute_list: $ => commaSep1($.attribute),
attribute: $ => seq($.identifier_name, optional($.attribute_argument_list)),
expression_statement: $ => seq($._expression, ';'),
attribute_argument_list: $ => seq(
fixed_statement: $ => seq('fixed', '(', $.variable_declaration, ')', $._statement),
for_statement: $ => seq(
'for',
'(',
// TODO: attribute_arguments
')'
optional(choice($.variable_declaration, commaSep1($._expression))),
';',
optional($._expression),
';',
optional(commaSep1($._expression)),
')',
$._statement
),
_global_attributes: $ => seq(
'[',
choice('assembly', 'module'),
':',
$.attribute_list,
']'
// Combines for_each_statement and for_each_variable_statement from grammar.txt
for_each_statement: $ => seq(
optional('await'),
'foreach',
'(',
choice(
seq($._type, $.identifier), // for_each_statement
$._expression, // for_each_variable_statement
),
'in',
$._expression,
')',
$._statement
),
// fields
field_declaration: $ => seq(
optional($._attributes),
optional($.modifiers),
$.variable_declaration,
// grammar.txt one doesn't seem to make sense so we do this instead
goto_statement: $ => seq(
'goto',
choice(
alias($.identifier, $.label_name),
seq('case', $._expression),
'default'
),
';'
),
variable_declaration: $ => seq($._type, commaSep1($.variable_declarator)),
generic_name: $ => seq($.identifier_name, $.type_parameter_list),
variable_declarator: $ => seq($.identifier_name, optional($.equals_value_clause)),
variable_initializer: $ => choice(
if_statement: $ => prec.right(seq(
'if',
'(',
$._expression,
$.array_initalizer
),
')',
$._statement,
optional($.else_clause)
)),
array_initalizer: $ => seq('{', commaSep1($.variable_initializer), '}'),
equals_value_clause: $ => seq('=', $._expression),
else_clause: $ => seq('else', $._statement),
// constants
labeled_statement: $ => seq(
alias($.identifier, $.label_name),
':',
$._statement
),
constant_declaration: $ => seq(
optional($._attributes),
optional($.modifiers),
'const',
$._type,
$._constant_declarators,
local_declaration_statement: $ => seq(
optional('await'),
optional('using'),
repeat($.modifier),
$.variable_declaration,
';'
),
_constant_declarators: $ => seq(
$.constant_declarator,
repeat(seq(',', $.constant_declarator))
local_function_statement: $ => seq(
repeat($.modifier),
$.return_type,
$.identifier,
optional($.type_parameter_list),
$.parameter_list,
repeat($.type_parameter_constraints_clause),
$._function_body
),
constant_declarator: $ => seq($.identifier_name, '=', $.constant_expression),
lock_statement: $ => seq('lock', '(', $._expression, ')', $._statement),
// expressions
return_statement: $ => seq('return', optional($._expression), ';'),
_expression: $ => choice(
$.identifier_name,
$._literal,
$.ternary_expression,
$.binary_expression,
$.unary_expression,
$.parenthesized_expression
switch_statement: $ => seq(
'switch',
'(',
$._expression,
')',
'{',
repeat($.switch_section),
'}'
),
boolean_expression: $ => $._expression,
constant_expression: $ => $._expression,
parenthesized_expression: $ => seq('(', $._expression, ')'),
ternary_expression: $ => prec.right(PREC.COND, seq(
$._expression, '?', $._expression, ':', $._expression
switch_section: $ => prec.left(seq(
repeat1(choice( // switch_label
$.case_switch_label,
$.case_pattern_switch_label,
$.default_switch_label
)),
repeat1($._statement)
)),
binary_expression: $ => choice(
...[
['&&', PREC.LOGAND],
['||', PREC.LOGOR],
['>>', PREC.SHIFT],
['<<', PREC.SHIFT],
['&', PREC.AND],
['^', PREC.OR],
['|', 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($._expression, operator, $._expression))
)
case_pattern_switch_label: $ => seq(
'case',
$._pattern,
optional($.when_clause),
':'
),
unary_expression: $ => prec.right(PREC.UNARY, choice(
...[
'!',
'~',
'-',
'+',
'--',
'++',
'typeof',
'sizeof'
].map(operator => seq(operator, $._expression)))),
_pattern: $ => choice(
$.constant_pattern,
$.declaration_pattern,
$.discard,
// $.recursive_pattern,
$.var_pattern
),
// TODO, hook this up and fix issues with it
postfix_expression: $ => prec.left(PREC.POSTFIX, choice(
seq($._expression, '++'),
seq($._expression, '--'),
)),
constant_pattern: $ => prec.right($._expression),
// literals
declaration_pattern: $ => seq($._type, $._variable_designation),
_literal: $ => choice(
$.boolean_literal,
$.character_literal,
$.integer_literal,
$.null_literal,
$.real_literal,
$.string_literal
_variable_designation: $ => choice(
$.discard,
$.parenthesized_variable_designation,
$.identifier
),
boolean_literal: $ => choice(
'true',
'false'
discard: $ => '_',
parenthesized_variable_designation: $ => seq(
'(',
commaSep($._variable_designation),
')'
),
character_literal: $ => seq(
"'",
choice(
/[^']/,
$._simple_escape_sequence,
$._hexadecimal_escape_sequence,
$._unicode_escape_sequence
),
"'"
// TODO: Matches everything as optional which won't work.
// Figure out valid combinations with at least one item to remove ambiguity.
recursive_pattern: $ => seq(
optional($._type),
optional($.positional_pattern_clause),
optional($.property_pattern_clause),
optional($._variable_designation)
),
_hexadecimal_escape_sequence: $ =>
(/\\x[0-9a-fA-F][0-9a-fA-F]?[0-9a-fA-F]?[0-9a-fA-F]?/),
positional_pattern_clause: $ => seq('(', commaSep($.subpattern), ')'),
_unicode_escape_sequence: $ => choice(
(/\\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]/)
subpattern: $ => seq(
optional($.name_colon),
$._pattern
),
_simple_escape_sequence: $ => choice(
"\\'",
'\\"',
'\\\\',
'\\0',
'\\a',
'\\b',
'\\f',
'\\n',
'\\r',
'\\t',
'\\v'
property_pattern_clause: $ => seq(
'{',
commaSep($.subpattern),
'}'
),
integer_literal: $ => seq(
choice(
(/[0-9]+/),
(/0x[0-9a-fA-F]+/)
),
optional($._integer_type_suffix)
var_pattern: $ => prec(1, seq('var', $._variable_designation)),
when_clause: $ => seq('when', $._expression),
case_switch_label: $ => prec.left(1, seq('case', $._expression, ':')),
default_switch_label: $ => prec.left(1, seq('default', ':')),
throw_statement: $ => seq('throw', optional($._expression), ';'),
try_statement: $ => seq(
'try',
$.block,
repeat($.catch_clause),
optional($.finally_clause),
),
_integer_type_suffix: $ => (/u|U|l|L|ul|UL|uL|Ul|lu|LU|Lu|lU/),
catch_clause: $ => seq(
'catch',
optional($.catch_declaration),
optional($.catch_filter_clause),
$.block
),
null_literal: $ => 'null',
catch_declaration: $ => seq('(', $._type, optional($.identifier), ')'),
real_literal: $ => choice(
seq(
(/[0-9]+/),
'.',
(/[0-9]+/),
optional($._exponent_part),
optional($._real_type_suffix)
catch_filter_clause: $ => seq('when', '(', $._expression, ')'),
finally_clause: $ => seq('finally', $.block),
unsafe_statement: $ => seq('unsafe', $.block),
using_statement: $ => seq(
optional('await'),
'using',
'(',
choice($.variable_declaration, $._expression),
')',
$._statement
),
while_statement: $ => seq('while', '(', $._expression, ')', $._statement),
yield_statement: $ => seq(
'yield',
choice( // grammar.txt incorrectly allows "break expression", we do not.
seq('return', $._expression),
'break'
),
seq(
'.',
(/[0-9]+/),
optional($._exponent_part),
optional($._real_type_suffix)
),
seq(
(/[0-9]+/),
$._exponent_part,
optional($._real_type_suffix)
),
seq(
(/[0-9]+/),
$._real_type_suffix
)
';'
),
_real_type_suffix: $ => (/[fFdDmm]/),
anonymous_method_expression: $ => seq(
optional('async'),
'delegate',
optional($.parameter_list),
$.block
),
_exponent_part: $ => (/[eE][+-]?[0-9]+/),
lambda_expression: $ => prec(-1, seq(
optional('async'),
choice($.parameter_list, $.identifier),
'=>',
choice($.block, $._expression)
)),
string_literal: $ => choice(
$._regular_string_literal,
$._verbatim_string_literal
anonymous_object_creation_expression: $ => seq(
'new',
'{',
commaSep($._anonymous_object_member_declarator),
optional(','),
'}'
),
_regular_string_literal: $ => seq(
'"',
repeat($._regular_string_literal_character),
'"'
_anonymous_object_member_declarator: $ => choice(
prec.dynamic(PREC.ASSIGN, seq($.name_equals, $._expression)),
$._expression
),
_regular_string_literal_character: $ => choice(
/[^"\\\n]/,
$._simple_escape_sequence,
$._hexadecimal_escape_sequence,
$._unicode_escape_sequence
array_creation_expression: $ => seq(
'new',
$.array_type,
optional($.initializer_expression)
),
_verbatim_string_literal: $ => seq(
'@"',
/[^"]*/,
'"'
initializer_expression: $ => seq(
'{',
commaSep($._expression),
optional(','),
'}'
),
// names
assignment_expression: $ => prec.right(seq(
$._expression,
$.assignment_operator,
$._expression
)),
qualified_name: $ => seq(
choice(
$.identifier_name,
$.qualified_name,
$.alias_qualified_name
),
'.',
$.identifier_name
assignment_operator: $ => choice('=', '+=', '-=', '*=', '/=', '%=', '&=', '^=', '|=', '<<=', '>>=', '??='),
await_expression: $ => prec.right(PREC.UNARY, seq('await', $._expression)),
cast_expression: $ => prec.right(PREC.CAST, seq(
'(',
$._type,
')',
$._expression
)),
checked_expression: $ => choice(
seq('checked', '(', $._expression, ')'),
seq('unchecked', '(', $._expression, ')')
),
alias_qualified_name: $ => seq('global', '::', $.identifier_name),
identifier_name: $ => /[a-zA-Z_][a-zA-Z_0-9]*/,
conditional_access_expression: $ => prec.right(seq(
$._expression,
'?',
$._expression
)),
// commments
conditional_expression: $ => prec.right(PREC.COND, seq(
$._expression, '?', $._expression, ':', $._expression
)),
comment: $ => token(choice(
seq('//', /.*/),
seq(
'/*',
repeat(choice(
/[^*]/,
/\*[^/]/
)),
'*/'
declaration_expression: $ => seq(
$._type,
$._variable_designation
),
default_expression: $ => prec.right(seq(
'default',
optional(
seq(
'(',
$._type,
')'
)
)
)),
// methods
element_access_expression: $ => seq($._expression, $.bracketed_argument_list),
constructor_declaration: $ => seq(
optional($._attributes),
optional($.modifiers),
$.identifier_name,
optional($.type_parameter_list),
$.parameter_list,
$.statement_block
element_binding_expression: $ => $.bracketed_argument_list,
implicit_array_creation_expression: $ => seq(
'new',
'[',
repeat(','),
']',
$.initializer_expression
),
destructor_declaration: $ => seq(
optional($._attributes),
optional('extern'),
'~',
$.identifier_name,
$.parameter_list,
$.statement_block
implicit_stack_alloc_array_creation_expression: $ => seq(
'stackalloc',
'[',
']',
$.initializer_expression
),
method_declaration: $ => seq(
optional($._attributes),
optional($.modifiers),
optional('partial'),
$.return_type,
$.identifier_name,
optional($.type_parameter_list),
$.parameter_list,
repeat($.type_parameter_constraints_clause),
$.statement_block
base_expression: $ => 'base',
this_expression: $ => 'this',
interpolated_string_expression: $ => choice(
seq('$"', repeat($._interpolated_string_content), '"'),
seq('$@"', repeat($._interpolated_verbatim_string_content), '"'),
),
// Statements
_interpolated_string_content: $ => choice(
$.interpolated_string_text,
$.interpolation
),
_statement: $ => choice(
$._labeled_statement,
$._embedded_statement,
$._declaration_statement,
$.variable_assignment_statement // TODO: Remove
_interpolated_verbatim_string_content: $ => choice(
$.interpolated_verbatim_string_text,
$.interpolation
),
variable_assignment_statement: $ => seq($.identifier_name, $.equals_value_clause, ';'),
interpolated_string_text: $ => choice(
'{{',
token.immediate(prec(1, /[^{"\\\n]+/)),
$.escape_sequence
),
statement_block: $ => seq('{', optional($._statement_list), '}'),
_statement_list: $ => repeat1($._statement),
_labeled_statement: $ => seq(
alias($.identifier_name, $.label_name),
':',
$._statement
interpolated_verbatim_string_text: $ => choice(/[^{"]+/, '""'),
interpolation: $ => seq(
'{',
$._expression,
optional($.interpolation_alignment_clause),
optional($.interpolation_format_clause),
'}'
),
// Embedded statements
interpolation_alignment_clause: $ => seq(',', $._expression),
_embedded_statement: $ => choice(
$.statement_block,
$.empty_statement,
$.expression_statement,
$._selection_statement,
$._iteration_statement,
$._jump_statement,
$.try_statement,
$.checked_statement,
$.unchecked_statement,
$.lock_statement,
$.yield_statement
interpolation_format_clause: $ => seq(':', /[^}"]+/),
invocation_expression: $ => seq(
$._expression,
$.argument_list
),
empty_statement: $ => ';',
expression_statement: $ => seq($._expression, ';'),
is_pattern_expression: $ => prec.left(PREC.EQUAL, seq(
$._expression,
'is',
$._pattern
)),
_selection_statement: $ => choice(
$.if_statement,
$.switch_statement
make_ref_expression: $ => seq(
'__makeref',
'(',
$._expression,
')'
),
_iteration_statement: $ => choice(
$.while_statement,
$.do_statement
member_access_expression: $ => prec(PREC.DOT, seq(
$._expression,
choice('.', '->'),
$._simple_name
)),
member_binding_expression: $ => seq(
'.',
$._simple_name,
),
_jump_statement: $ => choice(
$.break_statement,
$.continue_statement,
$.goto_statement,
$.return_statement,
$.throw_statement
object_creation_expression: $ => prec.right(seq(
'new',
$._type,
optional($.argument_list),
optional($.initializer_expression)
)),
parenthesized_expression: $ => seq('(', $._expression, ')'),
postfix_unary_expression: $ => prec.left(PREC.POSTFIX, choice(
seq($._expression, '++'),
seq($._expression, '--'),
seq($._expression, '!')
)),
prefix_unary_expression: $ => prec.right(PREC.UNARY, choice(
...[
'!',
'&',
'*',
'+',
'++',
'-',
'--',
'^',
'~'
].map(operator => seq(operator, $._expression)))),
query_expression: $ => seq($.from_clause, $._query_body),
from_clause: $ => seq(
'from',
optional($._type),
$.identifier,
'in',
$._expression
),
try_statement: $ => seq(
'try',
$.statement_block,
repeat($.catch_clause),
optional($.finally_clause),
_query_body: $ => prec.right(seq(
repeat($._query_clause), // grammar.txt is incorrect with '+'
$._select_or_group_clause,
optional($.query_continuation)
)),
_query_clause: $ => choice(
$.from_clause,
$.join_clause,
$.let_clause,
$.order_by_clause,
$.where_clause
),
catch_clause: $ => seq(
'catch',
optional($._exception_specifier),
optional($._exception_filter),
$.statement_block
join_clause: $ => seq(
'join',
optional($._type),
$.identifier,
'in',
$._expression,
'on',
$._expression,
'equals',
$._expression,
optional($.join_into_clause)
),
_exception_specifier: $ => seq('(', $._type, optional($.identifier_name), ')'),
_exception_filter: $ => seq('when', '(', $._expression, ')'),
finally_clause: $ => seq('finally', $.statement_block),
join_into_clause: $ => seq('into', $.identifier),
checked_statement: $ => seq('checked', $.statement_block),
unchecked_statement: $ => seq('unchecked', $.statement_block),
lock_statement: $ => seq('lock', '(', $._expression, ')', $._embedded_statement),
let_clause: $ => seq(
'let',
$.identifier,
'=',
$._expression
),
yield_statement: $ => seq(
'yield',
choice(
seq('return', $._expression),
'break'
),
';'
order_by_clause: $ => seq(
'orderby',
commaSep1($._ordering)
),
if_statement: $ => seq(
'if',
_ordering: $ => seq(
$._expression,
optional(choice('ascending', 'descending'))
),
where_clause: $ => seq('where', $._expression),
_select_or_group_clause: $ => choice(
$.group_clause,
$.select_clause
),
group_clause: $ => prec.left(PREC.SELECT, seq(
'group',
$._expression,
'by',
$._expression
)),
select_clause: $ => prec.left(PREC.SELECT, seq('select', $._expression)),
query_continuation: $ => seq('into', $.identifier, $._query_body),
range_expression: $ => prec.right(seq(
optional($._expression),
'..',
optional($._expression)
)),
ref_expression: $ => prec.right(seq('ref', $._expression)),
ref_type_expression: $ => seq(
'__reftype',
'(',
$.boolean_expression,
')',
$._embedded_statement,
optional(
seq(
'else',
$._embedded_statement,
)
)
$._expression,
')'
),
switch_statement: $ => seq(
'switch',
ref_value_expression: $ => seq(
'__refvalue',
'(',
$._expression,
')',
'{',
repeat($.switch_section),
'}'
',',
$._type,
')'
),
switch_section: $ => seq(repeat1($.switch_label), $._statement_list),
switch_label: $ => choice(
seq('case', $.constant_expression, ':'),
seq('default', ':')
size_of_expression: $ => seq(
'sizeof',
'(',
$._type,
')'
),
while_statement: $ => seq('while', '(', $.boolean_expression, ')', $._embedded_statement),
do_statement: $ => seq('do', $._embedded_statement, 'while', '(', $.boolean_expression, ')', ';'),
stack_alloc_array_creation_expression: $ => seq(
'stackalloc',
$.array_type,
optional($.initializer_expression)
),
break_statement: $ => seq('break', ';'),
continue_statement: $ => seq('continue', ';'),
return_statement: $ => seq('return', optional($._expression), ';'),
throw_statement: $ => seq('throw', optional($._expression), ';'),
switch_expression: $ => seq(
$._expression,
'switch',
'{',
commaSep($.switch_expression_arm),
'}',
),
goto_statement: $ => seq(
'goto',
choice(
alias($.identifier_name, $.label_name),
seq('case', $.constant_expression),
'default'
),
';'
switch_expression_arm: $ => seq(
$._pattern,
optional($.when_clause),
'=>',
$._expression
),
// declaration statements
throw_expression: $ => prec.right(seq('throw', $._expression)),
_declaration_statement: $ => seq(
choice(
$.local_variable_declaration,
$.local_constant_declaration
),
';'
tuple_expression: $ => seq(
'(',
$.argument,
repeat1(seq(
',',
$.argument,
)),
')'
),
local_variable_declaration: $ => seq(
$._local_variable_type,
$._local_variable_declarators
type_of_expression: $ => seq('typeof', '(', $._type, ')'),
// TODO: Expressions need work on precedence and conflicts.
_expression: $ => choice(
$.anonymous_method_expression,
$.anonymous_object_creation_expression,
$.array_creation_expression,
$.assignment_expression,
$.await_expression,
$.base_expression,
$.binary_expression,
$.cast_expression,
$.checked_expression,
$.conditional_access_expression,
$.conditional_expression,
// $.declaration_expression,
$.default_expression,
$.element_access_expression,
$.element_binding_expression,
$.implicit_array_creation_expression,
$.implicit_stack_alloc_array_creation_expression,
$.initializer_expression,
$.interpolated_string_expression,
$.invocation_expression,
$.is_pattern_expression,
$.lambda_expression,
$.make_ref_expression,
$.member_access_expression,
$.member_binding_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,
$._type,
$.identifier,
alias($._reserved_identifier, $.identifier),
// Literals
$.null_literal,
$.boolean_literal,
$.character_literal,
$.real_literal, // Don't combine real and integer literals together
$.integer_literal,
$.string_literal, // Or strings and verbatim strings
$.verbatim_string_literal
),
_local_variable_type: $ => choice(
'var',
$._type
binary_expression: $ => choice(
...[
['&&', PREC.LOGAND],
['||', PREC.LOGOR],
['>>', PREC.SHIFT],
['<<', PREC.SHIFT],
['&', PREC.AND],
['^', PREC.OR],
['|', PREC.OR],
['+', PREC.ADD],
['-', PREC.ADD],
['*', PREC.MULT],
['/', PREC.MULT],
['%', PREC.MULT],
['<', PREC.REL],
['<=', PREC.REL],
['==', PREC.EQUAL],
['!=', PREC.EQUAL],
['>=', PREC.REL],
['>', PREC.REL],
['??', PREC.EQUAL],
['as', PREC.EQUAL],
].map(([operator, precedence]) =>
prec.left(precedence, seq($._expression, operator, $._expression))
).concat(
prec.left(PREC.EQUAL, seq($._expression, 'is', $._type))
)
),
_local_variable_declarators: $ => choice(
$.local_variable_declarator,
seq($._local_variable_declarators, ',', $.local_variable_declarator)
// Literals - grammar.txt is useless here as it just refs to lexical specification
boolean_literal: $ => choice(
'true',
'false'
),
local_variable_declarator: $ => seq(
$.identifier_name,
optional(seq('=', $.local_variable_initializer))
character_literal: $ => seq(
"'",
choice(token.immediate(/[^'\\]/), $.escape_sequence),
"'"
),
local_variable_initializer: $ => choice(
$._expression,
$.array_initalizer
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(
choice(
(/[0-9_]+/), // Decimal
(/0[xX][0-9a-fA-F_]+/), // Hex
(/0[bB][01_]+/) // Binary
),
optional(/u|U|l|L|ul|UL|uL|Ul|lu|LU|Lu|lU/)
)),
null_literal: $ => 'null',
real_literal: $ => {
const suffix = /[fFdDmM]/;
const exponent = /[eE][+-]?[0-9_]+/;
return token(choice(
seq(
(/[0-9_]+/),
'.',
(/[0-9_]+/),
optional(exponent),
optional(suffix)
),
seq(
'.',
(/[0-9_]+/),
optional(exponent),
optional(suffix)
),
seq(
(/[0-9_]+/),
exponent,
optional(suffix)
),
seq(
(/[0-9_]+/),
suffix
)
))
},
string_literal: $ => seq(
'"',
repeat(choice(
token.immediate(prec(1, /[^"\\\n]+/)),
$.escape_sequence
)),
'"'
),
local_constant_declaration: $ => seq('const', $._type, $._constant_declarators)
verbatim_string_literal: $ => token(seq(
'@"',
repeat(choice(
/[^"]/,
'""',
)),
'"'
)),
// Comments
comment: $ => token(choice(
seq('//', /.*/),
seq(
'/*',
repeat(choice(
/[^*]/,
/\*[^/]/
)),
'*/'
)
)),
// Custom non-Roslyn additions beyond this point that will not sync up with grammar.txt
_reserved_identifier: $ => choice(
'from'
),
// 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',
// We could line this up with grammar.txt *_trivia at some point.
// Will need to understand how structured_trivia is implemented.
preprocessor_directive: $ => token(
seq(
// TODO: Nothing should come before the # on a line except whitespace
'#',
choice(
'if',
'define',
'endif',
'undef',
'warning',
'error',
'line',
'region',
'endregion',
'pragma warning',
'pragma checksum',
'nullable',
// Individiual code can be broken up by #if #else #elif etc. Parsing all the code ignoring the tokens can cause
// syntax errors. What we do instead is always parse the #if block but then completely ignore the #else and #elif blocks.
// It's not perfect as sometimes only valid combinations of names would compile or the defined names might be re-used.
seq(
choice('else', seq('elif', /.*/)),
repeat(choice(/[^#]/, /#[\s\u00A0]*(else|elif|define|undef|warning|error|line|region|endregion|pragma|nullable)/)), // Consume "disabled" code
/#[\s\u00A0]*endif/
),
),
/.*/
)
),
}
})
function commaSep(rule) {
return optional(commaSep1(rule))
}
function commaSep1(rule) {

@@ -1051,0 +1395,0 @@ return seq(

@@ -1,1 +0,13 @@

module.exports = require("./build/Release/ts_language_c_sharp_binding");
try {
module.exports = require("./build/Release/tree_sitter_c_sharp_binding");
} catch (error) {
try {
module.exports = require("./build/Debug/tree_sitter_c_sharp_binding");
} catch (_) {
throw error
}
}
try {
module.exports.nodeTypeInfo = require("./src/node-types.json");
} catch (_) {}
{
"name": "tree-sitter-c-sharp",
"version": "0.13.0",
"version": "0.15.0",
"description": "C# grammar for tree-sitter",

@@ -16,8 +16,7 @@ "main": "index.js",

"devDependencies": {
"tree-sitter-cli": "^0.13.1"
"tree-sitter-cli": "^0.15.14"
},
"scripts": {
"build": "tree-sitter generate && node-gyp build",
"test": "tree-sitter test"
}
}

@@ -10,6 +10,70 @@ tree-sitter-c-sharp

Currently incomplete, based on the C# 6.0 draft proposal.
Based on an export of the Roslyn grammar export with various changes in order to:
- Deal with differences between the parsing technologies
- Work around some bugs in that grammar
- Handle `#if`, `#else`, `#elif`, `#endif` blocks
- Support syntax highlighting/parsing of fragments
- Simplify the output tree
### Detailed status
Comprehensive support for C# exists with the following exceptions:
- [ ] [Non-ASCII identifiers](#37)
- [ ] [Contextual keywords](#47)
- [ ] [Global statements](#12)
#### C# 7.0
- [ ] [Tuples](#15)
- [x] Discards
- [x] Basic pattern matching
- [ ] [Recursive pattern matching](#19)
- [ ] [Ref locals and return](#14)
- [x] Local function statements
- [x] Expression bodied constructors
- [x] Expression bodied destructors/finalizers
- [x] Throw expressions
- [x] Binary and `_` literal support
#### C# 7.1
- [x] `async` main method
- [x] Default literals (as `default_expression`)
- [ ] Inferred tuple element names
- [ ] Generic type pattern matching
#### C# 7.2
- [x] `in` parameter modifiers
- [x] `ref readonly` method returns
- [x] `readonly struct`
- [x] `ref struct`
- [x] Non-trailing named arguments
- [x] `_` leading binary and hex literals
- [x] `private protected` modifier
- [ ] Conditional `ref` expressions
#### C# 7.3
- [x] `stackalloc` array initializers
- [x] `unmanaged` generic type parameter constraint
- [x] Attributes attached to auto property backing fields
- [x] `out` support for parameters on initializers, constructors etc.
#### C# 8.0
- [x] `readonly` members
- [x] Default interface methods
- [x] `switch` expressions
- [ ] `switch` property patterns
- [ ] `switch` tuple patterns
- [x] `static` local functions
- [x] nullable reference types
- [x] null-forgiving operator
### References
* [Official C# Language Spec](https://github.com/dotnet/csharplang/blob/master/spec/) It provides chapters that formally define the language grammar.
* [Official C# 6 Language Spec](https://github.com/dotnet/csharplang/blob/master/spec/) provides chapters that formally define the language grammar.
* [Roslyn C# language grammar export](https://github.com/dotnet/roslyn/blob/master/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4)

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 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