Разбор выражения миксфикса в antlr3

Мне нужно адаптировать грамматику ANTLR3 для поддержки выражений let. Оператору нужно привязать очень слабо. Например, let x=3 in x + 1 читается как let x=3 in (x+1), а не как (let x=3 in x) + 1.

Моя кандидатская грамматика все еще неоднозначна, к сожалению. Есть ли стандартный способ сделать правила однозначными? (С дополнительным ( ) это работает.)

Кстати, вроде работает коробка с ANTLR4. Однако в моем случае это не вариант.

grammar Expr;

prog:   stat+ ;

stat:   expr NEWLINE
    |   ID '=' expr NEWLINE
    |   NEWLINE
    ;

expr:   sum ( ('*'|'/') sum )* ;

sum:    atom ( ('+'|'-') atom )* ;

atom:   INT
    |   ID
    |   '(' expr ')'
 // |   '(' let ')'
    |   let
    ;

let:    'let' ID '=' expr 'in' expr ;

ID  :   ('a' .. 'z')+ ;
INT :   ('0' ..'9')+ ;
NEWLINE: '\r'? '\n' ;
WS  :   ' ' { $channel = HIDDEN; };

person Matt    schedule 10.06.2017    source источник
comment
Также должно быть так, что 3 * let x = 2 in x+1 совпадает с 3 * (let x=2 in x+1).   -  person Matt    schedule 10.06.2017
comment
Я попытался установить options { greedy = true; }, но, возможно, не в том месте?   -  person Matt    schedule 10.06.2017


Ответы (2)


Нет проблем.

Разобранное дерево для ввода

let x=3 in x + 1
3 * let x = 2 in x+1

is

Проанализированное дерево

person saka1029    schedule 10.06.2017
comment
Я получаю сообщение об ошибке (или предупреждение): Decision can match input such as "{'*', '/'}" using multiple alternatives: 1, 2 и т. д. По-видимому, синтаксический анализатор делает то, что я хочу, но, похоже, это совпадение. Это разрешает двусмысленную ситуацию в мою пользу. Счастливчик! - person Matt; 10.06.2017

Обычный способ - иметь разные нетерминалы для каждого уровня приоритета, например так (обратите внимание, что у вас, кажется, есть обратный приоритет суммирования и создания, поэтому я тоже это исправил):

expr:   sum | let;

let:    'let' ID '=' expr 'in' expr ;

sum:    product ( ('+'|'-') prodcut)* ;

product: atom ( ('*'|'/') atom )* ;

atom:   INT
    |   ID
    |   '(' expr ')'
    ;
person Matt Timmermans    schedule 10.06.2017
comment
Спасибо за очень быстрый ответ! Я ошибаюсь, думая, что эта грамматика не принимает 3 + let x=2 in x? - person Matt; 10.06.2017
comment
да. Допустить это было бы странно и немного грубо: у вас есть особый вид атома, который может появиться только в конце особого вида продукта, который может появиться только в конце особого вида суммы. - person Matt Timmermans; 10.06.2017
comment
Может быть, это странно, но именно так устроен целевой язык. Я попытался добавить специальные правила, упоминающие let в других местах, но это не сработало без конфликта. - person Matt; 10.06.2017
comment
Тогда вы, вероятно, захотите жить с неоднозначной грамматикой. Обычное правило по умолчанию состоит в том, чтобы урегулировать конфликт сдвига-уменьшения в пользу сдвига, который обычно можно заставить работать. - person Matt Timmermans; 10.06.2017