Let final and abstract be used as variable names - #52
Merged
Conversation
Every other modifier keyword already worked as an ordinary name -- public, private, package, remote, component, interface, static -- because the identifier rule lists them. FINAL and ABSTRACT were missing, so `final = 3;` and `abstract = 4;` were syntax errors. Same shape as the three already recorded in CLAUDE.md, and the fix is the same: add them to identifier alongside default, var, to, include, new. The one that needed checking is the pair FINAL now serves. `final x = 1;` is Lucee's immutable local, added in #34, so FINAL both starts a declaration and is a name. Both parse and, more to the point, build different trees: `final = 3;` decompiles as an assignment to a variable called final, `final x = 1;` as a declaration. `var final = 1;` and `final var y = 2;` are covered too, and the fixture pins all four together so a later change cannot collapse them. Differential harness 8 disagreements to 6 -- both corpus cases for this, and nothing newly broken. Verified end to end -- 313 cfparser tests, ./gradlew build, CFLint's 675. Closes #46 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GzpZFd4rnE1Yi2sVHAji35
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #46.
Every other modifier keyword already worked as an ordinary name —
public,private,package,remote,component,interface,static— because theidentifierrule lists them.FINALandABSTRACTwere missing:Same shape as the three recorded in
CLAUDE.md, and the same fix: add them toidentifieralongsidedefault,var,to,include,new.The part worth reviewing
FINALnow serves double duty.final x = 1;is Lucee's immutable local, added in #34, so the token both starts a declaration and is a name. A green parse proves nothing here — the question is whether the two still build different trees:final = 3;final = 3finalfinal x = 1;final x = 1var final = 1;var final = 1finalfinal var y = 2;final y = 2All four distinct, and the fixture pins them together so a later change can't quietly collapse one into another. The modifier positions (
abstract component {},final function f() {}) are unaffected.One cosmetic note:
final var y = 2decompiles asfinal y = 2, dropping thevar. Both spell the same thing andCFVarDeclExpressioncarries a single flag rather than tracking both keywords — pre-existing from #34, not introduced here.Verification
./gradlew buildidentifier-capable keywords still work as identifiersandkeywords as variable names), nothing newly brokencfml.parsing/src/mainstashedGenerated by Claude Code