[英]How to correctly parse a VB Case statement?
我正在尝试解析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
;
但是这打破了整个语法的各种方式(在我的项目中打破了rangeClause
次测试),所以我尝试将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。
如果需要其他上下文, 则完整的VBAParser.g4语法在github上 。
事实证明重新排序确实有效,但为了避免歧义, IS whiteSpace comparisonOperator
必须首先出现:
rangeClause :
(IS whiteSpace?)? comparisonOperator whiteSpace? expression
| selectStartValue whiteSpace TO whiteSpace selectEndValue
| expression
问题在于expression
(以及扩展名selectStartValue
和selectEndValue
)将递归匹配Is =
因为comparisonOperator comparisonOperator
是表达式匹配。 可能有一些工作可以阻止 comparisonOperator comparisonOperator
与匹配expression
(它在VBA AFAIK中永远不会有效),但上面的工作是一个快速而肮脏的修复。
基本上所有上述语法不被确保了“无效” comparisonOperator comparisonOperator
作为匹配rangeClause
才可以作为一个匹配expression
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.