|
19 | 19 |
|
20 | 20 | parser grammar VBAParser;
|
21 | 21 |
|
22 |
| -options { tokenVocab = VBALexer; } |
23 |
| - |
24 |
| -@header { using System.Text.RegularExpressions; } |
| 22 | +options { |
| 23 | + tokenVocab = VBALexer; |
| 24 | + superClass = VBABaseParser; |
| 25 | + } |
25 | 26 |
|
26 | 27 | startRule : module EOF;
|
27 | 28 |
|
@@ -321,14 +322,14 @@ defType :
|
321 | 322 | // singleLetter must appear at the end to prevent premature bailout
|
322 | 323 | letterSpec : universalLetterRange | letterRange | singleLetter;
|
323 | 324 |
|
324 |
| -singleLetter : {_input.Lt(1).Text.Length == 1 && Regex.Match(_input.Lt(1).Text, @"[a-zA-Z]").Success}? IDENTIFIER; |
| 325 | +singleLetter : {MatchesRegex(Text(LT(1)),"^[a-zA-Z]$")}? IDENTIFIER; |
325 | 326 |
|
326 | 327 | // We make a separate universalLetterRange rule because it is treated specially in VBA. This makes it easy for users of the parser
|
327 | 328 | // to identify this case. Quoting MS VBAL:
|
328 | 329 | // "A <universal-letter-range> defines a single implicit declared type for every <IDENTIFIER> within
|
329 | 330 | // a module, even those with a first character that would otherwise fall outside this range if it was
|
330 | 331 | // interpreted as a <letter-range> from A-Z.""
|
331 |
| -universalLetterRange : {_input.Lt(1).Text.Equals("A") && _input.Lt(3).Text.Equals("Z")}? IDENTIFIER MINUS IDENTIFIER; |
| 332 | +universalLetterRange : {EqualsString(Text(LT(1)),"A") && EqualsString(Text(LT(3)),"Z")}? IDENTIFIER MINUS IDENTIFIER; |
332 | 333 |
|
333 | 334 | letterRange : singleLetter MINUS singleLetter;
|
334 | 335 |
|
@@ -571,22 +572,22 @@ circleSpecialForm : (expression whiteSpace? DOT whiteSpace?)? CIRCLE whiteSpace
|
571 | 572 | scaleSpecialForm : (expression whiteSpace? DOT whiteSpace?)? SCALE whiteSpace tuple whiteSpace? MINUS whiteSpace? tuple;
|
572 | 573 | pSetSpecialForm : (expression whiteSpace? DOT whiteSpace?)? PSET (whiteSpace STEP)? whiteSpace? tuple whiteSpace? (COMMA whiteSpace? expression)?;
|
573 | 574 | tuple : LPAREN whiteSpace? expression whiteSpace? COMMA whiteSpace? expression whiteSpace? RPAREN;
|
574 |
| -lineSpecialFormOption : {_input.Lt(1).Text.ToLower().Equals("b") || _input.Lt(1).Text.ToLower().Equals("bf")}? unrestrictedIdentifier; |
| 575 | +lineSpecialFormOption : {EqualsStringIgnoringCase(Text(LT(1)),"b","bf")}? unrestrictedIdentifier; |
575 | 576 |
|
576 | 577 | subscripts : subscript (whiteSpace? COMMA whiteSpace? subscript)*;
|
577 | 578 |
|
578 | 579 | subscript : (expression whiteSpace TO whiteSpace)? expression;
|
579 | 580 |
|
580 | 581 | unrestrictedIdentifier : identifier | statementKeyword | markerKeyword;
|
581 |
| -legalLabelIdentifier : { !(new[]{DOEVENTS,END,CLOSE,ELSE,LOOP,NEXT,RANDOMIZE,REM,RESUME,RETURN,STOP,WEND}).Contains(_input.La(1))}? identifier | markerKeyword; |
| 582 | +legalLabelIdentifier : { !IsTokenType(LA(1),DOEVENTS,END,CLOSE,ELSE,LOOP,NEXT,RANDOMIZE,REM,RESUME,RETURN,STOP,WEND)}? identifier | markerKeyword; |
582 | 583 | //The predicate in the following rule has been introduced to lessen the problem that VBA uses the same characters used as type hints in other syntactical constructs,
|
583 | 584 | //e.g. in the bang notation (see withDictionaryAccessExpr). Generally, it is not legal to have an identifier or opening bracket follow immediately after a type hint.
|
584 | 585 | //The first part of the predicate tries to exclude these two situations. Unfortunately, predicates have to be at the start of a rule. So, an assumption about the number
|
585 | 586 | //of tokens in the identifier is made. All untypedIdentifers not a foreignNames consist of exactly one token and a typedIdentifier is an untyped one followed by a typeHint,
|
586 | 587 | //again a single token. So, in the majority of situations, the third token is the token following the potential type hint.
|
587 | 588 | //For foreignNames, no assumption can be made because they consist of a pair of brackets containing arbitrarily many tokens.
|
588 | 589 | //That is why the second part of the predicate looks at the first character in order to determine whether the identifier is a foreignName.
|
589 |
| -identifier : {_input.La(3) != IDENTIFIER && _input.La(3) != L_SQUARE_BRACKET || _input.La(1) == L_SQUARE_BRACKET}? typedIdentifier |
| 590 | +identifier : {!IsTokenType(LA(3),IDENTIFIER,L_SQUARE_BRACKET) || IsTokenType(LA(1),L_SQUARE_BRACKET)}? typedIdentifier |
590 | 591 | | untypedIdentifier;
|
591 | 592 | untypedIdentifier : identifierValue;
|
592 | 593 | typedIdentifier : untypedIdentifier typeHint;
|
@@ -614,7 +615,7 @@ complexType :
|
614 | 615 | fieldLength : MULT whiteSpace? (numberLiteral | identifierValue);
|
615 | 616 |
|
616 | 617 | //Statement labels can only appear at the start of a line.
|
617 |
| -statementLabelDefinition : {_input.La(-1) == NEWLINE || _input.La(-1) == LINE_CONTINUATION}? (combinedLabels | identifierStatementLabel | standaloneLineNumberLabel); |
| 618 | +statementLabelDefinition : {IsTokenType(LA(-1),NEWLINE,LINE_CONTINUATION)}? (combinedLabels | identifierStatementLabel | standaloneLineNumberLabel); |
618 | 619 | identifierStatementLabel : legalLabelIdentifier whiteSpace? COLON;
|
619 | 620 | standaloneLineNumberLabel :
|
620 | 621 | lineNumberLabel whiteSpace? COLON
|
|
0 commit comments