解析 – 如何正确解析VB Case语句?
我正在尝试解析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中的表达式优先,并使得:
…最终被选中并被视为{undeclared-variable} {EQ} {literal},这是一个问题,因为它应该是词法分析器,而不是比较表达式的LHS: expression whiteSpace? (EQ | NEQ | LT | GT | LEQ | GEQ | LIKE | IS) whiteSpace? expression # relationalOp 我尝试重新排序替代方案,以便表达式分支具有较低的优先级,如下所示: rangeClause : selectStartValue whiteSpace TO whiteSpace selectEndValue | (IS whiteSpace?)? comparisonOperator whiteSpace? expression | expression ; 但是这打破了整个语法的各种方式(在我的项目中打破了~1000次测试),所以我尝试将rangeClause更改为此(删除了可选的标记,因为Is without =实际上是非法的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. 解决方法
事实证明重新排序确实有效,但为了避免歧义,IS whiteSpace comparisonOperator必须首先出现:
rangeClause : (IS whiteSpace?)? comparisonOperator whiteSpace? expression | selectStartValue whiteSpace TO whiteSpace selectEndValue | expression 问题在于表达式(以及扩展名selectStartValue和selectEndValue)将递归匹配Is =,因为comparisonOperator comparisonOperator是表达式匹配.可能有一些工作可以阻止comparisonOperator comparisonOperator与匹配表达式(它在VBA AFAIK中永远不会有效),但上面的工作是一个快速而肮脏的修复. 基本上所有上述语法都确保“invalid”compareOperator comparisonOperator在作为表达式匹配之前匹配为rangeClause. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |