Skip to content

Fix keyword typos, support bare raise and property re-publication#20

Open
wpostma wants to merge 6 commits into
Isopod:masterfrom
wpostma:master
Open

Fix keyword typos, support bare raise and property re-publication#20
wpostma wants to merge 6 commits into
Isopod:masterfrom
wpostma:master

Conversation

@wpostma
Copy link
Copy Markdown

@wpostma wpostma commented Mar 6, 2026

Summary

Three grammar fixes for Delphi/Object Pascal constructs that produce parse errors on valid code:

  • Fix kSafecall regex typo: /safecal/i/safecall/i — the missing trailing l meant safecall was never recognized as a keyword, causing thousands of errors in COM type library imports (MSHTML, Word_TLB, mscorlib_TLB, etc.)
  • Fix kSealed regex typo: /seled/i/sealed/isealed classes were never recognized
  • Support bare raise;: Delphi allows raise; without an expression to re-raise the current exception inside an except block. Made the expression field optional.
  • Support property re-publication: Delphi descendant classes can re-publish inherited properties without repeating the type declaration, e.g. property Align;, property Font;, optionally with specifiers like property Visible stored False; or property BookmarkSize write SetBookmarkSize;. Made the : type portion of declProp optional.

Testing

Validated against 400 unique .pas files (182.6 MB, 5.1M lines) from real-world Delphi codebases including Embarcadero RTL/FMX/VCL sources, TMS components, ElevateDB, JCL/JEDI, mORMot, DevExpress, and business applications.

Results from specific files:

File Errors before Errors after Notes
FMX.StdCtrls.pas 1,598 0 100% clean
FireDAC.Comp.DataSet.pas 2,118 0 100% clean
edblocal.pas 474 14 bare raise fix
AdvToolBar.pas 612 312 remaining errors are other gaps
MSHTML.pas 11,706 6,087 safecall fix; remaining are readonly/dispinterface gaps

Grammar changes

 # kSafecall typo
-kSafecall: $ => /safecal/i,
+kSafecall: $ => /safecall/i,

 # kSealed typo
-kSealed: $ => /seled/i,
+kSealed: $ => /sealed/i,

 # Bare raise
-field('exception', $._expr),
+field('exception', optional($._expr)),

 # Property re-publication
-':',
-field('type', $.type),
+optional(seq(':', field('type', $.type))),

# JNI Bindings  allow $ in property names, such as read _Getval$transformer
  [JavaSignature('com/clover/core/internal/Lists$1')]
  JLists_1 = interface(JIterable)
    ['{7BC2900F-BE04-4ACD-B54B-EF426100E8A9}']
    function _Getval$transformer: JLists_Transformer; cdecl;
    property val$transformer: JLists_Transformer read _Getval$transformer;
  end;

wpostma and others added 3 commits March 5, 2026 15:35
kSafecall was /safecal/i (missing trailing 'l'), so safecall was never
recognized as a keyword. This caused thousands of parse errors in COM
type library imports (MSHTML, Word_TLB, mscorlib_TLB, etc.).

kSealed was /seled/i (missing 'a'), so sealed classes were never
recognized.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In Delphi, `raise;` without an expression re-raises the current
exception inside an except block. The grammar required an expression
after raise, causing parse errors on this common pattern.

Tested: edblocal.pas errors dropped from 474 to 14.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In Delphi, descendant classes can re-publish inherited properties
without repeating the type: `property Align;`, `property Font;`,
optionally with specifiers like `property Visible stored False;`
or `property BookmarkSize write SetBookmarkSize;`.

The grammar required `: type` after every property name. Made it
optional so both full declarations and re-publications parse.

Tested against 15 synthetic cases and real-world files:
- FMX.StdCtrls.pas: 1,598 -> 0 errors
- FireDAC.Comp.DataSet.pas: 2,118 -> 0 errors
- AdvToolBar.pas: 612 -> 312 errors (remaining are other gaps)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wpostma
Copy link
Copy Markdown
Author

wpostma commented Mar 6, 2026

Fixes top three issues in
#19

PR'ing them because they're the lowest risk changes, and I have validated against 400 of my largest pas files in my local working folders.

Delphi's JNI/Android binding generator produces identifiers containing
$ signs (e.g. val$transformer, Address$CacheKey$1). These are valid
Delphi identifiers but the grammar rejected them.

Added $ to the continuation character class of the identifier rule.
No conflict with hex literals ($FF) since those start with $ while
identifiers start with [a-zA-Z_].

Scanned 400 real-world .pas files: $ is the only non-standard
character that appears in actual identifiers (all others like
backtick, accented chars were inside comments/strings).

Tested: Clover.JNI.AllClasses.pas errors dropped from 1,924 to 0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wpostma
Copy link
Copy Markdown
Author

wpostma commented Mar 6, 2026

Note on the $ identifier fix (commit b34c593): The $ character in identifiers is not standard Object Pascal — it comes specifically from Delphi's JNI/Android binding generator, which translates Java nested class names like Address.CacheKey into Address$CacheKey. This is the only context where $ appears in real-world Delphi identifiers, confirmed by scanning 400 large .pas files from diverse codebases.

@AntoineGS
Copy link
Copy Markdown

I've run into the bare raise issue in a current use of this, I would be happy to see this merged :)

@wpostma
Copy link
Copy Markdown
Author

wpostma commented Mar 20, 2026

I've run into the bare raise issue in a current use of this, I would be happy to see this merged :)

Can you pull this branch in from my fork and try it with your cases?

Testing effort would probably get it merged.

@AntoineGS
Copy link
Copy Markdown

I can whip something together, I was using the crate as-is but I can use a local repo instead.
My use case is still in its early stages so testing will not be as useful as a more mature project :)

@wpostma
Copy link
Copy Markdown
Author

wpostma commented Mar 25, 2026

@Isopod any interest in this pr ?

fschetterer added a commit to fschetterer/tree-sitter-pascal that referenced this pull request Mar 26, 2026
- Fix safecall/sealed keyword regex typos (Issues Isopod#19/Isopod#20)
- Support bare raise; without exception expression
- Support property re-publication without type (property Name;)
- Allow $ in identifiers for JNI binding names
- Support for-var-in loops (for var Item in List do) (Issue Isopod#15)
- Add inline const declarations in statement blocks (Issue Isopod#17)
AntoineGS added a commit to AntoineGS/lint4d that referenced this pull request Apr 6, 2026
Switches to AntoineGS/tree-sitter-pascal which includes Isopod/tree-sitter-pascal#20,
fixing parsing of bare `raise;` (reraise) statements that were previously dropped.
@AntoineGS
Copy link
Copy Markdown

I can confirm it resolves my issue with the bare raise statement!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants