@willbooster/tree-sitter-c-sharp 1.0.8 → 1.0.10
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 +94 -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
|
@@ -83,6 +83,7 @@ module.exports = grammar({
|
|
|
83
83
|
[$.constant_pattern, $.lvalue_expression, $._name],
|
|
84
84
|
|
|
85
85
|
[$.type, $._name_invocation_pattern, $.recursive_pattern],
|
|
86
|
+
[$.type, $.recursive_pattern],
|
|
86
87
|
[$.attribute, $.type, $._name_invocation_pattern, $.recursive_pattern],
|
|
87
88
|
|
|
88
89
|
[$.parenthesized_pattern, $._parenthesized_pattern_with_designation],
|
|
@@ -1007,9 +1008,10 @@ module.exports = grammar({
|
|
|
1007
1008
|
_name_invocation_pattern: ($) => seq(field('function', $._name), field('arguments', $.argument_list)),
|
|
1008
1009
|
|
|
1009
1010
|
// Invocation where function is not a simple name
|
|
1011
|
+
// One above `invocation_expression`, which reads the same tokens where both fit.
|
|
1010
1012
|
_complex_invocation_expression: ($) =>
|
|
1011
1013
|
prec(
|
|
1012
|
-
PREC.INVOCATION,
|
|
1014
|
+
PREC.INVOCATION + 1,
|
|
1013
1015
|
seq(
|
|
1014
1016
|
field(
|
|
1015
1017
|
'function',
|
|
@@ -1081,10 +1083,15 @@ module.exports = grammar({
|
|
|
1081
1083
|
prec.dynamic(1, seq($.positional_pattern_clause, $._simple_designation)),
|
|
1082
1084
|
// positional pattern without variable designation (no type prefix)
|
|
1083
1085
|
$.positional_pattern_clause,
|
|
1084
|
-
// other type followed by
|
|
1086
|
+
// other type followed by a property pattern clause
|
|
1087
|
+
seq(field('type', $.type), $.property_pattern_clause, optional($._simple_designation)),
|
|
1088
|
+
// A positional clause follows only a name (above), a predefined type, or an array type. Letting any type take
|
|
1089
|
+
// one reads `Name(A.B)` once more, through `type`; after a syntax error, the extra GLR versions then exceed
|
|
1090
|
+
// the runtime's limit, and which reading survives depends on the versions alive, not on dynamic precedence.
|
|
1085
1091
|
seq(
|
|
1086
|
-
field('type', $.
|
|
1087
|
-
|
|
1092
|
+
field('type', choice($.predefined_type, $.array_type)),
|
|
1093
|
+
$.positional_pattern_clause,
|
|
1094
|
+
optional($.property_pattern_clause),
|
|
1088
1095
|
optional($._simple_designation)
|
|
1089
1096
|
),
|
|
1090
1097
|
// no type, just pattern clauses (no variable designation to avoid conflict with above)
|
|
@@ -1242,7 +1249,7 @@ module.exports = grammar({
|
|
|
1242
1249
|
)
|
|
1243
1250
|
),
|
|
1244
1251
|
|
|
1245
|
-
postfix_unary_expression: ($) => prec(PREC.POSTFIX, seq(
|
|
1252
|
+
postfix_unary_expression: ($) => prec(PREC.POSTFIX, seq(postfixOperand($), choice('++', '--', '!'))),
|
|
1246
1253
|
|
|
1247
1254
|
prefix_unary_expression: ($) =>
|
|
1248
1255
|
prec(
|
|
@@ -1260,35 +1267,69 @@ module.exports = grammar({
|
|
|
1260
1267
|
)
|
|
1261
1268
|
),
|
|
1262
1269
|
|
|
1263
|
-
// Pointer indirection is split by its operand.
|
|
1264
|
-
// (`*p`, `*(p)`, `**pp`)
|
|
1265
|
-
// `
|
|
1266
|
-
// expression (`*(
|
|
1267
|
-
// `
|
|
1268
|
-
// be
|
|
1270
|
+
// Pointer indirection is split by its operand. The assignable form, surfaced in `lvalue_expression`, takes an
|
|
1271
|
+
// lvalue (`*p`, `*(p)`, `**pp`) or an operand that ends in a closing token or an lvalue: a parenthesized
|
|
1272
|
+
// expression (`*(p + 1)`), a postfix expression (`*p++`), an address (`*&v`), or a cast of an lvalue, a
|
|
1273
|
+
// parenthesized, postfix, or invocation expression, or an address (`*(int*)p`, `*(long*)(p + 4)`, `*(T*)f()`,
|
|
1274
|
+
// `*(long*)&v`). Dereferencing any other expression (`*++p`) is only read: letting any expression be the assignable
|
|
1275
|
+
// form's operand lets `=` follow every expression that can be the operand, which grows the parser by about 4,800
|
|
1276
|
+
// states and nearly doubles the Wasm build, while these operands add about 550.
|
|
1269
1277
|
//
|
|
1270
|
-
//
|
|
1271
|
-
//
|
|
1272
|
-
//
|
|
1273
|
-
//
|
|
1274
|
-
// dereference of `
|
|
1275
|
-
// (-
|
|
1276
|
-
_pointer_indirection_expression: ($) =>
|
|
1278
|
+
// Dynamic precedences: an assignable dereference -2, a read-only one -4, a read-only cast +1, and an assignable cast
|
|
1279
|
+
// -1. C# reads a parenthesized name as a cast only when the token after `)` is `~`, `!`, `(`, an identifier, a
|
|
1280
|
+
// literal, or a keyword (C# spec §12.9.8 Cast expressions), and these values keep that reading: `(a) * b` is a
|
|
1281
|
+
// multiplication (0), not a cast of `*b` (+1 - 2); `*(p) + 1` and `*(p) & x` apply to a dereference of `(p)` (-2),
|
|
1282
|
+
// not to a dereference of a cast of `+1` or `&x` (-4 + 1 or -2 - 1); `*(b)[0]` dereferences an element access
|
|
1283
|
+
// (-2), not a cast of `[0]` (-2 - 1). Where both casts fit, they give the same tree.
|
|
1284
|
+
_pointer_indirection_expression: ($) =>
|
|
1285
|
+
prec.dynamic(
|
|
1286
|
+
-2,
|
|
1287
|
+
prec.right(
|
|
1288
|
+
PREC.UNARY,
|
|
1289
|
+
seq(
|
|
1290
|
+
'*',
|
|
1291
|
+
choice(
|
|
1292
|
+
$.lvalue_expression,
|
|
1293
|
+
$.parenthesized_expression,
|
|
1294
|
+
alias($._address_of_expression, $.prefix_unary_expression),
|
|
1295
|
+
alias($._lvalue_cast_expression, $.cast_expression),
|
|
1296
|
+
$.postfix_unary_expression
|
|
1297
|
+
)
|
|
1298
|
+
)
|
|
1299
|
+
)
|
|
1300
|
+
),
|
|
1301
|
+
|
|
1302
|
+
_lvalue_cast_expression: ($) =>
|
|
1303
|
+
prec(
|
|
1304
|
+
PREC.CAST,
|
|
1305
|
+
prec.dynamic(
|
|
1306
|
+
-1,
|
|
1307
|
+
seq(
|
|
1308
|
+
'(',
|
|
1309
|
+
field('type', $.type),
|
|
1310
|
+
')',
|
|
1311
|
+
field(
|
|
1312
|
+
'value',
|
|
1313
|
+
choice(
|
|
1314
|
+
$.lvalue_expression,
|
|
1315
|
+
$.parenthesized_expression,
|
|
1316
|
+
alias($._address_of_expression, $.prefix_unary_expression),
|
|
1317
|
+
$.postfix_unary_expression,
|
|
1318
|
+
$.invocation_expression
|
|
1319
|
+
)
|
|
1320
|
+
)
|
|
1321
|
+
)
|
|
1322
|
+
)
|
|
1323
|
+
),
|
|
1277
1324
|
|
|
1278
1325
|
_value_indirection_expression: ($) => prec.dynamic(-4, prec.right(PREC.UNARY, seq('*', $.non_lvalue_expression))),
|
|
1279
1326
|
|
|
1280
|
-
// Address-of is split out from `prefix_unary_expression`
|
|
1281
|
-
//
|
|
1282
|
-
//
|
|
1283
|
-
//
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
// a unary start and the lexer split `&&` into two `&` tokens.
|
|
1287
|
-
// With this split, `&` is only valid before an lvalue, which
|
|
1288
|
-
// `(b > 0)` is not — so the cast interpretation can no longer
|
|
1289
|
-
// consume the trailing parenthesized expression and `&&` must
|
|
1290
|
-
// be emitted as a single token for the binary path to succeed.
|
|
1291
|
-
_address_of_expression: ($) => prec.right(PREC.UNARY, seq('&', $.lvalue_expression)),
|
|
1327
|
+
// Address-of is split out from `prefix_unary_expression` and takes only a variable: an lvalue, or an invocation,
|
|
1328
|
+
// which can return a reference (`&span.GetPinnableReference()`). If a cast could take `&` before any expression,
|
|
1329
|
+
// the lexer would split `&&` into two `&` tokens and `(a) && (b > 0)` would read as a cast of `&(&(b > 0))`; as
|
|
1330
|
+
// `(b > 0)` is not a variable, that reading fails and `&&` stays one token.
|
|
1331
|
+
_address_of_expression: ($) =>
|
|
1332
|
+
prec.right(PREC.UNARY, seq('&', choice($.lvalue_expression, $.invocation_expression))),
|
|
1292
1333
|
|
|
1293
1334
|
query_expression: ($) => seq($.from_clause, $._query_body),
|
|
1294
1335
|
|
|
@@ -1370,7 +1411,7 @@ module.exports = grammar({
|
|
|
1370
1411
|
checked_expression: ($) => seq(choice('checked', 'unchecked'), '(', $.expression, ')'),
|
|
1371
1412
|
|
|
1372
1413
|
invocation_expression: ($) =>
|
|
1373
|
-
prec(PREC.INVOCATION, seq(field('function',
|
|
1414
|
+
prec(PREC.INVOCATION, seq(field('function', postfixOperand($)), field('arguments', $.argument_list))),
|
|
1374
1415
|
|
|
1375
1416
|
switch_expression: ($) => prec(PREC.SWITCH, seq($.expression, 'switch', $._switch_expression_body)),
|
|
1376
1417
|
_switch_expression_body: ($) => seq('{', commaSep($.switch_expression_arm), optional(','), '}'),
|
|
@@ -1384,7 +1425,7 @@ module.exports = grammar({
|
|
|
1384
1425
|
throw_expression: ($) => seq('throw', $.expression),
|
|
1385
1426
|
|
|
1386
1427
|
element_access_expression: ($) =>
|
|
1387
|
-
prec(PREC.POSTFIX, seq(field('expression',
|
|
1428
|
+
prec(PREC.POSTFIX, seq(field('expression', postfixOperand($)), field('subscript', $.bracketed_argument_list))),
|
|
1388
1429
|
|
|
1389
1430
|
interpolated_string_expression: ($) =>
|
|
1390
1431
|
choice(
|
|
@@ -1434,7 +1475,7 @@ module.exports = grammar({
|
|
|
1434
1475
|
prec(
|
|
1435
1476
|
PREC.DOT,
|
|
1436
1477
|
seq(
|
|
1437
|
-
field('expression', choice(
|
|
1478
|
+
field('expression', choice(postfixOperand($), $.predefined_type, $._name)),
|
|
1438
1479
|
choice('.', '->'),
|
|
1439
1480
|
field('name', $._simple_name)
|
|
1440
1481
|
)
|
|
@@ -1855,6 +1896,26 @@ function preprocIf(suffix, content, precedence = 0, rep = true) {
|
|
|
1855
1896
|
};
|
|
1856
1897
|
}
|
|
1857
1898
|
|
|
1899
|
+
/**
|
|
1900
|
+
* The operand of a postfix operator, an invocation, an element access, or a member access. Besides `expression`, it
|
|
1901
|
+
* lists the forms that are operands of `&`, of the assignable `*`, or of the assignable cast: reaching them only
|
|
1902
|
+
* through `expression` would reduce the unary operator or the cast (precedence UNARY or CAST) before `expression`
|
|
1903
|
+
* (precedence 0) lets the postfix operator apply, reading `&a[0]` as `(&a)[0]` and `*(T*)f()[0]` as `(*(T*)f())[0]`.
|
|
1904
|
+
*
|
|
1905
|
+
* @param {GrammarSymbols<string>} $
|
|
1906
|
+
*
|
|
1907
|
+
* @returns {ChoiceRule}
|
|
1908
|
+
*/
|
|
1909
|
+
function postfixOperand($) {
|
|
1910
|
+
return choice(
|
|
1911
|
+
$.expression,
|
|
1912
|
+
$.lvalue_expression,
|
|
1913
|
+
$.invocation_expression,
|
|
1914
|
+
$.postfix_unary_expression,
|
|
1915
|
+
$.parenthesized_expression
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1858
1919
|
/**
|
|
1859
1920
|
* Creates a rule to match one or more of the rules separated by a comma
|
|
1860
1921
|
*
|
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
|