Я прочитал много вопросов здесь, в 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
моему определению выражения, потому что тогда задание будет принимать любое другое действительное выражение слева, а не только одно из этих двух.
Я думал, что не могу совместить эти два, потому что в определении языка есть оператор присваивания, который вызывает левое выражение, а выражение может быть только левым выражением, если за ним следует DOT IDENT. Я обновлю вопрос, чтобы включить эту информацию. –
Я не уверен, что понимаю, что вы после, но имейте в виду, что синтаксический анализатор - это синтаксический инструмент. Он не понимает семантику, которую вы подразумеваете. Вы должны принудительно применять их после разбора, если это необходимо. С точки зрения парсера нет никакой разницы, если вы изолируете 2 альта в собственном правиле или нет. Однако ANTLR не сможет анализировать взаимно левые рекурсивные правила. Левая рекурсия может произойти только в одном правиле. –
В принципе, 'l_exp' - это то, что может быть в левой части назначения, либо идентификатор, либо точечный идентификатор' exp', в то время как 'l_exp' также является действительным' exp' сам по себе. Я старался не допускать что-то вроде '6 = 12', которое является целым литералом в левой части задания. Но это звучит так, как будто мне просто нужно разрешить это после парсера и обработать его позже. –