XText Dangling Else — другой вариант

Итак, я использую 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

Однако, рассматривая это как оборванную проблему else, решение, которое все дают, дает мне неправильное решение. Как же тогда в 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. Как заставить его «смотреть вперед» для символа «+», а затем разделить оператор на два, если он увидит это?


person alexp82539    schedule 17.03.2016    source источник


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

person Miro Spönemann    schedule 21.03.2016