tree-sitter-delphi13-pure 1.1.0 → 1.2.0
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/grammar.js +154 -34
- package/package.json +1 -1
- package/src/grammar.json +935 -74
- package/src/node-types.json +79 -0
- package/src/parser.c +376445 -337868
package/grammar.js
CHANGED
|
@@ -104,8 +104,15 @@ function enable_if(cond, ...args) {
|
|
|
104
104
|
// Generate rules for trailing & non-trailing statements
|
|
105
105
|
function statements(trailing) {
|
|
106
106
|
let rn = x => trailing ? x + 'Tr' : x
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
// Ported from root 2026-07-16: a goto label may prefix the
|
|
108
|
+
// single-statement BODY of then/else/do/on (`if I = 0 then Found: ...`,
|
|
109
|
+
// `else FoundMismatch: Exit`, `while true do redo: case ...`).
|
|
110
|
+
// prec.dynamic(-1) keeps the case-ARM interpretation winning where a
|
|
111
|
+
// label could also open an arm; requires [caseCase]/[caseCaseTr]
|
|
112
|
+
// conflicts.
|
|
113
|
+
let bodyLabel = $ => optional(prec.dynamic(-1, $.label));
|
|
114
|
+
let lastStatement = $ => trailing ? optional(seq(bodyLabel($), tr($,'_statement'))) : seq(bodyLabel($), $._statement);
|
|
115
|
+
let lastStatement1= $ => trailing ? seq(bodyLabel($), tr($,'_statement')) : seq(bodyLabel($), $._statement);
|
|
109
116
|
let semicolon = trailing ? [] : [';'];
|
|
110
117
|
|
|
111
118
|
return Object.fromEntries([
|
|
@@ -272,6 +279,37 @@ function statements(trailing) {
|
|
|
272
279
|
]);
|
|
273
280
|
}
|
|
274
281
|
|
|
282
|
+
// Ported from root 2026-07-16: shared front of a routine declaration
|
|
283
|
+
// (everything before the first `;`) — used by _declProc (strict tail,
|
|
284
|
+
// backs defProc) and _declProcLenient (separator-form tail, interface
|
|
285
|
+
// declaration lists only).
|
|
286
|
+
function declProcFront($) {
|
|
287
|
+
return [
|
|
288
|
+
...enable_if(fpc, optional($.kGeneric)),
|
|
289
|
+
optional($.kClass),
|
|
290
|
+
choice($.kProcedure, $.kFunction, $.kConstructor, $.kDestructor),
|
|
291
|
+
field('name', $._genericName),
|
|
292
|
+
field('args', optional($.declArgs)),
|
|
293
|
+
optional(seq(
|
|
294
|
+
':',
|
|
295
|
+
field('type', $.typeref),
|
|
296
|
+
)),
|
|
297
|
+
field('assign', optional($.defaultValue)),
|
|
298
|
+
// Inline calling-convention or procAttribute BEFORE the terminating
|
|
299
|
+
// ';' — Embarcadero RTL / AzureAPI use lenient forms:
|
|
300
|
+
// function DbiInitFn(...): DBIResult stdcall; (iter 56)
|
|
301
|
+
// procedure PreflightBlobRequest(...) overload; (iter 60)
|
|
302
|
+
// `repeat` allows multiple chained attributes like `... cdecl overload`.
|
|
303
|
+
repeat(choice(
|
|
304
|
+
$.kStdcall, $.kCdecl, $.kSafecall, $.kPascal,
|
|
305
|
+
$.kRegister, $.kWinapi, $.kInline,
|
|
306
|
+
$.kOverload, $.kVirtual, $.kAbstract, $.kOverride,
|
|
307
|
+
$.kReintroduce, $.kStatic, $.kDynamic, $.kFinal,
|
|
308
|
+
$.kUnsafe // ARC/AUTOREFCOUNT method directive (ported v1.1.0)
|
|
309
|
+
)),
|
|
310
|
+
];
|
|
311
|
+
}
|
|
312
|
+
|
|
275
313
|
module.exports = grammar({
|
|
276
314
|
name: "delphi13_pure",
|
|
277
315
|
|
|
@@ -308,6 +346,21 @@ module.exports = grammar({
|
|
|
308
346
|
// optional _definitions before AND after declContains. GLR forks
|
|
309
347
|
// on which slot absorbs a given definition.
|
|
310
348
|
[$.package],
|
|
349
|
+
// Iter 2026-07-16 (implicit-init, ported from root): the unit tail's
|
|
350
|
+
// `tr($,'block')` arm forks against `implementation` absorbing the
|
|
351
|
+
// same `begin` into its `_definitions` (prec(-1) blockTr recovery).
|
|
352
|
+
// GLR keeps both; precedence picks the unit-tail block.
|
|
353
|
+
[$.implementation],
|
|
354
|
+
// Iter 2026-07-16 (label-as-body, ported from root): body label vs
|
|
355
|
+
// the arm's own jumpLabel slot (`1: Foo: x`); prec.dynamic(-1) keeps
|
|
356
|
+
// the arm interpretation winning.
|
|
357
|
+
[$.caseCase],
|
|
358
|
+
[$.caseCaseTr],
|
|
359
|
+
// Iter 2026-07-16 (lenient directive tail, ported from root): group
|
|
360
|
+
// separator `;` vs optional final `;`, and lenient-tail groups vs
|
|
361
|
+
// declProcFwd's strict groups while both are live.
|
|
362
|
+
[$.procAttribute],
|
|
363
|
+
[$._declProcLenient, $._procAttributeNoExt],
|
|
311
364
|
// Anonymous record/class types in type position conflict with the
|
|
312
365
|
// type-declaration form (`type Foo = record ... end;`). Both reach
|
|
313
366
|
// declClass but at different parser states.
|
|
@@ -381,13 +434,29 @@ module.exports = grammar({
|
|
|
381
434
|
|
|
382
435
|
rules: {
|
|
383
436
|
root: $ => optional(choice(
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
437
|
+
seq(
|
|
438
|
+
choice(
|
|
439
|
+
$.program,
|
|
440
|
+
$.library,
|
|
441
|
+
$.unit,
|
|
442
|
+
$.package,
|
|
443
|
+
),
|
|
444
|
+
// Iter 2026-07-16 (ported from root): dcc ignores everything
|
|
445
|
+
// after the final `end.` (warning W1011 only). One
|
|
446
|
+
// low-precedence catch-all token; linters can flag the node.
|
|
447
|
+
optional($.trailingText),
|
|
448
|
+
),
|
|
388
449
|
$._definitions // For include files
|
|
389
450
|
)),
|
|
390
451
|
|
|
452
|
+
// Everything from the first non-blank char after the module's final
|
|
453
|
+
// `end.` to EOF. token(prec(-2)) so real tokens (incl. comments)
|
|
454
|
+
// always win over it.
|
|
455
|
+
// NOTE: `(.|\s)*` rather than `[\s\S]*` — tree-sitter's regex engine
|
|
456
|
+
// compiles the latter to a non-greedy/empty match (token stopped after
|
|
457
|
+
// one char; observed 2026-07-16).
|
|
458
|
+
trailingText: $ => token(prec(-2, /[^\s](.|\s)*/)),
|
|
459
|
+
|
|
391
460
|
// HIGH LEVEL ----------------------------------------------------------
|
|
392
461
|
|
|
393
462
|
program: $ => seq(
|
|
@@ -420,13 +489,32 @@ module.exports = grammar({
|
|
|
420
489
|
$.kLibrary, // ported from root v1.1.0
|
|
421
490
|
)),
|
|
422
491
|
';',
|
|
492
|
+
// Unit tail, restructured 2026-07-16 (ported from root, iter:
|
|
493
|
+
// implicit-init): `initialization`/`finalization` moved out of the
|
|
494
|
+
// flat repeat into the kEnd tail arm, plus a mutually-exclusive
|
|
495
|
+
// `tr($,'block')` arm for the Turbo-Pascal implicit initialization
|
|
496
|
+
// block (`begin <stmts> end.` — dcc 13 still accepts it). Because
|
|
497
|
+
// the block arm is unreachable once `initialization` appears, the
|
|
498
|
+
// statement-list fork the old shape suffered cannot arise; the only
|
|
499
|
+
// fork is blockTr-inside-_definitions (prec -1 recovery) vs
|
|
500
|
+
// blockTr-as-unit-tail (prec 0), same as `library`. Requires the
|
|
501
|
+
// [$.implementation] conflict. CST: the implicit block renders as
|
|
502
|
+
// the same `block` node `program`/`library` produce.
|
|
423
503
|
repeat(choice(
|
|
424
504
|
$.interface,
|
|
425
505
|
$.implementation,
|
|
426
|
-
$.initialization,
|
|
427
|
-
$.finalization,
|
|
428
506
|
)),
|
|
429
|
-
|
|
507
|
+
choice(
|
|
508
|
+
seq(
|
|
509
|
+
repeat(choice(
|
|
510
|
+
$.initialization,
|
|
511
|
+
$.finalization,
|
|
512
|
+
)),
|
|
513
|
+
$.kEnd
|
|
514
|
+
),
|
|
515
|
+
tr($,'block'),
|
|
516
|
+
),
|
|
517
|
+
$.kEndDot
|
|
430
518
|
),
|
|
431
519
|
|
|
432
520
|
// Delphi package file (.dpk). Structure:
|
|
@@ -515,6 +603,13 @@ module.exports = grammar({
|
|
|
515
603
|
// en/EN not followed by d/D, end immediately followed by ident-char
|
|
516
604
|
// (so it's NOT the keyword, e.g. 'endif' / 'endloop').
|
|
517
605
|
asmBody: $ => token(prec(-1, repeat1(choice(
|
|
606
|
+
// Ported from root 2026-07-16: consume a whole COMMENT as one chunk so a
|
|
607
|
+
// bare `end` *inside* a comment doesn't falsely terminate the asm block.
|
|
608
|
+
// add edi,ecx {point EDI to end of destination} <-- AsyncPro AwFView
|
|
609
|
+
// mov eax,1 // end of loop
|
|
610
|
+
// Must precede the single-char alternatives: longest match wins.
|
|
611
|
+
/\{[^}]*\}/,
|
|
612
|
+
/\/\/[^\n]*/,
|
|
518
613
|
// Identifier not starting with e/E — consume as a unit so an
|
|
519
614
|
// embedded `end` substring (like in `addend` or `xchg ext`)
|
|
520
615
|
// doesn't falsely terminate the body.
|
|
@@ -805,8 +900,18 @@ module.exports = grammar({
|
|
|
805
900
|
$.identifier, $.genericDot, ...enable_if(templates, $.genericTpl)
|
|
806
901
|
),
|
|
807
902
|
genericArgs: $ => delimited1($.genericArg, ';'),
|
|
903
|
+
// Ported from root 2026-07-16: nested generic instantiation as a
|
|
904
|
+
// genericArg name element (method resolution clause `function
|
|
905
|
+
// TFunc<T1, IEnumerable<TResult>>.Invoke = Bind;`). Self-contained
|
|
906
|
+
// identifier-only recursion — referencing genericTpl/_genericName
|
|
907
|
+
// here explodes table construction.
|
|
908
|
+
genericArgTpl: $ => seq(
|
|
909
|
+
$.identifier, $.kLt,
|
|
910
|
+
delimited1(choice($.identifier, $.genericArgTpl)),
|
|
911
|
+
$.kGt
|
|
912
|
+
),
|
|
808
913
|
genericArg: $ => seq(
|
|
809
|
-
field('name', delimited1($.identifier)),
|
|
914
|
+
field('name', delimited1(choice($.identifier, $.genericArgTpl))),
|
|
810
915
|
// Type constraint: `T: BaseType` or one/more of the special
|
|
811
916
|
// constraint keywords `class` / `record` / `constructor`, comma-
|
|
812
917
|
// separated. Examples:
|
|
@@ -943,7 +1048,11 @@ module.exports = grammar({
|
|
|
943
1048
|
),
|
|
944
1049
|
|
|
945
1050
|
_declarations: $ => repeat1(choice(
|
|
946
|
-
$.declTypes, $.declVars, $.declConsts,
|
|
1051
|
+
$.declTypes, $.declVars, $.declConsts,
|
|
1052
|
+
// Lenient directive tail in interface declaration lists (ported
|
|
1053
|
+
// from root); rendered as a plain declProc node.
|
|
1054
|
+
alias($.declProcLenient, $.declProc),
|
|
1055
|
+
$.declProp,
|
|
947
1056
|
alias($.declProcFwd, $.declProc),
|
|
948
1057
|
$.declUses, $.declLabels, $.declExports,
|
|
949
1058
|
// Phase 3 (pure): CIL/.NET [assembly: ...] attributes inside
|
|
@@ -1110,6 +1219,12 @@ module.exports = grammar({
|
|
|
1110
1219
|
...enable_if(rtti, optional($.rttiAttributes)),
|
|
1111
1220
|
choice($._declProc, $._declOperator),
|
|
1112
1221
|
),
|
|
1222
|
+
// Interface/forward flavor with the lenient directive tail; aliased
|
|
1223
|
+
// back to `declProc` at its use site (CST-identical).
|
|
1224
|
+
declProcLenient: $ => seq(
|
|
1225
|
+
...enable_if(rtti, optional($.rttiAttributes)),
|
|
1226
|
+
choice($._declProcLenient, $._declOperator),
|
|
1227
|
+
),
|
|
1113
1228
|
|
|
1114
1229
|
declVar: $ => seq(
|
|
1115
1230
|
...enable_if(rtti, optional($.rttiAttributes)),
|
|
@@ -1140,6 +1255,13 @@ module.exports = grammar({
|
|
|
1140
1255
|
alias($.kDeprecated, $.identifier),
|
|
1141
1256
|
alias($.kExperimental, $.identifier),
|
|
1142
1257
|
alias($.kRegister, $.identifier),
|
|
1258
|
+
// Ported from root 2026-07-16: same family — `local` is a
|
|
1259
|
+
// procAttribute, so `var X: Integer; Local: Integer;` had the
|
|
1260
|
+
// parser eat `Local` as a trailing directive on X.
|
|
1261
|
+
alias($.kLocal, $.identifier),
|
|
1262
|
+
// Ported from root 2026-07-16: `dispid` is a property/method
|
|
1263
|
+
// directive — same trap (System.Win.ObjComAuto, Vcl.OleCtrls).
|
|
1264
|
+
alias($.kDispId, $.identifier),
|
|
1143
1265
|
))),
|
|
1144
1266
|
':',
|
|
1145
1267
|
// Phase 3b iter 36: declVar type may be a subrange:
|
|
@@ -1500,32 +1622,27 @@ module.exports = grammar({
|
|
|
1500
1622
|
// Stuff for procedure / function / operator declarations
|
|
1501
1623
|
|
|
1502
1624
|
_declProc: $ => seq(
|
|
1503
|
-
...
|
|
1504
|
-
optional($.kClass),
|
|
1505
|
-
choice($.kProcedure, $.kFunction, $.kConstructor, $.kDestructor),
|
|
1506
|
-
field('name', $._genericName),
|
|
1507
|
-
field('args', optional($.declArgs)),
|
|
1508
|
-
optional(seq(
|
|
1509
|
-
':',
|
|
1510
|
-
field('type', $.typeref),
|
|
1511
|
-
)),
|
|
1512
|
-
field('assign', optional($.defaultValue)),
|
|
1513
|
-
// Inline calling-convention or procAttribute BEFORE the terminating
|
|
1514
|
-
// ';' — Embarcadero RTL / AzureAPI use lenient forms:
|
|
1515
|
-
// function DbiInitFn(...): DBIResult stdcall; (iter 56)
|
|
1516
|
-
// procedure PreflightBlobRequest(...) overload; (iter 60)
|
|
1517
|
-
// `repeat` allows multiple chained attributes like `... cdecl overload`.
|
|
1518
|
-
repeat(choice(
|
|
1519
|
-
$.kStdcall, $.kCdecl, $.kSafecall, $.kPascal,
|
|
1520
|
-
$.kRegister, $.kWinapi, $.kInline,
|
|
1521
|
-
$.kOverload, $.kVirtual, $.kAbstract, $.kOverride,
|
|
1522
|
-
$.kReintroduce, $.kStatic, $.kDynamic, $.kFinal,
|
|
1523
|
-
$.kUnsafe // ARC/AUTOREFCOUNT method directive (ported v1.1.0)
|
|
1524
|
-
)),
|
|
1625
|
+
...declProcFront($),
|
|
1525
1626
|
';',
|
|
1627
|
+
// STRICT tail — backs defProc, where the `;` before the body is
|
|
1628
|
+
// mandatory. Lenient separator-form twin below (ported from root).
|
|
1526
1629
|
repeat($._procAttributeNoExt)
|
|
1527
1630
|
),
|
|
1528
1631
|
|
|
1632
|
+
// Lenient twin for interface declaration lists: directive groups are
|
|
1633
|
+
// `;`-SEPARATED with the final `;` optional, so
|
|
1634
|
+
// `function F: Boolean; overload` before another declaration parses
|
|
1635
|
+
// (dxCryptoAPI, dxServerModeUtils, dxGDIPlusAPI — dcc32-verified).
|
|
1636
|
+
_declProcLenient: $ => seq(
|
|
1637
|
+
...declProcFront($),
|
|
1638
|
+
';',
|
|
1639
|
+
optional(seq(
|
|
1640
|
+
repeat1(field('attribute', $.procAttribute)),
|
|
1641
|
+
repeat(seq(';', repeat1(field('attribute', $.procAttribute)))),
|
|
1642
|
+
optional(';')
|
|
1643
|
+
))
|
|
1644
|
+
),
|
|
1645
|
+
|
|
1529
1646
|
_declOperator: $ => seq(
|
|
1530
1647
|
optional($.kClass),
|
|
1531
1648
|
$.kOperator,
|
|
@@ -1921,7 +2038,10 @@ module.exports = grammar({
|
|
|
1921
2038
|
// so structural tokens stay intact.
|
|
1922
2039
|
identifier: $ => /&{0,2}[a-zA-Z_-][0-9_a-zA-Z-]*/,
|
|
1923
2040
|
|
|
1924
|
-
|
|
2041
|
+
// Classic Pascal treats every control char <= #31 as a token
|
|
2042
|
+
// separator (dcc compiles sources with stray bytes like the 0x12 in
|
|
2043
|
+
// DevExpress dxPDFForm.pas), so the whitespace extra does too.
|
|
2044
|
+
_space: $ => /[\s\x00-\x1F]+/,
|
|
1925
2045
|
// Single preprocessor directive. The external scanner (src/scanner.c)
|
|
1926
2046
|
// handles multi-line `{$IF*}...{$END*}` blocks via the pp_block token,
|
|
1927
2047
|
// refusing blocks that wrap structural decls so they parse normally.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tree-sitter-delphi13-pure",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Pure Delphi 13 tree-sitter sub-grammar — drops {$IFDEF}/pp_* tokens entirely and expects preprocessor-resolved source as input. Pairs with delphi13-preprocessor to reach 99%+ pass on real Delphi 13 corpora.",
|
|
5
5
|
"main": "bindings/node",
|
|
6
6
|
"types": "bindings/node",
|