@willbooster/tree-sitter-c-sharp 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/grammar.js +100 -33
- package/package.json +1 -1
- package/src/node-types.json +27 -23
- package/tree-sitter-c_sharp.wasm +0 -0
- package/tree-sitter.json +1 -1
package/README.md
CHANGED
|
@@ -27,8 +27,9 @@ The grammar is based upon the Roslyn grammar with changes in order to:
|
|
|
27
27
|
Known gaps:
|
|
28
28
|
|
|
29
29
|
- `async`, `var` and `await` cannot be used as identifiers everywhere they are valid
|
|
30
|
-
- A pointer dereference can be assigned to only when its operand is a variable,
|
|
31
|
-
or
|
|
30
|
+
- A pointer dereference can be assigned to only when its operand is a variable, an address, a parenthesized or
|
|
31
|
+
postfix expression, or a cast of one of these or of an invocation (`*p = 1`, `*(p + 1) = 1`, `*(int*)p = 1`,
|
|
32
|
+
`*dst++ = 1`); `*++p = 1` and `*f() = 1` are not recognized
|
|
32
33
|
- File-based apps preprocessor directives (`#:property`, `#:package`, `#:sdk`, `#:project`) are not yet recognized
|
|
33
34
|
|
|
34
35
|
## Usage
|
package/grammar.js
CHANGED
|
@@ -101,6 +101,7 @@ module.exports = grammar({
|
|
|
101
101
|
[$._reserved_identifier, $.parameter],
|
|
102
102
|
[$._simple_name, $.parameter],
|
|
103
103
|
[$.tuple_element, $.parameter, $.declaration_expression],
|
|
104
|
+
[$.parameter, $.declaration_expression],
|
|
104
105
|
[$.parameter, $.tuple_element],
|
|
105
106
|
|
|
106
107
|
[$.event_declaration, $.variable_declarator],
|
|
@@ -518,8 +519,9 @@ module.exports = grammar({
|
|
|
518
519
|
)
|
|
519
520
|
),
|
|
520
521
|
|
|
522
|
+
// The precedence reads the `ref` of `extension(ref int)` as a modifier rather than a ref_type.
|
|
521
523
|
receiver_parameter: ($) =>
|
|
522
|
-
seq(repeat($._attribute_list), $._parameter_type_with_modifiers, optional(field('name', $.identifier))),
|
|
524
|
+
prec(1, seq(repeat($._attribute_list), $._parameter_type_with_modifiers, optional(field('name', $.identifier)))),
|
|
523
525
|
|
|
524
526
|
extension_body: ($) => seq('{', repeat($._extension_member_declaration), '}', optional(';')),
|
|
525
527
|
|
|
@@ -615,9 +617,18 @@ module.exports = grammar({
|
|
|
615
617
|
|
|
616
618
|
parameter_list: ($) => seq('(', sep(choice($.parameter, $._parameter_array), ','), ')'),
|
|
617
619
|
|
|
620
|
+
// `ref`, `out`, and `in` stay out of the repeat: reducing the repeat after them would compete with the shift of
|
|
621
|
+
// the next token into an argument (`(ref x)`), whose precedence wins, so `(ref int i) =>` would read `ref int` as a
|
|
622
|
+
// ref_type while a method's `(ref int i)` reads `ref` as a modifier.
|
|
618
623
|
_parameter_type_with_modifiers: ($) =>
|
|
619
624
|
seq(
|
|
620
|
-
repeat(prec.left(alias(choice('this', 'scoped', '
|
|
625
|
+
repeat(prec.left(alias(choice('this', 'scoped', 'readonly'), $.modifier))),
|
|
626
|
+
optional(
|
|
627
|
+
seq(
|
|
628
|
+
alias(choice('ref', 'out', 'in'), $.modifier),
|
|
629
|
+
repeat(prec.left(alias(choice('this', 'readonly'), $.modifier)))
|
|
630
|
+
)
|
|
631
|
+
),
|
|
621
632
|
field('type', $.type)
|
|
622
633
|
),
|
|
623
634
|
|
|
@@ -770,7 +781,8 @@ module.exports = grammar({
|
|
|
770
781
|
)
|
|
771
782
|
),
|
|
772
783
|
|
|
773
|
-
|
|
784
|
+
// Right-associative so that a parameter's `ref int x` keeps `ref` as a modifier instead of reducing a ref_type.
|
|
785
|
+
ref_type: ($) => prec.right(seq('ref', optional('readonly'), field('type', $.type))),
|
|
774
786
|
|
|
775
787
|
_ref_base_type: ($) =>
|
|
776
788
|
choice(
|
|
@@ -995,9 +1007,10 @@ module.exports = grammar({
|
|
|
995
1007
|
_name_invocation_pattern: ($) => seq(field('function', $._name), field('arguments', $.argument_list)),
|
|
996
1008
|
|
|
997
1009
|
// Invocation where function is not a simple name
|
|
1010
|
+
// One above `invocation_expression`, which reads the same tokens where both fit.
|
|
998
1011
|
_complex_invocation_expression: ($) =>
|
|
999
1012
|
prec(
|
|
1000
|
-
PREC.INVOCATION,
|
|
1013
|
+
PREC.INVOCATION + 1,
|
|
1001
1014
|
seq(
|
|
1002
1015
|
field(
|
|
1003
1016
|
'function',
|
|
@@ -1230,7 +1243,7 @@ module.exports = grammar({
|
|
|
1230
1243
|
)
|
|
1231
1244
|
),
|
|
1232
1245
|
|
|
1233
|
-
postfix_unary_expression: ($) => prec(PREC.POSTFIX, seq(
|
|
1246
|
+
postfix_unary_expression: ($) => prec(PREC.POSTFIX, seq(postfixOperand($), choice('++', '--', '!'))),
|
|
1234
1247
|
|
|
1235
1248
|
prefix_unary_expression: ($) =>
|
|
1236
1249
|
prec(
|
|
@@ -1248,35 +1261,69 @@ module.exports = grammar({
|
|
|
1248
1261
|
)
|
|
1249
1262
|
),
|
|
1250
1263
|
|
|
1251
|
-
// Pointer indirection is split by its operand.
|
|
1252
|
-
// (`*p`, `*(p)`, `**pp`)
|
|
1253
|
-
// `
|
|
1254
|
-
// expression (`*(
|
|
1255
|
-
// `
|
|
1256
|
-
// be
|
|
1264
|
+
// Pointer indirection is split by its operand. The assignable form, surfaced in `lvalue_expression`, takes an
|
|
1265
|
+
// lvalue (`*p`, `*(p)`, `**pp`) or an operand that ends in a closing token or an lvalue: a parenthesized
|
|
1266
|
+
// expression (`*(p + 1)`), a postfix expression (`*p++`), an address (`*&v`), or a cast of an lvalue, a
|
|
1267
|
+
// parenthesized, postfix, or invocation expression, or an address (`*(int*)p`, `*(long*)(p + 4)`, `*(T*)f()`,
|
|
1268
|
+
// `*(long*)&v`). Dereferencing any other expression (`*++p`) is only read: letting any expression be the assignable
|
|
1269
|
+
// form's operand lets `=` follow every expression that can be the operand, which grows the parser by about 4,800
|
|
1270
|
+
// states and nearly doubles the Wasm build, while these operands add about 550.
|
|
1257
1271
|
//
|
|
1258
|
-
//
|
|
1259
|
-
//
|
|
1260
|
-
//
|
|
1261
|
-
//
|
|
1262
|
-
// dereference of `
|
|
1263
|
-
// (-
|
|
1264
|
-
_pointer_indirection_expression: ($) =>
|
|
1272
|
+
// Dynamic precedences: an assignable dereference -2, a read-only one -4, a read-only cast +1, and an assignable cast
|
|
1273
|
+
// -1. C# reads a parenthesized name as a cast only when the token after `)` is `~`, `!`, `(`, an identifier, a
|
|
1274
|
+
// literal, or a keyword (C# spec §12.9.8 Cast expressions), and these values keep that reading: `(a) * b` is a
|
|
1275
|
+
// multiplication (0), not a cast of `*b` (+1 - 2); `*(p) + 1` and `*(p) & x` apply to a dereference of `(p)` (-2),
|
|
1276
|
+
// not to a dereference of a cast of `+1` or `&x` (-4 + 1 or -2 - 1); `*(b)[0]` dereferences an element access
|
|
1277
|
+
// (-2), not a cast of `[0]` (-2 - 1). Where both casts fit, they give the same tree.
|
|
1278
|
+
_pointer_indirection_expression: ($) =>
|
|
1279
|
+
prec.dynamic(
|
|
1280
|
+
-2,
|
|
1281
|
+
prec.right(
|
|
1282
|
+
PREC.UNARY,
|
|
1283
|
+
seq(
|
|
1284
|
+
'*',
|
|
1285
|
+
choice(
|
|
1286
|
+
$.lvalue_expression,
|
|
1287
|
+
$.parenthesized_expression,
|
|
1288
|
+
alias($._address_of_expression, $.prefix_unary_expression),
|
|
1289
|
+
alias($._lvalue_cast_expression, $.cast_expression),
|
|
1290
|
+
$.postfix_unary_expression
|
|
1291
|
+
)
|
|
1292
|
+
)
|
|
1293
|
+
)
|
|
1294
|
+
),
|
|
1295
|
+
|
|
1296
|
+
_lvalue_cast_expression: ($) =>
|
|
1297
|
+
prec(
|
|
1298
|
+
PREC.CAST,
|
|
1299
|
+
prec.dynamic(
|
|
1300
|
+
-1,
|
|
1301
|
+
seq(
|
|
1302
|
+
'(',
|
|
1303
|
+
field('type', $.type),
|
|
1304
|
+
')',
|
|
1305
|
+
field(
|
|
1306
|
+
'value',
|
|
1307
|
+
choice(
|
|
1308
|
+
$.lvalue_expression,
|
|
1309
|
+
$.parenthesized_expression,
|
|
1310
|
+
alias($._address_of_expression, $.prefix_unary_expression),
|
|
1311
|
+
$.postfix_unary_expression,
|
|
1312
|
+
$.invocation_expression
|
|
1313
|
+
)
|
|
1314
|
+
)
|
|
1315
|
+
)
|
|
1316
|
+
)
|
|
1317
|
+
),
|
|
1265
1318
|
|
|
1266
1319
|
_value_indirection_expression: ($) => prec.dynamic(-4, prec.right(PREC.UNARY, seq('*', $.non_lvalue_expression))),
|
|
1267
1320
|
|
|
1268
|
-
// Address-of is split out from `prefix_unary_expression`
|
|
1269
|
-
//
|
|
1270
|
-
//
|
|
1271
|
-
//
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
// a unary start and the lexer split `&&` into two `&` tokens.
|
|
1275
|
-
// With this split, `&` is only valid before an lvalue, which
|
|
1276
|
-
// `(b > 0)` is not — so the cast interpretation can no longer
|
|
1277
|
-
// consume the trailing parenthesized expression and `&&` must
|
|
1278
|
-
// be emitted as a single token for the binary path to succeed.
|
|
1279
|
-
_address_of_expression: ($) => prec.right(PREC.UNARY, seq('&', $.lvalue_expression)),
|
|
1321
|
+
// Address-of is split out from `prefix_unary_expression` and takes only a variable: an lvalue, or an invocation,
|
|
1322
|
+
// which can return a reference (`&span.GetPinnableReference()`). If a cast could take `&` before any expression,
|
|
1323
|
+
// the lexer would split `&&` into two `&` tokens and `(a) && (b > 0)` would read as a cast of `&(&(b > 0))`; as
|
|
1324
|
+
// `(b > 0)` is not a variable, that reading fails and `&&` stays one token.
|
|
1325
|
+
_address_of_expression: ($) =>
|
|
1326
|
+
prec.right(PREC.UNARY, seq('&', choice($.lvalue_expression, $.invocation_expression))),
|
|
1280
1327
|
|
|
1281
1328
|
query_expression: ($) => seq($.from_clause, $._query_body),
|
|
1282
1329
|
|
|
@@ -1358,7 +1405,7 @@ module.exports = grammar({
|
|
|
1358
1405
|
checked_expression: ($) => seq(choice('checked', 'unchecked'), '(', $.expression, ')'),
|
|
1359
1406
|
|
|
1360
1407
|
invocation_expression: ($) =>
|
|
1361
|
-
prec(PREC.INVOCATION, seq(field('function',
|
|
1408
|
+
prec(PREC.INVOCATION, seq(field('function', postfixOperand($)), field('arguments', $.argument_list))),
|
|
1362
1409
|
|
|
1363
1410
|
switch_expression: ($) => prec(PREC.SWITCH, seq($.expression, 'switch', $._switch_expression_body)),
|
|
1364
1411
|
_switch_expression_body: ($) => seq('{', commaSep($.switch_expression_arm), optional(','), '}'),
|
|
@@ -1372,7 +1419,7 @@ module.exports = grammar({
|
|
|
1372
1419
|
throw_expression: ($) => seq('throw', $.expression),
|
|
1373
1420
|
|
|
1374
1421
|
element_access_expression: ($) =>
|
|
1375
|
-
prec(PREC.POSTFIX, seq(field('expression',
|
|
1422
|
+
prec(PREC.POSTFIX, seq(field('expression', postfixOperand($)), field('subscript', $.bracketed_argument_list))),
|
|
1376
1423
|
|
|
1377
1424
|
interpolated_string_expression: ($) =>
|
|
1378
1425
|
choice(
|
|
@@ -1422,7 +1469,7 @@ module.exports = grammar({
|
|
|
1422
1469
|
prec(
|
|
1423
1470
|
PREC.DOT,
|
|
1424
1471
|
seq(
|
|
1425
|
-
field('expression', choice(
|
|
1472
|
+
field('expression', choice(postfixOperand($), $.predefined_type, $._name)),
|
|
1426
1473
|
choice('.', '->'),
|
|
1427
1474
|
field('name', $._simple_name)
|
|
1428
1475
|
)
|
|
@@ -1843,6 +1890,26 @@ function preprocIf(suffix, content, precedence = 0, rep = true) {
|
|
|
1843
1890
|
};
|
|
1844
1891
|
}
|
|
1845
1892
|
|
|
1893
|
+
/**
|
|
1894
|
+
* The operand of a postfix operator, an invocation, an element access, or a member access. Besides `expression`, it
|
|
1895
|
+
* lists the forms that are operands of `&`, of the assignable `*`, or of the assignable cast: reaching them only
|
|
1896
|
+
* through `expression` would reduce the unary operator or the cast (precedence UNARY or CAST) before `expression`
|
|
1897
|
+
* (precedence 0) lets the postfix operator apply, reading `&a[0]` as `(&a)[0]` and `*(T*)f()[0]` as `(*(T*)f())[0]`.
|
|
1898
|
+
*
|
|
1899
|
+
* @param {GrammarSymbols<string>} $
|
|
1900
|
+
*
|
|
1901
|
+
* @returns {ChoiceRule}
|
|
1902
|
+
*/
|
|
1903
|
+
function postfixOperand($) {
|
|
1904
|
+
return choice(
|
|
1905
|
+
$.expression,
|
|
1906
|
+
$.lvalue_expression,
|
|
1907
|
+
$.invocation_expression,
|
|
1908
|
+
$.postfix_unary_expression,
|
|
1909
|
+
$.parenthesized_expression
|
|
1910
|
+
);
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1846
1913
|
/**
|
|
1847
1914
|
* Creates a rule to match one or more of the rules separated by a comma
|
|
1848
1915
|
*
|
package/package.json
CHANGED
package/src/node-types.json
CHANGED
|
@@ -1511,6 +1511,14 @@
|
|
|
1511
1511
|
{
|
|
1512
1512
|
"type": "expression",
|
|
1513
1513
|
"named": true
|
|
1514
|
+
},
|
|
1515
|
+
{
|
|
1516
|
+
"type": "invocation_expression",
|
|
1517
|
+
"named": true
|
|
1518
|
+
},
|
|
1519
|
+
{
|
|
1520
|
+
"type": "postfix_unary_expression",
|
|
1521
|
+
"named": true
|
|
1514
1522
|
}
|
|
1515
1523
|
]
|
|
1516
1524
|
}
|
|
@@ -2316,6 +2324,14 @@
|
|
|
2316
2324
|
{
|
|
2317
2325
|
"type": "expression",
|
|
2318
2326
|
"named": true
|
|
2327
|
+
},
|
|
2328
|
+
{
|
|
2329
|
+
"type": "invocation_expression",
|
|
2330
|
+
"named": true
|
|
2331
|
+
},
|
|
2332
|
+
{
|
|
2333
|
+
"type": "postfix_unary_expression",
|
|
2334
|
+
"named": true
|
|
2319
2335
|
}
|
|
2320
2336
|
]
|
|
2321
2337
|
},
|
|
@@ -3449,36 +3465,16 @@
|
|
|
3449
3465
|
"type": "cast_expression",
|
|
3450
3466
|
"named": true
|
|
3451
3467
|
},
|
|
3452
|
-
{
|
|
3453
|
-
"type": "conditional_access_expression",
|
|
3454
|
-
"named": true
|
|
3455
|
-
},
|
|
3456
|
-
{
|
|
3457
|
-
"type": "element_access_expression",
|
|
3458
|
-
"named": true
|
|
3459
|
-
},
|
|
3460
3468
|
{
|
|
3461
3469
|
"type": "expression",
|
|
3462
3470
|
"named": true
|
|
3463
3471
|
},
|
|
3464
|
-
{
|
|
3465
|
-
"type": "generic_name",
|
|
3466
|
-
"named": true
|
|
3467
|
-
},
|
|
3468
|
-
{
|
|
3469
|
-
"type": "identifier",
|
|
3470
|
-
"named": true
|
|
3471
|
-
},
|
|
3472
3472
|
{
|
|
3473
3473
|
"type": "invocation_expression",
|
|
3474
3474
|
"named": true
|
|
3475
3475
|
},
|
|
3476
3476
|
{
|
|
3477
|
-
"type": "
|
|
3478
|
-
"named": true
|
|
3479
|
-
},
|
|
3480
|
-
{
|
|
3481
|
-
"type": "parenthesized_expression",
|
|
3477
|
+
"type": "postfix_unary_expression",
|
|
3482
3478
|
"named": true
|
|
3483
3479
|
},
|
|
3484
3480
|
{
|
|
@@ -3894,11 +3890,11 @@
|
|
|
3894
3890
|
"named": true
|
|
3895
3891
|
},
|
|
3896
3892
|
{
|
|
3897
|
-
"type": "
|
|
3893
|
+
"type": "invocation_expression",
|
|
3898
3894
|
"named": true
|
|
3899
3895
|
},
|
|
3900
3896
|
{
|
|
3901
|
-
"type": "
|
|
3897
|
+
"type": "postfix_unary_expression",
|
|
3902
3898
|
"named": true
|
|
3903
3899
|
},
|
|
3904
3900
|
{
|
|
@@ -4668,6 +4664,14 @@
|
|
|
4668
4664
|
{
|
|
4669
4665
|
"type": "expression",
|
|
4670
4666
|
"named": true
|
|
4667
|
+
},
|
|
4668
|
+
{
|
|
4669
|
+
"type": "invocation_expression",
|
|
4670
|
+
"named": true
|
|
4671
|
+
},
|
|
4672
|
+
{
|
|
4673
|
+
"type": "postfix_unary_expression",
|
|
4674
|
+
"named": true
|
|
4671
4675
|
}
|
|
4672
4676
|
]
|
|
4673
4677
|
}
|
package/tree-sitter-c_sharp.wasm
CHANGED
|
Binary file
|