From 64e3db31bb91a28ea8ad5709c09f672aed9a60bc Mon Sep 17 00:00:00 2001 From: Partouf Date: Thu, 8 Oct 2026 18:16:47 +0200 Subject: [PATCH 1/2] Register the UnicodeString keyword handler TmwBasePasLex.Func158 lexes UnicodeString as ptString with ExID ptUnicodeString, the way Func-handlers already treat AnsiString and WideString, but InitIdent never put it in FIdentFuncTable. 'UnicodeString' hashes to 158, which had no entry, so the handler was unreachable (Delphi: H2219 Private symbol 'Func158' declared but never used) and the word lexed as a plain identifier. Declarations parse the same either way. The difference is a typecast: UnicodeString(p^) built a CALL whose callee was an IDENTIFIER, which cannot be told apart from a call to a routine of that name, while AnsiString(p^) and WideString(p^) build a TYPE callee. Now all three do. Co-Authored-By: Claude Opus 5.5 --- Source/SimpleParser/SimpleParser.Lexer.pas | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/SimpleParser/SimpleParser.Lexer.pas b/Source/SimpleParser/SimpleParser.Lexer.pas index 2257785..bc01580 100644 --- a/Source/SimpleParser/SimpleParser.Lexer.pas +++ b/Source/SimpleParser/SimpleParser.Lexer.pas @@ -574,6 +574,7 @@ procedure TmwBasePasLex.InitIdent; 141: FIdentFuncTable[I] := Func141; 142: FIdentFuncTable[I] := Func142; 143: FIdentFuncTable[I] := Func143; + 158: FIdentFuncTable[I] := Func158; 166: FIdentFuncTable[I] := Func166; 167: FIdentFuncTable[I] := Func167; 168: FIdentFuncTable[I] := Func168; From 710dc245a2d04e9ccba4e41009a906e27093f1de Mon Sep 17 00:00:00 2001 From: Partouf Date: Thu, 8 Oct 2026 18:17:42 +0200 Subject: [PATCH 2/2] Test that a UnicodeString typecast has a type callee AST.UnicodeStringTypecast parses `s := UnicodeString(p^)` and checks that the CALL's callee is an ntType named UnicodeString. It fails without the Func158 registration ("A UnicodeString typecast has a type as its callee.") and passes with it. Co-Authored-By: Claude Opus 5.5 --- Test/UnitTests/DelphiAST.Tests.pas | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Test/UnitTests/DelphiAST.Tests.pas b/Test/UnitTests/DelphiAST.Tests.pas index 9053210..b69a872 100644 --- a/Test/UnitTests/DelphiAST.Tests.pas +++ b/Test/UnitTests/DelphiAST.Tests.pas @@ -300,6 +300,23 @@ procedure TestRepeatedCallingConvention; end; end; +procedure TestUnicodeStringTypecast; +var + Root, CallNode, Callee: TSyntaxNode; +begin + Root := ParseSource('unit Example; interface implementation ' + + 'procedure Run(p: Pointer); var s: UnicodeString; begin s := UnicodeString(p^); end; end.'); + try + CallNode := FindDescendant(Root, ntCall); + AssertNotNil(CallNode, 'Missing call'); + Callee := CallNode.ChildNodes[0]; + AssertTrue(Callee.Typ = ntType, 'A UnicodeString typecast has a type as its callee.'); + AssertEquals('UnicodeString', Callee.GetAttribute(anName), 'Typecast type name.'); + finally + Root.Free; + end; +end; + procedure TestInvalidSyntax; var Root: TSyntaxNode; @@ -379,6 +396,7 @@ procedure RunAllTests; RunTest('Node.AttributeOverwrite', TestAttributeOverwrite); RunTest('Node.AttributeRemove', TestAttributeRemove); RunTest('AST.RepeatedCallingConvention', TestRepeatedCallingConvention); + RunTest('AST.UnicodeStringTypecast', TestUnicodeStringTypecast); RunTest('Parser.InvalidSyntax', TestInvalidSyntax); RunTest('Parser.UnexpectedEndOfFilePosition', TestUnexpectedEndOfFilePosition); {$IFNDEF FPC}