Skip to content

Commit bd1fae3

Browse files
Andrin Meierretailcoder
authored andcommitted
Literal Expression Fix (#1628)
* fix literalexpression classified as simplenameexpression * add clarifying comment
1 parent 03c57d4 commit bd1fae3

File tree

11 files changed

+4563
-4600
lines changed

11 files changed

+4563
-4600
lines changed

Rubberduck.Parsing/Grammar/VBALexer.cs

Lines changed: 686 additions & 686 deletions
Large diffs are not rendered by default.

Rubberduck.Parsing/Grammar/VBALexer.g4

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ NEW : N E W;
159159
NOT : N O T;
160160
NOTHING : N O T H I N G;
161161
NULL : N U L L;
162+
OBJECT: O B J E C T;
162163
ON : O N;
163164
ON_ERROR : O N WS E R R O R;
164165
ON_LOCAL_ERROR : O N WS L O C A L WS E R R O R;
@@ -297,7 +298,7 @@ SINGLEQUOTE : '\'';
297298
UNDERSCORE : '_';
298299
WS : [ \t];
299300
GUIDLITERAL : '{' [0-9A-F]+ '-' [0-9A-F]+ '-' [0-9A-F]+ '-' [0-9A-F]+ '-' [0-9A-F]+ '}';
300-
IDENTIFIER : ~[\[\]\(\)\r\n\t.,'"|!@#$%^&*\-+:=; 0-9-/\\] ~[\[\]\(\)\r\n\t.,'"|!@#$%^&*\-+:=; ]* | L_SQUARE_BRACKET ~[\r\n\u2028\u2029]* R_SQUARE_BRACKET;
301+
IDENTIFIER : ~[\[\]\(\)\r\n\t.,'"|!@#$%^&*\-+:=; 0-9-/\\] ~[\[\]\(\)\r\n\t.,'"|!@#$%^&*\-+:=; ]*;
301302
LINE_CONTINUATION : [ \t]* UNDERSCORE [ \t]* '\r'? '\n';
302303
fragment LETTER : [a-zA-Z_äöüÄÖÜ];
303304
fragment DIGIT : [0-9];

Rubberduck.Parsing/Grammar/VBAParser.cs

Lines changed: 3685 additions & 3726 deletions
Large diffs are not rendered by default.

Rubberduck.Parsing/Grammar/VBAParser.g4

Lines changed: 87 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,92 @@ typeHint : PERCENT | AMPERSAND | POW | EXCLAMATIONPOINT | HASH | AT | DOLLAR;
518518

519519
visibility : PRIVATE | PUBLIC | FRIEND | GLOBAL;
520520

521+
// 5.6 Expressions
522+
expression :
523+
// Literal Expression has to come before lExpression, otherwise it'll be classified as simple name expression instead.
524+
literalExpression # literalExpr
525+
| lExpression # lExpr
526+
| builtInType # builtInTypeExpr
527+
| LPAREN whiteSpace? expression whiteSpace? RPAREN # parenthesizedExpr
528+
| TYPEOF whiteSpace expression # typeofexpr // To make the grammar SLL, the type-of-is-expression is actually the child of an IS relational op.
529+
| NEW whiteSpace expression # newExpr
530+
| expression whiteSpace? POW whiteSpace? expression # powOp
531+
| MINUS whiteSpace? expression # unaryMinusOp
532+
| expression whiteSpace? (MULT | DIV) whiteSpace? expression # multOp
533+
| expression whiteSpace? INTDIV whiteSpace? expression # intDivOp
534+
| expression whiteSpace? MOD whiteSpace? expression # modOp
535+
| expression whiteSpace? (PLUS | MINUS) whiteSpace? expression # addOp
536+
| expression whiteSpace? AMPERSAND whiteSpace? expression # concatOp
537+
| expression whiteSpace? (EQ | NEQ | LT | GT | LEQ | GEQ | LIKE | IS) whiteSpace? expression # relationalOp
538+
| NOT whiteSpace? expression # logicalNotOp
539+
| expression whiteSpace? AND whiteSpace? expression # logicalAndOp
540+
| expression whiteSpace? OR whiteSpace? expression # logicalOrOp
541+
| expression whiteSpace? XOR whiteSpace? expression # logicalXorOp
542+
| expression whiteSpace? EQV whiteSpace? expression # logicalEqvOp
543+
| expression whiteSpace? IMP whiteSpace? expression # logicalImpOp
544+
| HASH expression # markedFileNumberExpr // Added to support special forms such as Input(file1, #file1)
545+
;
546+
547+
// 5.6.5 Literal Expressions
548+
literalExpression :
549+
numberLiteral
550+
| DATELITERAL
551+
| STRINGLITERAL
552+
| literalIdentifier typeHint?
553+
;
554+
555+
literalIdentifier : booleanLiteralIdentifier | objectLiteralIdentifier | variantLiteralIdentifier;
556+
booleanLiteralIdentifier : TRUE | FALSE;
557+
objectLiteralIdentifier : NOTHING;
558+
variantLiteralIdentifier : EMPTY | NULL;
559+
560+
lExpression :
561+
lExpression whiteSpace? LPAREN whiteSpace? argumentList? whiteSpace? RPAREN # indexExpr
562+
| lExpression DOT unrestrictedIdentifier # memberAccessExpr
563+
| lExpression LINE_CONTINUATION whiteSpace? DOT unrestrictedIdentifier # memberAccessExpr
564+
| lExpression EXCLAMATIONPOINT unrestrictedIdentifier # dictionaryAccessExpr
565+
| lExpression LINE_CONTINUATION EXCLAMATIONPOINT unrestrictedIdentifier # dictionaryAccessExpr
566+
| lExpression LINE_CONTINUATION EXCLAMATIONPOINT LINE_CONTINUATION unrestrictedIdentifier # dictionaryAccessExpr
567+
| ME # instanceExpr
568+
| identifier # simpleNameExpr
569+
| DOT unrestrictedIdentifier # withMemberAccessExpr
570+
| EXCLAMATIONPOINT unrestrictedIdentifier # withDictionaryAccessExpr
571+
;
572+
573+
// 3.3.5.3 Special Identifier Forms
574+
builtInType :
575+
baseType
576+
| L_SQUARE_BRACKET whiteSpace? baseType whiteSpace? R_SQUARE_BRACKET
577+
| OBJECT
578+
| L_SQUARE_BRACKET whiteSpace? OBJECT whiteSpace? R_SQUARE_BRACKET
579+
;
580+
581+
// 5.6.13.1 Argument Lists
582+
argumentList : positionalOrNamedArgumentList;
583+
positionalOrNamedArgumentList :
584+
(positionalArgumentOrMissing whiteSpace?)* requiredPositionalArgument
585+
| (positionalArgumentOrMissing whiteSpace?)* namedArgumentList
586+
;
587+
positionalArgumentOrMissing :
588+
positionalArgument whiteSpace? COMMA # specifiedPositionalArgument
589+
| whiteSpace? COMMA # missingPositionalArgument
590+
;
591+
positionalArgument : argumentExpression;
592+
requiredPositionalArgument : argumentExpression;
593+
namedArgumentList : namedArgument (whiteSpace? COMMA whiteSpace? namedArgument)*;
594+
namedArgument : unrestrictedIdentifier whiteSpace? ASSIGN whiteSpace? argumentExpression;
595+
argumentExpression :
596+
(BYVAL whiteSpace)? expression
597+
| addressOfExpression
598+
// Special case for redim statements. The resolver doesn't have to deal with this because it is "picked apart" in the redim statement.
599+
| lowerBoundArgumentExpression whiteSpace TO whiteSpace upperBoundArgumentExpression
600+
;
601+
lowerBoundArgumentExpression : expression;
602+
upperBoundArgumentExpression : expression;
603+
604+
// 5.6.16.8 AddressOf Expressions
605+
addressOfExpression : ADDRESSOF whiteSpace expression;
606+
521607
keyword :
522608
ABS
523609
| ADDRESSOF
@@ -542,7 +628,6 @@ keyword :
542628
| CLNG
543629
| CLNGLNG
544630
| CLNGPTR
545-
| COLLECTION
546631
| CSNG
547632
| CSTR
548633
| CURRENCY
@@ -551,7 +636,6 @@ keyword :
551636
| DATABASE
552637
| DATE
553638
| DEBUG
554-
| DELETESETTING
555639
| DOEVENTS
556640
| DOUBLE
557641
| END
@@ -592,9 +676,6 @@ keyword :
592676
| PSET
593677
| PTRSAFE
594678
| REM
595-
| RMDIR
596-
| SENDKEYS
597-
| SETATTR
598679
| SGN
599680
| SINGLE
600681
| SPC
@@ -738,92 +819,4 @@ annotationArgList :
738819
| whiteSpace? LPAREN annotationArg (whiteSpace? COMMA whiteSpace? annotationArg)+ whiteSpace? RPAREN;
739820
annotationArg : expression;
740821

741-
whiteSpace : (WS | LINE_CONTINUATION)+;
742-
743-
744-
745-
746-
// 5.6 Expressions
747-
expression :
748-
lExpression # lExpr
749-
| builtInType # builtInTypeExpr
750-
| LPAREN whiteSpace? expression whiteSpace? RPAREN # parenthesizedExpr
751-
| TYPEOF whiteSpace expression # typeofexpr // To make the grammar SLL, the type-of-is-expression is actually the child of an IS relational op.
752-
| NEW whiteSpace expression # newExpr
753-
| expression whiteSpace? POW whiteSpace? expression # powOp
754-
| MINUS whiteSpace? expression # unaryMinusOp
755-
| expression whiteSpace? (MULT | DIV) whiteSpace? expression # multOp
756-
| expression whiteSpace? INTDIV whiteSpace? expression # intDivOp
757-
| expression whiteSpace? MOD whiteSpace? expression # modOp
758-
| expression whiteSpace? (PLUS | MINUS) whiteSpace? expression # addOp
759-
| expression whiteSpace? AMPERSAND whiteSpace? expression # concatOp
760-
| expression whiteSpace? (EQ | NEQ | LT | GT | LEQ | GEQ | LIKE | IS) whiteSpace? expression # relationalOp
761-
| NOT whiteSpace? expression # logicalNotOp
762-
| expression whiteSpace? AND whiteSpace? expression # logicalAndOp
763-
| expression whiteSpace? OR whiteSpace? expression # logicalOrOp
764-
| expression whiteSpace? XOR whiteSpace? expression # logicalXorOp
765-
| expression whiteSpace? EQV whiteSpace? expression # logicalEqvOp
766-
| expression whiteSpace? IMP whiteSpace? expression # logicalImpOp
767-
| literalExpression # literalExpr
768-
| HASH expression # markedFileNumberExpr // Added to support special forms such as Input(file1, #file1)
769-
;
770-
771-
// 5.6.5 Literal Expressions
772-
literalExpression :
773-
numberLiteral
774-
| DATELITERAL
775-
| STRINGLITERAL
776-
| literalIdentifier typeHint?
777-
;
778-
779-
literalIdentifier : booleanLiteralIdentifier | objectLiteralIdentifier | variantLiteralIdentifier;
780-
booleanLiteralIdentifier : TRUE | FALSE;
781-
objectLiteralIdentifier : NOTHING;
782-
variantLiteralIdentifier : EMPTY | NULL;
783-
784-
lExpression :
785-
lExpression whiteSpace? LPAREN whiteSpace? argumentList? whiteSpace? RPAREN # indexExpr
786-
| lExpression DOT unrestrictedIdentifier # memberAccessExpr
787-
| lExpression LINE_CONTINUATION whiteSpace? DOT unrestrictedIdentifier # memberAccessExpr
788-
| lExpression EXCLAMATIONPOINT unrestrictedIdentifier # dictionaryAccessExpr
789-
| lExpression LINE_CONTINUATION EXCLAMATIONPOINT unrestrictedIdentifier # dictionaryAccessExpr
790-
| lExpression LINE_CONTINUATION EXCLAMATIONPOINT LINE_CONTINUATION unrestrictedIdentifier # dictionaryAccessExpr
791-
| ME # instanceExpr
792-
| identifier # simpleNameExpr
793-
| DOT unrestrictedIdentifier # withMemberAccessExpr
794-
| EXCLAMATIONPOINT unrestrictedIdentifier # withDictionaryAccessExpr
795-
;
796-
797-
// 3.3.5.3 Special Identifier Forms
798-
builtInType :
799-
baseType
800-
| L_SQUARE_BRACKET whiteSpace? baseType whiteSpace? R_SQUARE_BRACKET
801-
| OBJECT
802-
| L_SQUARE_BRACKET whiteSpace? OBJECT whiteSpace? R_SQUARE_BRACKET
803-
;
804-
805-
// 5.6.13.1 Argument Lists
806-
argumentList : positionalOrNamedArgumentList;
807-
positionalOrNamedArgumentList :
808-
(positionalArgumentOrMissing whiteSpace?)* requiredPositionalArgument
809-
| (positionalArgumentOrMissing whiteSpace?)* namedArgumentList
810-
;
811-
positionalArgumentOrMissing :
812-
positionalArgument whiteSpace? COMMA # specifiedPositionalArgument
813-
| whiteSpace? COMMA # missingPositionalArgument
814-
;
815-
positionalArgument : argumentExpression;
816-
requiredPositionalArgument : argumentExpression;
817-
namedArgumentList : namedArgument (whiteSpace? COMMA whiteSpace? namedArgument)*;
818-
namedArgument : unrestrictedIdentifier whiteSpace? ASSIGN whiteSpace? argumentExpression;
819-
argumentExpression :
820-
(BYVAL whiteSpace)? expression
821-
| addressOfExpression
822-
// Special case for redim statements. The resolver doesn't have to deal with this because it is "picked apart" in the redim statement.
823-
| lowerBoundArgumentExpression whiteSpace TO whiteSpace upperBoundArgumentExpression
824-
;
825-
lowerBoundArgumentExpression : expression;
826-
upperBoundArgumentExpression : expression;
827-
828-
// 5.6.16.8 AddressOf Expressions
829-
addressOfExpression : ADDRESSOF whiteSpace expression;
822+
whiteSpace : (WS | LINE_CONTINUATION)+;

Rubberduck.Parsing/Grammar/VBAParserBaseListener.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -905,30 +905,30 @@ public virtual void EnterCircleSpecialForm([NotNull] VBAParser.CircleSpecialForm
905905
public virtual void ExitCircleSpecialForm([NotNull] VBAParser.CircleSpecialFormContext context) { }
906906

907907
/// <summary>
908-
/// Enter a parse tree produced by <see cref="VBAParser.statementKeyword"/>.
908+
/// Enter a parse tree produced by <see cref="VBAParser.lExpr"/>.
909909
/// <para>The default implementation does nothing.</para>
910910
/// </summary>
911911
/// <param name="context">The parse tree.</param>
912-
public virtual void EnterStatementKeyword([NotNull] VBAParser.StatementKeywordContext context) { }
912+
public virtual void EnterLExpr([NotNull] VBAParser.LExprContext context) { }
913913
/// <summary>
914-
/// Exit a parse tree produced by <see cref="VBAParser.statementKeyword"/>.
914+
/// Exit a parse tree produced by <see cref="VBAParser.lExpr"/>.
915915
/// <para>The default implementation does nothing.</para>
916916
/// </summary>
917917
/// <param name="context">The parse tree.</param>
918-
public virtual void ExitStatementKeyword([NotNull] VBAParser.StatementKeywordContext context) { }
918+
public virtual void ExitLExpr([NotNull] VBAParser.LExprContext context) { }
919919

920920
/// <summary>
921-
/// Enter a parse tree produced by <see cref="VBAParser.lExpr"/>.
921+
/// Enter a parse tree produced by <see cref="VBAParser.statementKeyword"/>.
922922
/// <para>The default implementation does nothing.</para>
923923
/// </summary>
924924
/// <param name="context">The parse tree.</param>
925-
public virtual void EnterLExpr([NotNull] VBAParser.LExprContext context) { }
925+
public virtual void EnterStatementKeyword([NotNull] VBAParser.StatementKeywordContext context) { }
926926
/// <summary>
927-
/// Exit a parse tree produced by <see cref="VBAParser.lExpr"/>.
927+
/// Exit a parse tree produced by <see cref="VBAParser.statementKeyword"/>.
928928
/// <para>The default implementation does nothing.</para>
929929
/// </summary>
930930
/// <param name="context">The parse tree.</param>
931-
public virtual void ExitLExpr([NotNull] VBAParser.LExprContext context) { }
931+
public virtual void ExitStatementKeyword([NotNull] VBAParser.StatementKeywordContext context) { }
932932

933933
/// <summary>
934934
/// Enter a parse tree produced by <see cref="VBAParser.logicalAndOp"/>.

Rubberduck.Parsing/Grammar/VBAParserBaseVisitor.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -770,26 +770,26 @@ public partial class VBAParserBaseVisitor<Result> : AbstractParseTreeVisitor<Res
770770
public virtual Result VisitCircleSpecialForm([NotNull] VBAParser.CircleSpecialFormContext context) { return VisitChildren(context); }
771771

772772
/// <summary>
773-
/// Visit a parse tree produced by <see cref="VBAParser.statementKeyword"/>.
773+
/// Visit a parse tree produced by <see cref="VBAParser.lExpr"/>.
774774
/// <para>
775775
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
776776
/// on <paramref name="context"/>.
777777
/// </para>
778778
/// </summary>
779779
/// <param name="context">The parse tree.</param>
780780
/// <return>The visitor result.</return>
781-
public virtual Result VisitStatementKeyword([NotNull] VBAParser.StatementKeywordContext context) { return VisitChildren(context); }
781+
public virtual Result VisitLExpr([NotNull] VBAParser.LExprContext context) { return VisitChildren(context); }
782782

783783
/// <summary>
784-
/// Visit a parse tree produced by <see cref="VBAParser.lExpr"/>.
784+
/// Visit a parse tree produced by <see cref="VBAParser.statementKeyword"/>.
785785
/// <para>
786786
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
787787
/// on <paramref name="context"/>.
788788
/// </para>
789789
/// </summary>
790790
/// <param name="context">The parse tree.</param>
791791
/// <return>The visitor result.</return>
792-
public virtual Result VisitLExpr([NotNull] VBAParser.LExprContext context) { return VisitChildren(context); }
792+
public virtual Result VisitStatementKeyword([NotNull] VBAParser.StatementKeywordContext context) { return VisitChildren(context); }
793793

794794
/// <summary>
795795
/// Visit a parse tree produced by <see cref="VBAParser.logicalAndOp"/>.

Rubberduck.Parsing/Grammar/VBAParserListener.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -793,28 +793,28 @@ public interface IVBAParserListener : IParseTreeListener {
793793
void ExitCircleSpecialForm([NotNull] VBAParser.CircleSpecialFormContext context);
794794

795795
/// <summary>
796-
/// Enter a parse tree produced by <see cref="VBAParser.statementKeyword"/>.
796+
/// Enter a parse tree produced by the <c>lExpr</c>
797+
/// labeled alternative in <see cref="VBAParser.expression"/>.
797798
/// </summary>
798799
/// <param name="context">The parse tree.</param>
799-
void EnterStatementKeyword([NotNull] VBAParser.StatementKeywordContext context);
800+
void EnterLExpr([NotNull] VBAParser.LExprContext context);
800801
/// <summary>
801-
/// Exit a parse tree produced by <see cref="VBAParser.statementKeyword"/>.
802+
/// Exit a parse tree produced by the <c>lExpr</c>
803+
/// labeled alternative in <see cref="VBAParser.expression"/>.
802804
/// </summary>
803805
/// <param name="context">The parse tree.</param>
804-
void ExitStatementKeyword([NotNull] VBAParser.StatementKeywordContext context);
806+
void ExitLExpr([NotNull] VBAParser.LExprContext context);
805807

806808
/// <summary>
807-
/// Enter a parse tree produced by the <c>lExpr</c>
808-
/// labeled alternative in <see cref="VBAParser.expression"/>.
809+
/// Enter a parse tree produced by <see cref="VBAParser.statementKeyword"/>.
809810
/// </summary>
810811
/// <param name="context">The parse tree.</param>
811-
void EnterLExpr([NotNull] VBAParser.LExprContext context);
812+
void EnterStatementKeyword([NotNull] VBAParser.StatementKeywordContext context);
812813
/// <summary>
813-
/// Exit a parse tree produced by the <c>lExpr</c>
814-
/// labeled alternative in <see cref="VBAParser.expression"/>.
814+
/// Exit a parse tree produced by <see cref="VBAParser.statementKeyword"/>.
815815
/// </summary>
816816
/// <param name="context">The parse tree.</param>
817-
void ExitLExpr([NotNull] VBAParser.LExprContext context);
817+
void ExitStatementKeyword([NotNull] VBAParser.StatementKeywordContext context);
818818

819819
/// <summary>
820820
/// Enter a parse tree produced by the <c>logicalAndOp</c>

Rubberduck.Parsing/Grammar/VBAParserVisitor.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -513,19 +513,19 @@ public interface IVBAParserVisitor<Result> : IParseTreeVisitor<Result> {
513513
Result VisitCircleSpecialForm([NotNull] VBAParser.CircleSpecialFormContext context);
514514

515515
/// <summary>
516-
/// Visit a parse tree produced by <see cref="VBAParser.statementKeyword"/>.
516+
/// Visit a parse tree produced by the <c>lExpr</c>
517+
/// labeled alternative in <see cref="VBAParser.expression"/>.
517518
/// </summary>
518519
/// <param name="context">The parse tree.</param>
519520
/// <return>The visitor result.</return>
520-
Result VisitStatementKeyword([NotNull] VBAParser.StatementKeywordContext context);
521+
Result VisitLExpr([NotNull] VBAParser.LExprContext context);
521522

522523
/// <summary>
523-
/// Visit a parse tree produced by the <c>lExpr</c>
524-
/// labeled alternative in <see cref="VBAParser.expression"/>.
524+
/// Visit a parse tree produced by <see cref="VBAParser.statementKeyword"/>.
525525
/// </summary>
526526
/// <param name="context">The parse tree.</param>
527527
/// <return>The visitor result.</return>
528-
Result VisitLExpr([NotNull] VBAParser.LExprContext context);
528+
Result VisitStatementKeyword([NotNull] VBAParser.StatementKeywordContext context);
529529

530530
/// <summary>
531531
/// Visit a parse tree produced by the <c>logicalAndOp</c>

0 commit comments

Comments
 (0)