取决于上下文的ANTLR4语义谓词不起作用 [英] ANTLR4 Semantic Predicates that is Context Dependent Does Not Work

查看:91
本文介绍了取决于上下文的ANTLR4语义谓词不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用这种缩小的语法来解析类似C ++的声明(删除了许多详细信息以使其成为一个可以正常工作的示例).它无法神秘地工作(至少对我而言).它与上下文相关谓词的使用有关吗?如果是,那么实现计算子节点数量逻辑"的正确方法是什么?

I am parsing a C++ like declaration with this scaled down grammar (many details removed to make it a fully working example). It fails to work mysteriously (at least to me). Is it related to the use of context dependent predicate? If yes, what is the proper way to implement the "counting the number of child nodes logic"?

grammar CPPProcessor;

cppCompilationUnit : decl_specifier_seq? init_declarator* ';'  EOF;

init_declarator:     declarator initializer?;
declarator:  identifier;
initializer: '=0';

decl_specifier_seq
  locals [int cnt=0]
    @init {  $cnt=0;    }
: decl_specifier+ ;
decl_specifier :   @init {    System.out.println($decl_specifier_seq::cnt);  }
    'const'
  | {$decl_specifier_seq::cnt < 1}? type_specifier {$decl_specifier_seq::cnt += 1;}  ;
type_specifier:  identifier ; 
identifier:IDENTIFIER;
CRLF: '\r'? '\n' -> channel(2);
WS: [ \t\f]+    -> channel(1);
IDENTIFIER:[_a-zA-Z] [0-9_a-zA-Z]* ;

我需要实现标准的C ++规则,在decl_specifier_seq 下允许的字符数不得超过1个.

I need to implement the standard C++ rule that no more than 1 type_specifier is allowed under an decl_specifier_seq.

type_specifier之前的语义谓词似乎是解决方案.计数自然会在decl_specifier_seq中声明为局部变量,因为可能嵌套decl_specifier_seq.

Semantic predicate before type_specifier seems to be the solution. And the count is naturally declared as a local variable in decl_specifier_seq since nested decl_specifier_seq are possible.

但是似乎像我使用的上下文谓词一样,上下文相关的语义谓词会产生错误的解析,即引用$ attributes的语义谓词.首先输入结果正确的文件(以说明普通解析树的样子):

But it seems that a context dependent semantic predicate like the one I used will produce incorrect parsing i.e. a semantic predicate that references $attributes. First an input file with correct result (to illustrate what a normal parse tree looks like):

int t=0;

和解析树:

但是,没有'= 0'的输入将有助于解析

But, an input without the '=0' to aid the parsing

int t;

0
1
line 1:4 no viable alternative at input 't'
1

解析失败,并显示无可行替代方案"错误(控制台中打印的数字是$decl_specifier_cnt::cnt值的调试打印,以验证测试条件).即,语义谓词不能阻止将t解析为type_specifier,并且t不再被视为init_declarator.这里有什么问题?是因为使用具有$decl_specifier_seq::cnt的上下文相关谓词吗?

the parsing failed with the 'no viable alternative' error (the numbers printed in the console is debug print of the $decl_specifier_cnt::cnt value as a verification of the test condition). i.e. the semantic predicate cannot prevent the t from being parsed as type_specifier and t is no longer considered a init_declarator. What is the problem here? Is it because a context dependent predicate having $decl_specifier_seq::cnt is used?

这是否意味着上下文相关谓词不能用于实现计算子节点数量"逻辑?

Does it mean context dependent predicate cannot be used to implement "counting the number of child nodes" logic?

编辑

我尝试了其谓词使用成员变量而不是$decl_specifier_seq::cnt的新版本,令人惊讶的是,语法现在可以正常工作,证明上下文相关谓词确实导致先前的语法失败:

I tried new versions whose predicate uses member variable instead of the $decl_specifier_seq::cnt and surprisingly the grammar now works proving that the Context Dependent predicate did cause the previous grammar to fail:

....
@parser::members {
  public int cnt=0;
}
decl_specifier
  @init {System.out.println("cnt:"+cnt);  }
: 
    'const'
  | {cnt<1 }? type_specifier {cnt++;}  ;

生成正常的分析树:

这引发了一个问题,即如果必须使用成员变量来替换局部变量以避免上下文相关谓词,那么如何支持嵌套规则?

This gives rise to the question of how to support nested rule if we must use member variables to replace the local variables to avoid context sensitive predicates?

一个奇怪的结果是,如果我在谓词之后添加/*$ctx*/,它将再次失败:

And a weird result is that if I add a /*$ctx*/ after the predicate, it fails again:

decl_specifier
  @init {System.out.println("cnt:"+cnt);  }
: 
    'const'
  | {cnt<1 /*$ctx*/ }? type_specifier {cnt++;}  ;

line 1:4 no viable alternative at input 't'

解析失败,并显示no viable alternative.为什么/*$ctx*/会导致解析失败,就像使用$decl_specifier_seq::cnt一样,尽管实际逻辑仅使用成员变量? 并且,如果没有/*$ctx*/,则会出现另一个与在@init块之前调用的谓词有关的问题(在此描述)

The parsing failed with no viable alternative. Why the /*$ctx*/ causes the parsing to fail like when $decl_specifier_seq::cnt is used although the actual logic uses a member variable only? And, without the /*$ctx*/, another issue related to the predicate called before @init block appears(described here)

推荐答案

ANTLR 4在两种情况下评估语义谓词.

ANTLR 4 evaluates semantic predicates in two cases.

  1. 生成的代码在解析期间评估语义谓词,并引发评估返回false的异常.以此方式评估在解析过程中遍历的所有谓词,包括上下文相关的谓词和未出现在决策左侧的谓词.
  2. 预测方法评估谓词,以便在解析过程中做出正确的决定.在这种情况下,假设出现在除了要评估的决策的左边缘以外的任何地方的谓词返回true(即被忽略).另外,仅当上下文数据可用时,才评估上下文相关谓词.预测算法将不会创建解析代码尚未提供的上下文结构.如果在预测过程中遇到上下文相关的谓词,并且没有上下文可用,则假定该谓词返回true(即该决策将忽略该谓词).

代码生成器不会评估目标语言的语义,因此当$ctx出现在/*$ctx*/中时,它无法知道$ctx在语义上是不相关的.两种情况都导致谓词被视作上下文相关.

The code generator does not evaluate the semantics of the target language, so it has no way to know that $ctx is semantically irrelevant when it appears in /*$ctx*/. Both cases result in the predicate being treated as context-dependent.

这篇关于取决于上下文的ANTLR4语义谓词不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆