如何正确解析 VB 案例语句?



我正在尝试解析 VBA 代码,规范的 5.4.2.10 部分定义了Select 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},这是一个问题,因为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
;

然后在代码中使用CaseFromToContextCaseIsContext类(必须这样做,以保持编译),但它再次破坏了我项目中的~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。

如果需要额外的上下文,完整的VBAParser.g4语法在github上。

事实证明,重新排序确实有效,但为了防止解析中的歧义,IS whiteSpace comparisonOperator必须排在第一位:

rangeClause :
(IS whiteSpace?)? comparisonOperator whiteSpace? expression
| selectStartValue whiteSpace TO whiteSpace selectEndValue 
| expression

问题在于expression(以及扩展selectStartValueselectEndValue),它将递归匹配Is =comparisonOperator comparisonOperator因为是表达式匹配。 可能有一些工作可以做来防止comparisonOperator comparisonOperator匹配expression(它在 VBA AFAIK 中永远不会有效),但上述方法可以作为快速而肮脏的修复。

基本上上述语法所做的只是确保"无效"comparisonOperator comparisonOperator作为rangeClause匹配,然后才能匹配为expression

相关内容

  • 没有找到相关文章

最新更新