如何在解析期间检查ID是否有效 - ParseTreeListener输入未调用的事件

时间:2014-08-01 20:59:12

标签: antlr4

我的语法包含以下内容:

assignment
: ID ASSIGN expr
;

expr
 : MINUS expr                 #unaryMinusExpr
 | NOT expr                   #notExpr
 | expr MULT expr             #multExpr
 | expr DIV expr              #divExpr
 | expr PLUS expr             #plusExpr
 | expr MINUS expr            #minusExpr
 | expr LTEQ expr             #lteqExpr
 | expr GTEQ expr             #gteqExpr
 | expr LT expr               #ltExpr
 | expr GT expr               #gtExpr
 | expr NEQ expr              #neqExpr
 | expr EQ expr               #eqExpr
 | expr AND expr              #andExpr
 | expr OR expr               #orExpr
 | atom                       #atomExpr
 ;

atom
 : OPAR expr CPAR #parExpr
 | (INT | FLOAT)  #numberAtom
 | (TRUE | FALSE) #booleanAtom
 | STRING         #stringAtom
 | ID             #idAtom
 ;

ID
 : [a-zA-Z_] [a-zA-Z_0-9]*
 ;

此处的ID表示数据库中的条目(行),用户通过其引用,ID,ID。因此,在解析公式时,我想检查它们是否输入了有效的ID。

从我所知道的,可行的方法是让ParseTreeListener覆盖EnterIdAtom,这样我就可以抛出一个RecognitionException。所以我把它搞定了,但是从不调用Enter事件。

class MyListener : BaseListener
{
     public override EnterIdAtom(IdAtomContext context)
     {
          if (!CheckForValidId(context.ID().GetText())
          {
               throw new RecognitionException(...)
          }
     }
}

不确定原因?

有更好的方法吗?

感谢。

2 个答案:

答案 0 :(得分:1)

听起来你正在使用Parser.addParseListener(我添加的粗体字):

  

注册侦听器以在解析过程中接收事件。

     

为了支持保存输出的语法转换(包括但不限于左递归删除,自动左因子分解和优化代码生成),在解析期间对侦听器方法的调用可能与{{1}的调用有很大不同解析完成后使用。特别地,规则进入和退出事件可以在解析期间以与解析器之后不同的顺序发生。 此外,可能会忽略对某些规则输入方法的调用。

     

除了以下特定的例外情况,对侦听器事件的调用是 deterministic ,即对于相同的输入,对侦听器方法的调用将是相同的。

     
      
  • 对用于生成代码的语法的更改可能会改变侦听器调用的行为。
  •   
  • 在生成解析器时,对传递给ANTLR 4的命令行选项的更改可能会改变侦听器调用的行为。
  •   
  • 更改用于生成解析器的ANTLR工具的版本可能会更改侦听器调用的行为。
  •   

如果是这种情况,您应该在解析完​​成后使用ParseTreeWalker.DEFAULT来遍历树,而不是尝试将两个操作混合在一起。

答案 1 :(得分:0)

您是否设置了断点:

public override void enterEveryRule(ParserRuleContext ctx)

public override void enterAtom(AtomContext ctx)

如果甚至调用了规则,这应该会给你一个线索。

否则试试这个:

atom
 : OPAR expr CPAR #parExpr
 | (INT | FLOAT)  #numberAtom
 | (TRUE | FALSE) #booleanAtom
 | STRING         #stringAtom
 | atomId            // changed!
 ;


atomId
 :  ID
 ;

这将生成一个新的“真实”上下文,您可以访问:

public override void enterAtom(AtomIdContext ctx) {}