tree-sitter-delphi13 1.2.1 → 1.2.2

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 CHANGED
@@ -2,15 +2,22 @@
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/tree-sitter-delphi13.svg)](https://www.npmjs.com/package/tree-sitter-delphi13)
4
4
  [![license](https://img.shields.io/npm/l/tree-sitter-delphi13.svg)](LICENSE)
5
+ [![corpus](https://img.shields.io/badge/valid_Delphi_13-100.000%25-brightgreen.svg)](CORPUS-CEILING-REPORT.md)
6
+ [![corpus raw](https://img.shields.io/badge/full_corpus_raw-99.82%25-green.svg)](CORPUS-CEILING-REPORT.md)
5
7
 
6
8
  Tree-sitter grammar pipeline focused on **Delphi 13 (RAD Studio 37.0 / Florence)** and the surrounding modern Delphi ecosystem.
7
9
 
8
- **v1.2.1: 100.000% pass rate on compilable Delphi 13** (zero ERROR nodes), measured
9
- on an 11,722-unique-file corpus spanning the RAD Studio 13 RTL/VCL (including
10
- `System.pas`), DevExpress, Spring4D, EurekaLog, Indy, FireDAC, AsyncPro/Orpheus,
11
- mORMot-era community code and a full production application. Every failure that
12
- remains is individually diagnosed, dcc32-cross-checked, and *supposed* to fail
13
- (see [CORPUS-CEILING-REPORT.md](CORPUS-CEILING-REPORT.md)).
10
+ **v1.2.2: 100.000% pass rate on compilable Delphi 13** (zero ERROR nodes), measured
11
+ on a corpus spanning the RAD Studio 13 RTL/VCL (including `System.pas`), DevExpress,
12
+ Spring4D, EurekaLog, Indy, FireDAC, AsyncPro/Orpheus, **JCL/JVCL (JEDI)**, mORMot-era
13
+ community code and a full production application — 23,385 deduplicated files. Every
14
+ failure that remains is individually diagnosed, dcc32-cross-checked, and *supposed*
15
+ to fail (see [CORPUS-CEILING-REPORT.md](CORPUS-CEILING-REPORT.md)).
16
+
17
+ v1.2.2 added the JEDI (JCL + JVCL) libraries to the corpus and closed the three
18
+ valid-Delphi-13 gaps they surfaced: a subrange bound that is a nested constant-expr
19
+ call (`2..Succ(High(T))`), the `at` soft keyword as an `inherited` method name
20
+ (`inherited At(...)`), and `Operator` used as a record/class field name.
14
21
 
15
22
  | measurement basis | pass rate |
16
23
  |---|---|
@@ -31,9 +38,9 @@ watchlist).
31
38
  |---|---|
32
39
  | **`tree-sitter-delphi13`** *(this directory)* | Master grammar — Delphi-13 syntax, all proven fixes from upstream merged + new extensions. Self-contained "THEN-wins" parser (98.6% raw on its own). |
33
40
  | **[`tree-sitter-delphi13-pure`](pure/)** | Simpler sub-grammar that drops `pp_*` tokens entirely. Expects preprocessor-resolved source. |
34
- | **[`delphi13-preprocessor`](preprocessor/)** | Standalone JavaScript library that resolves `{$IFDEF}` / `{$IF}` / `{$DEFINE}` / `{$I X.inc}` directives as a text transformation. |
41
+ | **[`delphi13-preprocessor`](preprocessor/)** | Standalone JavaScript library that resolves `{$IFDEF}` / `{$IF}` / `{$DEFINE}` / `{$I X.inc}` directives as a text transformation. The **canonical** preprocessor is now a pure-Delphi port of this library (shipping inside drag-lint); this JS package remains the byte-for-byte oracle and the drop-in choice for JavaScript consumers. |
35
42
 
36
- The full pipeline `preprocessor → pure → AST` is what reaches **99.97%** on valid
43
+ The full pipeline `preprocessor → pure → AST` is what reaches **100.000%** on valid
37
44
  Delphi 13. Use the master grammar alone (98.6% raw) if you don't need
38
45
  conditional-compilation awareness; use the pipeline if you do.
39
46
 
@@ -138,7 +145,9 @@ node-gyp rebuild
138
145
 
139
146
  - **Inline `asm` blocks** treated as opaque text by design. Not tree-sitter-asm.
140
147
  - **`{$IF declared(SymName)}`** always evaluates to `false` — no symbol table. ~10 corpus files use this. A lightweight symbol pre-scan would address most cases.
141
- - **Include search path** is currently same-directory only. Cross-directory `{$I ..\Common\X.inc}` requires a search-path option (see TODO.md).
148
+ - **Include resolution** is nearest-first (same directory, its subdirectories, then
149
+ up to 3 parent levels with their subdirectories — v1.1.0 of the preprocessor).
150
+ Arbitrary project search paths still need the `includePaths` option.
142
151
  - **FreePascal-specific extensions** (operator overloading variants, `{$mode ObjFPC}` directives, macOS PasCocoa namespaces) are not covered. A separate `tree-sitter-delphi-plus-fp` repo is planned.
143
152
 
144
153
  ## Acknowledgements
package/grammar.js CHANGED
@@ -756,7 +756,16 @@ module.exports = grammar({
756
756
  field('body', choice(tr($, 'block'), tr($, 'asm'))),
757
757
  ),
758
758
 
759
- inherited: $ => prec.right(seq($.kInherited, optional($.identifier))),
759
+ inherited: $ => prec.right(seq($.kInherited, optional(choice(
760
+ $.identifier,
761
+ // Soft keyword `at` (the raise-with-address `raise E at Addr`
762
+ // keyword) used as an INHERITED method name: `inherited At(Offset)`
763
+ // (JCL JclCLR.pas). `At` already works as a plain/dotted call and a
764
+ // field name; only the inherited slot lost it to the kAtWord token.
765
+ // Aliased to identifier so the call-args attach exactly as for
766
+ // `inherited Foo(x)`. Narrow — only the corpus-confirmed kAtWord.
767
+ alias($.kAtWord, $.identifier),
768
+ )))),
760
769
 
761
770
  exprDot: $ => choice(
762
771
  op.infix(5, $._ref, $.kDot, $._ref),
@@ -1288,6 +1297,13 @@ module.exports = grammar({
1288
1297
  // conflicts with typerefDot in this position.)
1289
1298
  seq($.identifier, '.', $.identifier),
1290
1299
  seq($.identifier, '(', $.identifier, ')'),
1300
+ // Iter 2026-07-17: nested const-expr call bound —
1301
+ // `2 .. Succ(High(TDigitValue))` (JCL JclSysUtils TNumericSystemBase).
1302
+ // dcc accepts any constant ordinal expression as a bound; the grammar
1303
+ // stays with the narrow corpus-driven enumeration (a wide `_expr`
1304
+ // bound blows the parser tables, see above), adding just the one
1305
+ // real shape: `Ident( Ident(Ident) )`, one level of call nesting.
1306
+ seq($.identifier, '(', seq($.identifier, '(', $.identifier, ')'), ')'),
1291
1307
  // `hid - 1`, `MaxN + 2` — narrow `identifier OP integer` form for
1292
1308
  // real-corpus patterns like `TNmbrRange = 0 .. hid - 1;`.
1293
1309
  // Kept narrow (no full _expr) to avoid the conflict cascade hit
@@ -1663,6 +1679,12 @@ module.exports = grammar({
1663
1679
  field('name', delimited1(choice(
1664
1680
  $.identifier,
1665
1681
  alias($.kRegister, $.identifier),
1682
+ // Iter 2026-07-17: `Operator` as a FIELD NAME
1683
+ // (`Operator: TJvXmlSQLOperator;` — JVCL JvXmlDatabase). The
1684
+ // `operator` token otherwise starts _declOperator; GLR splits
1685
+ // on the follow token (`:` -> field, operator-name -> class
1686
+ // operator). Same narrow one-keyword alias as kRegister above.
1687
+ alias($.kOperator, $.identifier),
1666
1688
  ))),
1667
1689
  ':',
1668
1690
  // Iter 2026-07-06: a record/class field type may be a subrange, same
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tree-sitter-delphi13",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Tree-sitter grammar focused on Delphi 13 (RAD Studio 37.0)",
5
5
  "main": "bindings/node",
6
6
  "types": "bindings/node",
package/src/grammar.json CHANGED
@@ -3671,8 +3671,22 @@
3671
3671
  "type": "CHOICE",
3672
3672
  "members": [
3673
3673
  {
3674
- "type": "SYMBOL",
3675
- "name": "identifier"
3674
+ "type": "CHOICE",
3675
+ "members": [
3676
+ {
3677
+ "type": "SYMBOL",
3678
+ "name": "identifier"
3679
+ },
3680
+ {
3681
+ "type": "ALIAS",
3682
+ "content": {
3683
+ "type": "SYMBOL",
3684
+ "name": "kAtWord"
3685
+ },
3686
+ "named": true,
3687
+ "value": "identifier"
3688
+ }
3689
+ ]
3676
3690
  },
3677
3691
  {
3678
3692
  "type": "BLANK"
@@ -7195,6 +7209,44 @@
7195
7209
  }
7196
7210
  ]
7197
7211
  },
7212
+ {
7213
+ "type": "SEQ",
7214
+ "members": [
7215
+ {
7216
+ "type": "SYMBOL",
7217
+ "name": "identifier"
7218
+ },
7219
+ {
7220
+ "type": "STRING",
7221
+ "value": "("
7222
+ },
7223
+ {
7224
+ "type": "SEQ",
7225
+ "members": [
7226
+ {
7227
+ "type": "SYMBOL",
7228
+ "name": "identifier"
7229
+ },
7230
+ {
7231
+ "type": "STRING",
7232
+ "value": "("
7233
+ },
7234
+ {
7235
+ "type": "SYMBOL",
7236
+ "name": "identifier"
7237
+ },
7238
+ {
7239
+ "type": "STRING",
7240
+ "value": ")"
7241
+ }
7242
+ ]
7243
+ },
7244
+ {
7245
+ "type": "STRING",
7246
+ "value": ")"
7247
+ }
7248
+ ]
7249
+ },
7198
7250
  {
7199
7251
  "type": "SEQ",
7200
7252
  "members": [
@@ -9658,6 +9710,15 @@
9658
9710
  },
9659
9711
  "named": true,
9660
9712
  "value": "identifier"
9713
+ },
9714
+ {
9715
+ "type": "ALIAS",
9716
+ "content": {
9717
+ "type": "SYMBOL",
9718
+ "name": "kOperator"
9719
+ },
9720
+ "named": true,
9721
+ "value": "identifier"
9661
9722
  }
9662
9723
  ]
9663
9724
  },
@@ -9689,6 +9750,15 @@
9689
9750
  },
9690
9751
  "named": true,
9691
9752
  "value": "identifier"
9753
+ },
9754
+ {
9755
+ "type": "ALIAS",
9756
+ "content": {
9757
+ "type": "SYMBOL",
9758
+ "name": "kOperator"
9759
+ },
9760
+ "named": true,
9761
+ "value": "identifier"
9692
9762
  }
9693
9763
  ]
9694
9764
  }