如何在访问期间知道ANTLR解析器当前处于哪个替代规则

2023-12-02

如果我们查看 bash 源代码,特别是 yacc 语法,我们可以看到所有重定向都是这样定义的:

redirection
        :   GREATER WORD
        |   LESS WORD
        |   NUMBER GREATER WORD
        |   NUMBER LESS WORD
        |   REDIR_WORD GREATER WORD
        |   REDIR_WORD LESS WORD
        |   GREATER_GREATER WORD
        |   NUMBER GREATER_GREATER WORD
        |   REDIR_WORD GREATER_GREATER WORD
        |   GREATER_BAR WORD
        |   NUMBER GREATER_BAR WORD
        |   REDIR_WORD GREATER_BAR WORD
        |   LESS_GREATER WORD
        |   NUMBER LESS_GREATER WORD
        |   REDIR_WORD LESS_GREATER WORD
        |   LESS_LESS WORD
        |   NUMBER LESS_LESS WORD
        |   REDIR_WORD LESS_LESS WORD
        |   LESS_LESS_MINUS WORD
        |   NUMBER LESS_LESS_MINUS WORD
        |   REDIR_WORD  LESS_LESS_MINUS WORD
        |   LESS_LESS_LESS WORD
        |   NUMBER LESS_LESS_LESS WORD
        |   REDIR_WORD LESS_LESS_LESS WORD
        |   LESS_AND NUMBER
        |   NUMBER LESS_AND NUMBER
        |   REDIR_WORD LESS_AND NUMBER
        |   GREATER_AND NUMBER
        |   NUMBER GREATER_AND NUMBER
        |   REDIR_WORD GREATER_AND NUMBER
        |   LESS_AND WORD
        |   NUMBER LESS_AND WORD
        |   REDIR_WORD LESS_AND WORD
        |   GREATER_AND WORD
        |   NUMBER GREATER_AND WORD
        |   REDIR_WORD GREATER_AND WORD
        |   GREATER_AND DASH
        |   NUMBER GREATER_AND DASH
        |   REDIR_WORD GREATER_AND DASH
        |   LESS_AND DASH
        |   NUMBER LESS_AND DASH
        |   REDIR_WORD LESS_AND DASH
        |   AND_GREATER WORD
        |   AND_GREATER_GREATER WORD
        ;

在我的访客中,当visitRedirection被称为这感觉几乎不可能轻松地知道访问者当前处于哪个替代方案中。我可以使用标签每个替代方案#和标签,但仅仅为一个生产规则添加 43 个访问方法似乎有些过多。

通常我只会做一些null通过做检查ctx.GREATER() != null知道是否选择了第一个替代方案,但在这个例子中几乎总是有 2 个相互冲突的替代方案,例如:

GREATER WORD
NUMBER GREATER WORD

所以我应该这样做ctx.NUMBER() != null && ctx.GREATER() != null匹配第二个选择并且ctx.NUMBER() == null && ctx.GREATER() != null匹配第一个?

是否有更简单或更干净的方法来了解访问者当前处于哪种特定选择?


重组你的语法以减少选择。其中许多都有共同的前导或尾随部分,例如:

redirection
        :   GREATER WORD
        |   LESS WORD
        |   NUMBER (GREATER | LESS) WORD
        |   REDIR_WORD (GREATER | LESS | LESS_LESS_MINUS) WORD
        |   ...

这样,每个 alt 中就有一个唯一的第一个标记,然后您可以将其分配给局部变量:

redirection
        :   op = GREATER WORD
        |   op = LESS WORD
        |   op = NUMBER subOp= (GREATER | LESS) WORD
        |   op = REDIR_WORD subOp =(GREATER | LESS | LESS_LESS_MINUS) WORD
        |   ...

这样你就可以轻松地检查你在听众/访问者中的哪个替代:

public exitRedirection(RedirectionContext ctx) {
    switch (ctx.op.getType()) {
        case YourParser.GREATER_WORD: {
            break;
        }

        case YourParser.REDIR_WORD: {
            switch (ctx.supOp.getType()) {
                case YourParser.LESS_LESS_MINUS: {
                    break;
                }
            }
            break;
        }
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在访问期间知道ANTLR解析器当前处于哪个替代规则 的相关文章

随机推荐