Я пытаюсь разобрать VBA код, и 5.4.2.10 раздел спецификации определяет Select Case
заявление, которое мы определили следующим образом:Как правильно разобрать оператор VB Case?
// 5.4.2.10 Select Case Statement
selectCaseStmt :
SELECT whiteSpace? CASE whiteSpace? selectExpression endOfStatement
caseClause*
caseElseClause?
END_SELECT
;
selectExpression : expression;
caseClause :
CASE whiteSpace rangeClause (whiteSpace? COMMA whiteSpace? rangeClause)* endOfStatement block
;
caseElseClause : CASE whiteSpace? ELSE endOfStatement block;
rangeClause :
expression
| selectStartValue whiteSpace TO whiteSpace selectEndValue
| (IS whiteSpace?)? comparisonOperator whiteSpace? expression
;
selectStartValue : expression;
selectEndValue : expression;
Проблема заключается в том, что expression
в rangeClause
принимает старшинство, и делает это:
Select Case foo Case Is = 42 Exit Sub End Select
... в конечном итоге получить подхвачена и рассматривается как {undeclared-variable} {EQ} {literal}
, что является проблемой, потому что Is
должен быть знаком лексическим, не LHS из выражения сравнения:
expression whiteSpace? (EQ | NEQ | LT | GT | LEQ | GEQ | LIKE | IS) whiteSpace? expression # relationalOp
Я попытался переназначением альтернативы, так что expression
ветви имеет более низкий приоритет, как это:
rangeClause :
selectStartValue whiteSpace TO whiteSpace selectEndValue
| (IS whiteSpace?)? comparisonOperator whiteSpace? expression
| expression
;
Но что сломало (разрывает ~ 1000 тестов в моем проекте), поэтому вместо этого я попытался изменить rangeClause
на это (удаленные необязательные токены, потому что Is
без =
фактически является незаконным кодом VBA):
rangeClause :
expression (whiteSpace TO whiteSpace expression)? #caseFromTo
| (IS whiteSpace comparisonOperator whiteSpace)? expression #caseIs
;
И затем работает с CaseFromToContext
и CaseIsContext
классами в коде (должен был, чтобы он компилировался), но снова он сломал ~ 1000 тестов в моем проекте.
Тогда я подумал: «Эй, это потенциально двусмысленно!» и превратили его в это:
rangeClause :
expression whiteSpace TO whiteSpace expression #caseFromTo
| IS whiteSpace comparisonOperator whiteSpace expression #caseIs
| expression #caseExpr
;
... но не повезло, то же идентичное исходы.
Как это сделать rangeClause
понять это раздражающее синтаксис Case Is = foobar
? Я использую ANTLR 4.3, но мы планируем перейти на ANTLR 4.6 в ближайшее время.
Если необходим дополнительный контекст, the complete VBAParser.g4 grammar is on github.