XText Dangling Else - 其他选项

时间:2016-03-17 10:40:15

标签: antlr xtext ll ambiguous-grammar

所以我一直在使用X-Text并使用Syntactic Predicates。

经典的例子是悬空的其他问题,给出的解决方案是贪婪地解析else语句,即不要终止内部表达式,如下所示:

IfStatement: 'if' condition=Expression 'then' then=Expression (=>'else' else=Expression)?;

我有一个进程语法,例如,其中两个可以组合起来用二元运算符创建一个大进程 process 1 + process 2 提供过程1和过程2之间的选择

此外,流程可能会调用其他流程: process 1 -> process 2 表示执行流程1,然后执行流程2。

在我的语法中,以下内容: process 1 -> process 2 + process 3

应解释为

(process 1 -> process 2) + process 3

然而,考虑到这是一个悬而未决的问题,每个人提供的解决方案都为我提供了错误的解决方案。 那么,在X-Text中我怎么说,"如果它有意义,并且程序仍在解析,那么尽可能早地跳出内部声明"

为了清晰起见,这是我的语法的嗤之以鼻: PProc: PProcAtomic ({Binary.left = current} '+' right=Proc)?
; PProcAtomic returns PProc: dotted=Dotted (fields+=Field)* type="->" proc=Proc | bool=Bool type="&" proc=Proc | type="(" proc=Proc ")"
| type="||" (gens+=Gen)+ "@" "[" rset=Set "]" proc=Proc | type="|~|" (gens+=Gen)+ "@" proc=Proc | type="[]" (gens+=Gen)+ "@" proc=Proc
| type="|||" (gens+=Gen)+ "@" proc=Proc
| type=";" (gens+=Gen)+ "@" proc=Proc
| type="[|" rset=PSet "|]" (gens+=Gen)+ "@" proc=Proc
| type="|[" rset=PSet "]|" (gens+=Gen)+ "@" proc=Proc | type="<->" (gens+=Gen)+ "@" "[" (exprs+=Expr)+ "]" proc=Proc | type="STOP" | type="SKIP" | type="CHAOS" "(" rset=PSet ")" ; Proc: PProc | "namedprocess" ;

显然,如果我把&#39; =&gt;&#39;在&#34; +&#34;然后它将贪婪地消耗,导致错误的AST。我如何做到&#34;展望未来&#34;对于&#34; +&#34;符号,然后如果它看到那么将语句拆分成两个?

1 个答案:

答案 0 :(得分:1)

在描述基于运算符的表达式时,通常可以通过编写解析器规则链并避免对链中较低规则的反向引用来消除歧义,而不需要=>谓词。运算符优先级仅由链中规则的顺序控制。

在您的情况下,歧义是由频繁的对Proc规则的反向引用引起的。你可以写下这样的东西来避免它:

PProc returns Proc:
    PProcAdvanced ({Binary.left = current} '+' right=PProcAdvanced)*;

PProcAdvanced returns Proc:
    PProcAtomic
    | dotted=Dotted (fields+=Field)* type="->" proc=PProcAdvanced
    | bool=Bool type="&" proc=PProcAdvanced

    | type="||" (gens+=Gen)+ "@" "[" rset=Set "]" proc=PProcAdvanced 
    | type="|~|" (gens+=Gen)+ "@" proc=PProcAdvanced
    | type="[]" (gens+=Gen)+ "@" proc=PProcAdvanced

    | type="|||" (gens+=Gen)+ "@" proc=PProcAdvanced

    | type=";" (gens+=Gen)+ "@" proc=PProcAdvanced

    | type="[|" rset=PSet "|]" (gens+=Gen)+ "@" proc=PProcAdvanced

    | type="|[" rset=PSet "]|" (gens+=Gen)+ "@" proc=PProcAdvanced 
    | type="<->" (gens+=Gen)+ "@" "[" (exprs+=Expr)+ "]" proc=PProcAdvanced;

PProcAtomic returns Proc:
    "(" Proc ")"
    | type="STOP"
    | type="SKIP" 
    | type="CHAOS" "(" rset=PSet ")";

这里唯一的反向引用是"(" Proc ")",它以前括号为前缀,因此没有歧义。