[英]How to know which alternative rule ANTLR parser is currently in during visit
如果我们查看 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
时,感觉几乎不可能轻松地知道访问者当前所在的选项。我可以使用#
和标签对每个选项进行 label,但是为单个生产规则添加 43 种访问方法似乎有些过分。
通常我会通过执行ctx.GREATER() != null
来做一些null
检查,以了解是否选择了第一个替代方案,但在此示例中几乎总是有 2 个冲突的替代方案,例如:
GREATER WORD
NUMBER GREATER WORD
So should I do ctx.NUMBER().= null && ctx.GREATER() != null
to match the second alternative and ctx.NUMBER() == null && ctx.GREATER() != null
to match the first?
是否有更简单或更简洁的方法可以知道访问者当前所处的特定替代方案?
重组你的语法以减少替代方案。 其中许多具有共同的前导或尾随部分,例如:
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
| ...
有了它,您可以轻松地检查您在听众/访问者中的 alt:
public exitRedirection(RedirectionContext cts) {
switch (ctx.op.getType()) {
case YourParser.GREATER_WORD: {
break;
}
case YourParser.REDIR_WORD: {
switch (ctx.supOp.getType()) {
case YourParser.LESS_LESS_MINUS: {
break;
}
}
break;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.