From dd36747a111c77002a59678dcf0ad48f3239ca25 Mon Sep 17 00:00:00 2001 From: Jonah Jeleniewski Date: Fri, 15 Nov 2024 11:46:05 +1100 Subject: [PATCH] Fix parsing errors on some semicolon-delimited generic type parameters Specifically, in routine implementation headers. Previously, only comma-delimited type parameters were parsing correctly. --- CHANGELOG.md | 1 + .../au/com/integradev/delphi/antlr/Delphi.g | 15 +++++++++++++-- .../integradev/delphi/antlr/GrammarTest.java | 5 +++++ .../SemicolonSeparatedGenericArguments.pas | 17 +++++++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 delphi-frontend/src/test/resources/au/com/integradev/delphi/grammar/SemicolonSeparatedGenericArguments.pas diff --git a/CHANGELOG.md b/CHANGELOG.md index dcdc51d5c..514b2f0b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Parsing errors on semicolon-delimited generic type parameters in routine implementation headers. - Incorrect return types for `Length`, `High`, and `Low` on open/dynamic arrays depending on the compiler version and toolchain. - Name resolution failures on explicit references to default array properties with overloads on diff --git a/delphi-frontend/src/main/antlr3/au/com/integradev/delphi/antlr/Delphi.g b/delphi-frontend/src/main/antlr3/au/com/integradev/delphi/antlr/Delphi.g index b0d078dac..510565e6c 100644 --- a/delphi-frontend/src/main/antlr3/au/com/integradev/delphi/antlr/Delphi.g +++ b/delphi-frontend/src/main/antlr3/au/com/integradev/delphi/antlr/Delphi.g @@ -724,7 +724,12 @@ genericConstraint : typeReference | CONSTRUCTOR ; genericArguments : '<' typeReferenceOrStringOrFile (',' typeReferenceOrStringOrFile)* '>' - -> ^(TkGenericArguments typeReferenceOrStringOrFile typeReferenceOrStringOrFile*) + -> ^(TkGenericArguments '<' typeReferenceOrStringOrFile (',' typeReferenceOrStringOrFile)* '>') + ; +routineNameGenericArguments : '<' typeReferenceOrStringOrFile (commaOrSemicolon typeReferenceOrStringOrFile)* '>' + -> ^(TkGenericArguments '<' typeReferenceOrStringOrFile (commaOrSemicolon typeReferenceOrStringOrFile)* '>') + ; +commaOrSemicolon : ',' | ';' ; //---------------------------------------------------------------------------- @@ -810,7 +815,7 @@ routineDeclarationName : ( ) -> ^(TkRoutineName $decl) ; -routineImplementationName : nameReference -> ^(TkRoutineName nameReference) +routineImplementationName : routineNameReference -> ^(TkRoutineName routineNameReference) ; routineKey : PROCEDURE | CONSTRUCTOR @@ -1182,6 +1187,12 @@ simpleNameReference : ident extendedNameReference : extendedIdent genericArguments? ('.' extendedNameReference)? -> ^(TkNameReference extendedIdent genericArguments? ('.' extendedNameReference)?) ; +routineNameReference : ident routineNameGenericArguments? ('.' extendedRoutineNameReference)? + -> ^(TkNameReference ident routineNameGenericArguments? ('.' extendedRoutineNameReference)?) + ; +extendedRoutineNameReference : extendedIdent routineNameGenericArguments? ('.' extendedRoutineNameReference)? + -> ^(TkNameReference extendedIdent routineNameGenericArguments? ('.' extendedRoutineNameReference)?) + ; extendedIdent : ident | keywords -> ^({changeTokenType(TkIdentifier)}) ; diff --git a/delphi-frontend/src/test/java/au/com/integradev/delphi/antlr/GrammarTest.java b/delphi-frontend/src/test/java/au/com/integradev/delphi/antlr/GrammarTest.java index b55c6beb2..14bb8722f 100644 --- a/delphi-frontend/src/test/java/au/com/integradev/delphi/antlr/GrammarTest.java +++ b/delphi-frontend/src/test/java/au/com/integradev/delphi/antlr/GrammarTest.java @@ -348,4 +348,9 @@ void testImmediatelyTerminatedComments() { void testConditionalAsm() { assertParsed("ConditionalAsm.pas"); } + + @Test + void testSemicolonSeparatedGenericArguments() { + assertParsed("SemicolonSeparatedGenericArguments.pas"); + } } diff --git a/delphi-frontend/src/test/resources/au/com/integradev/delphi/grammar/SemicolonSeparatedGenericArguments.pas b/delphi-frontend/src/test/resources/au/com/integradev/delphi/grammar/SemicolonSeparatedGenericArguments.pas new file mode 100644 index 000000000..7c7815bf0 --- /dev/null +++ b/delphi-frontend/src/test/resources/au/com/integradev/delphi/grammar/SemicolonSeparatedGenericArguments.pas @@ -0,0 +1,17 @@ +unit SemicolonSeparatedGenericArguments; + +interface + +implementation + +type + TFoo = class + class procedure Bar; + end; + +class procedure TFoo.Bar; +begin + // ... +end; + +end. \ No newline at end of file