N-арные операторы в грамматике ANTLR4

#antlr #antlr4 #grammar

#antlr #antlr4 #грамматика

Вопрос:

У меня есть грамматика для синтаксического анализа логических формул:

 expr: op=NOT right=expr                                   #Not
    | left=expr op=AND right=expr                         #And
    | left=expr op=OR right=expr                          #Or
    | left=expr op=XOR right=expr                         #Xor
    | <assoc=right> left=expr op=IMPL right=expr          #Implication
    | <assoc=right> left=expr op=EQ right=expr            #Equivalence
    | boolean=BOOL                                        #Boolean
    | '(' content=expr  ')'                               #Brackets
    | atomic=ATOMIC                                       #Atomic
    ;
BOOL        : TRUE|FALSE;
NOT         : ('!'|'not');
AND         : ('amp;'|'and');
OR          : ('|'|'or');
XOR         : ('^'|'xor');
IMPL        : '->';
EQ          : '<->';
TRUE        : ('True'|'true');
FALSE       : ('False'|'false');
ATOMIC      : [a-z] ([_]?[a-z] )*;
WS          : [ tn]  -> skip;       //Skip whitespaces
  

Как я могу изменить AND , OR , и XOR быть n-арными вместо двоичных (чтобы дочерние элементы этих операторов находились на одном уровне)? Я попытался заменить left=expr op=AND right=expr на expr (op=AND expr) , что ничего не меняет.

Ответ №1:

Что-то вроде этого помогло бы:

 expr
 : <assoc=right> expr IMPL expr
 | <assoc=right> expr EQ expr
 | xor_expr
 ;

xor_expr
 : or_expr (XOR or_expr)*
 ;

or_expr
 : and_expr (OR and_expr)*
 ;

and_expr
 : unary (AND unary)*
 ;

unary
 : NOT atom
 | atom
 ;

atom
 : BOOL
 | '(' expr  ')'
 | ATOMIC
 ;
  

Комментарии:

1. Спасибо! Но тогда что-то вроде a->b->c больше не может быть проанализировано. Такое выражение должно быть правоассоциативным. Как это можно сделать? Замена impl_expr (EQ impl_expr)? на impl_expr (EQ impl_expr)* теряет правоассоциативность.