私は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;
問題がrangeClause
でexpression
を取っているということです
Select Case foo Case Is = 42 Exit Sub End Select
が...最終的に取り上げ、問題がある{undeclared-variable} {EQ} {literal}
、として扱われます 、理由:優先順位は、このなりますは、レクサーのトークンではなく、比較式の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
;
...ただし運がなく、同じ結果です。
をこの厄介な意味を理解できるようにするにはCase Is = foobar
構文を使用しますか?私はANTLR 4.3を使用していますが、ANTLR 4.6にすぐにアップグレードする予定です。
追加のコンテキストが必要な場合はthe complete VBAParser.g4 grammar is on githubです。