2016-03-17 3 views
0

Итак, я использую X-Text и играю с синтаксическими предикатами.XText Dangling Else - Другой вариант

Классическим примером является оборванных еще проблема, где решение дано это жадностью разобрать заявление другого, то есть не прекратить внутреннее выражение, например, так:

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

У меня есть грамматики процессов, в которых два могут быть объединены, чтобы создать один большой процесс с бинарным оператором, например process 1 + process 2 дает возможность выбора между процессом 1 и 2 процесса

Кроме того, процессы могут вызывать другие процессы: process 1 -> process 2 означает, что процесс 1, затем выполните процесс два.

В моей грамматике, следующее: 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" ;

Очевидно, что если я надену «=>» на «+», он будет потреблять это жадно, что приведет к неправильному АСТ. Как заставить «смотреть вперед» на символ «+», а затем разделить заявление на два, если он это увидит?

ответ

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 ")", который предваряется открывающей скобкой и, таким образом, свободный от двусмысленности.

Смежные вопросы