0

所以我一直在使用 X-Text 和句法谓词。

经典的例子是悬空 else 问题,给出的解决方案是贪婪地解析 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" ;

显然,如果我将 '=>' 放在“+”上,那么它会贪婪地消耗它,从而导致错误的 AST。我如何让它“向前看”一个“+”符号,然后如果它看到的话,将语句分成两部分?

4

1 回答 1

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 ")",它以左括号为前缀,因此没有歧义。

于 2016-03-21T09:14:04.747 回答