我正在使用Antlr sintaxe为语言LUA编写语法,但我在exp_prefixo
,variavel
和chamada_de_funcao
之间收到了相互左递归错误。我阅读了其他帖子中给出的很多解决方案,但无法使其适用于我的具体情况,因为大多数是直接递归或只有两个相互递归的规则。
以下是相互左递归的规则集:
exp_prefixo
: variavel
| chamada_de_funcao
| '(' expressao ')'
;
chamada_de_funcao
: exp_prefixo args
| exp_prefixo ':' NOME args
;
variavel
: NOME
| exp_prefixo '[' expressao ']'
| exp_prefixo '.' NOME
;
这是我的语法文件:
programa
: trecho
;
trecho
: (comando (';')?)* (ultimo_comando (';')?)?
;
bloco
: trecho
;
comando
: lista_variaveis '=' lista_expressoes
| chamada_de_funcao
| 'do' bloco 'end'
| 'while' expressao 'do' bloco 'end'
| 'repeat' bloco 'until' expressao
| 'if' expressao 'then' bloco ('elseif' expressao 'then' bloco)* ('else' bloco)? 'end'
| 'for' NOME '=' expressao ',' expressao (',' expressao)? 'do' bloco 'end'
| 'for' lista_de_nomes 'in' lista_expressoes 'do' bloco 'end'
| 'function' nome_da_funcao corpo_da_funcao
| 'local' 'function' NOME corpo_da_funcao
| 'local' lista_de_nomes ('=' lista_expressoes)?
;
ultimo_comando
: 'return' (lista_expressoes)?
| 'break'
;
nome_da_funcao
: NOME ('.' NOME)* (':' NOME)?
;
lista_variaveis
: variavel (',' variavel)*
;
variavel
: NOME
| exp_prefixo '[' expressao ']'
| exp_prefixo '.' NOME
;
lista_de_nomes
: NOME (',' NOME)*
;
lista_expressoes
: (expressao ',')* expressao
;
expressao
: 'nil'
| 'false'
| 'true'
| NUMERO
| CADEIA
| '...'
| funcao
| exp_prefixo
| construtor_tabela
| expressao opbin expressao
| opunaria expressao
;
exp_prefixo
: variavel
| chamada_de_funcao
| '(' expressao ')'
;
chamada_de_funcao
: exp_prefixo args
| exp_prefixo ':' NOME args
;
args
: '(' (lista_expressoes)? ')'
| construtor_tabela
| CADEIA
;
funcao
: 'function' corpo_da_funcao
;
corpo_da_funcao
: '(' (lista_par)? ')' bloco 'end'
;
lista_par
: lista_de_nomes (',' '...')?
| '...'
;
construtor_tabela
: '{' (lista_de_campos)? '}'
;
lista_de_campos
: campo (separador_de_campos campo)* (separador_de_campos)?
;
campo
: '[' expressao ']' '=' expressao
| NOME '=' expressao
| expressao
;
separador_de_campos
: ','
| ';'
;
opbin
: '+'
| '-'
| '*'
| '/'
| '^'
| '%'
| '..'
| '<'
| '<='
| '>'
| '>='
| '=='
| '~='
| 'and'
| 'or'
;
opunaria
: '-'
| 'not'
| '#'
;
有人可以提供一些有关如何消除此错误的初步步骤的提示吗?我已经理解了“理论”问题。我真的很难实施解决方案。
谢谢!
答案 0 :(得分:1)
要解决间接递归,通常会用规则代码本身替换规则的调用。这最终将导致直接左递归(并且可能是非常混乱的语法规则)。像:
a: b | A;
b: c | B;
c: a | C;
替换c
:
a: b | A;
b: a | C | B;
替换b
:
a: a | C | B | A;
现在从这里开始并重构a
,以便将所有左递归规则保留在a
中,并将其余部分移动到子规则中(如果需要)。
解决问题的另一个选择是在规则上稍等一下,直到找到一种方法来制定语法而根本没有左递归。大多数时候都有替代品。取表达式,通常写成:
expr:
expr AND expr
| expr OR expr
| primary // There must be at least one non-recursive alt.
;
等等。
这可以非递归地表达:
expr:
andExpr
| primary
;
andExpr: orExpr AND orExpr;
orExpr: ... OR ...;
等。这种方式也使运算符优先级更加明显,但可能会稍微改变优先级,具体取决于转换的执行方式。