No artigo Analisando expressões por descendência recursiva de Theodore Norvell (1999), o autor começa com a seguinte gramática para expressões aritméticas:
E --> E "+" E | E "-" E | "-" E | E "*" E | E "/" E | E "^" E | "(" E ")" | v
o que é bastante ruim, porque é ambíguo e recursivo à esquerda. Então ele começa removendo a recursão esquerda e seu resultado é o seguinte:
E --> P {B P}
P --> v | "(" E ")" | U P
B --> "+" | "-" | "*" | "/" | "^"
U --> "-"
Mas não consigo descobrir como ele chegou a esse resultado. Quando tento remover a recursão esquerda, faço da seguinte maneira:
Primeiramente, agrupo as produções que não deixaram recursão em um grupo e outras (recursivas à esquerda) em outro grupo:
E --> E "+" E | E "-" E | E "*" E | E "/" E | E "^" E // L-recursive E --> v | "(" E ")" | "-" E
Em seguida, nomeio-os e considero as manipulações mais fáceis:
E --> E B E // L-recursive; B stands for "Binary operator" E --> P // not L-recursive; P stands for "Primary Expression" P --> v | "(" E ")" | U E // U stands for "Unary operator" B --> "+" | "-" | "*" | "/" | "^" P --> "-"
Agora, preciso lidar apenas com as duas primeiras produções, que agora são mais fáceis de lidar.
Reescrevo essas duas primeiras produções começando da produção não L-recursiva (que é simplesmente
P
a expressão Primária) e seguindo-a pela cauda opcionalT
, que eu defino como o restante da produção original menos o primeiro não-recursivo esquerdo recursivo à esquerda (isto é, apenasB E
) seguido pela caudaT
, ou que pode estar vazia:E --> P T T --> B E T |
(observe a alternativa vazia para a cauda).
Agora, essas duas produções agora posso reescrever no EBNF:
E --> P {B E}
que é quase o que o autor obtém, mas eu tenho, em
E
vez dissoP
, dentro do padrão de repetição de zero ou mais (a cauda). As outras produções são exatamente as mesmas que ele tem:P --> v | "(" E ")" | U E B -> "+" | "-" | "*" | "/" | "^" U -> "-"
mas aqui também eu tenho, em
E
vez deP
na primeira produção paraP
.
Então, minha pergunta é: o que estou perdendo? Que transformação algébrica na sintaxe eu preciso proceder agora para obter a mesma forma exata que o autor obtém? Tentei substituições E
, mas isso só me leva a loops. Eu suspeito que eu preciso de alguma forma para substituir P
para E
, mas eu não sei qualquer transformação legal que a justifique. Talvez você saiba qual é o último passo que falta?
Respostas:
A etapa que falta:
reescreva E em T:
Simplifique T:
Equivalente a:
E aí está você.
fonte
T
s com segurança em umT
? Existe alguma regra para isso? (Eu suspeito que poderia ser de alguma forma semelhante à regra em lógica booleana algébrica que diz "aa = a".)*
? Eu vi no "Dragon Book" (3.3, p.91) issox** = x*
. Essa é a mesma regra que você usou?