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

本教程将介绍如何在访问期间知道ANTLR解析器当前处于哪个替代规则中的处理方法,这篇教程是从别的地方看到的,然后加了一些国外程序员的疑问与解答,希望能对你有所帮助,好了,下面开始学习吧。

怎么在访问期间知道ANTLR解析器当前处于哪个替代规则中 教程 第1张

问题描述

如果我们查看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检查,以了解是否选择了第一个备选方案,但在本例中几乎总是有两个冲突的备选方案,例如:

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
  |...

通过该选项,您可以轻松地检查您在监听器/访问者中的哪个ALT:

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;
  }
 }

好了关于怎么在访问期间知道ANTLR解析器当前处于哪个替代规则中的教程就到这里就结束了,希望趣模板源码网找到的这篇技术文章能帮助到大家,更多技术教程可以在站内搜索。