微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

解析 – 如何正确解析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中的表达式优先,并使得:

06001

…最终被选中并被视为{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.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐