2017-01-22 12 views
1

Я прочитал много вопросов здесь, в StackOverflow о проблемах с левой левой рекурсией в парсерах LL (k). Я нашел общий алгоритм для удаления левой рекурсии:ANTLR4 взаимная левая рекурсивная грамматика

A : Aa | b ; 

становится

A : bR ; 
R : (aA)? ; 

Однако, я не могу понять, как применить его к моей ситуации. У меня есть

left_exp: IDENT | exp DOT IDENT ; 
exp  : handful 
     | of 
     | other rules 
     | left_exp ; 

«несколько других правил» содержит регулярные рекурсию, такие как exp : exp PLUS exp и т.д., и нет никаких проблем. Проблема заключается в том, что left_exp и exp являются взаимно рекурсивными.

Я думал о том, просто добавив IDENT и exp DOT IDENT к exp правилам, но бывают ситуации, когда другие действующие exp правила не применяются, где left_exp будет действительным.

EDIT

У меня есть следующее правило, которое вызывает для левого выражения с последующим назначением.

assign_statement: left_exp (COLON IDENT)? EQUAL exp SEMI ; 

Поскольку регулярное выражение только левое выражение, если оно сопровождается DOT IDENT, кажется, что я не могу просто добавить

| IDENT 
| exp DOT IDENT 

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

ответ

1

подхода я применяю обычно выглядит следующим образом:

A: Aa | b; 

становится:

A: b (a)*; 

Или вообще: все альты без левой рекурсии следует все альты с (удалено) левой рекурсией с неограниченное количество (выражается через оператор kleene). Пример:

A: Aa | Ab | c | d | Ae; 

становится:

А: (C |) (а | Ь | е) *;

Вы можете проверить это легко заменить непрерывно A:

A: Aa | b; 
A: (Aa | b)a | b; 
A: Aaa | ba | b; 
A: (Aa | b)aa | ba | b; 
A: Aaaa | baa | ba | b; 

т.д.

В вашем примере, однако у вас есть опосредованная левая рекурсия (через 2 правил). ANTLR не принимается. Решением является перемещение альтов от left_exp к правилу exp, а затем применить описанный выше алгоритм.

+0

Я думал, что не могу совместить эти два, потому что в определении языка есть оператор присваивания, который вызывает левое выражение, а выражение может быть только левым выражением, если за ним следует DOT IDENT. Я обновлю вопрос, чтобы включить эту информацию. –

+0

Я не уверен, что понимаю, что вы после, но имейте в виду, что синтаксический анализатор - это синтаксический инструмент. Он не понимает семантику, которую вы подразумеваете. Вы должны принудительно применять их после разбора, если это необходимо. С точки зрения парсера нет никакой разницы, если вы изолируете 2 альта в собственном правиле или нет. Однако ANTLR не сможет анализировать взаимно левые рекурсивные правила. Левая рекурсия может произойти только в одном правиле. –

+0

В принципе, 'l_exp' - это то, что может быть в левой части назначения, либо идентификатор, либо точечный идентификатор' exp', в то время как 'l_exp' также является действительным' exp' сам по себе. Я старался не допускать что-то вроде '6 = 12', которое является целым литералом в левой части задания. Но это звучит так, как будто мне просто нужно разрешить это после парсера и обработать его позже. –