【发布时间】:2022-01-05 22:25:54
【问题描述】:
如果我们查看 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 种访问方法规则似乎有些过分。
通常我会通过 ctx.GREATER() != null 进行一些 null 检查以了解是否选择了第一个备选方案,但在此示例中几乎总是有 2 个相互冲突的备选方案,例如:
GREATER WORD
NUMBER GREATER WORD
那么我应该使用ctx.NUMBER() != null && ctx.GREATER() != null 匹配第二个备选方案并使用ctx.NUMBER() == null && ctx.GREATER() != null 匹配第一个备选方案吗?
是否有更简单或更简洁的方法可以知道访问者当前所处的具体替代方案?
【问题讨论】:
-
我这样做的方法是get the first child of the node,然后测试令牌类型。或者,您可以标记每个 alt。
-
43 个标签有点多,我正在尝试找到一种更清洁的方法。我看到
RuleContext::getChild可以让我得到第一个孩子,但它返回ParseTree,我看不到如何从javadoc 中获取令牌类型。引起我注意的是getAltNumber;这似乎正是我想要的,但它说它不是默认设置的,所以我不确定如何启用它 -
将第一个孩子投射到 TerminalNode,然后 getSymbol()、getType() 和测试。
-
很好,确实有效,我想我只需要分支很多(由于这个生产规则有多少替代方案)但这确实比仅仅标记所有内容有所帮助,谢谢!
标签: java antlr4 visitor-pattern