Gramática de Precedência de Operadores
Gramática de Operadores (G.Op) são gramáticas tais que, para toda regra de P, A
® b , então b¹e e b não possui 2 não-terminais consecutivos.
Ex1: A gramática
E
® EAE | (E) | -E | idA
® + | - | * | / | pode ser transformada numa G.Op:
E
® E+E | E-E | E*E | E/E | E E |Þ
Parsers simples, eficientesclasse pequena de gramáticas
Relações de Precedência (entre 2 terminais)
a < b
® a dá precedência a ba = b
® a e b têm mesma precedênciaa > b
® a tem precedência sobre bCuidado: pode-se ter a > b e a > b ou a ? b
Como determinar as Relações de Precedência:
Ex: + < * , * > + (Gramáticas Ambíguas)
Objetivo das Relações de Precedência:
Delimitar um handle:
Uma forma sentencial mais à direita numa G.Op tem a forma:
b0a1b 1........anb n ; ai Î VT; bi Î VN È {e }
Hipótese: ai R ai+1; R, único,
Î {>, <, =}$ < b e b > $; b
Î VT e $ denota fim da cadeia-input
Tomando parte da Gramática do Ex1:
sentença: id + id * id
com as relações: $ <id> + <id> * <id> $
Processo para detectar o handle:
Portanto: $ E + <id> * <id> $
Em 2 passos: $ E + E * E $
Considerando que: $ < + < * > $
a extremidade esquerda do próximo handle está entre + e *, e a direita entre * e $. Como os não-terminais "limites" fazem parte do handle, temos que, em E+E*E, o handle é E*E ou seja, $ < E + < E * E > $
Algoritmo Parsing Precedência Operadores
else begin
begin
end
else
end
OBS: VN "anônimos"
Métodos para Determinar Relações Precedência
a. Através de Heurísticas - para Gramáticas Expr. Ambíguas
E também:
(=) $<( $<id
(<( id>$ )>$
(<id id>) )>)
Tabela para Gramáticas do Ex1:
Operadores Unários
Por exemplo negação lógica ~ : Para todo operador
q :
Exemplo:
~ < and
and > and
Portanto E and ~ E and E
Þ ( E and (~ E)) and E
-: unário (prefix) e binários (infix)
Þ
A.L. deve "lembrar" token anterior para distinguir entre um ou outro.
b. Através de Funções de Precedência
Ao invés de armazenar e consultar a matriz de Precedência, codificá-la em 2 funções - f e g - que mapeiam terminais em números inteiros.
Para 2 terminais a e b:
2 passos:
(i)
Portanto se A
® a a g b b ;A
Î VNa, b
Î VT a , b Î (VN È VT)* e g Î (VN È {e })
A
A, B
a, b
Î VTg
Î VN È {e }a
, b , d Î (VN È VT)*
A
A, B
Î VNa, b
Î VTa
, b , d Î (VN È VT)*g
Î VN È {e }(ii) f e g para Gramática do Ex1:
* < id
Þ f(*) = 4 < g(id) = 5
OBS: f(id) > g(id) embora id ? id
Rotinas de Erro devem detectar!
Algoritmo: Funções de Precedência
( se a = b e c = b, fa e fc estarão num mesmo grupo. Se c = d então fa e gd estão juntos - embora a e d não se relacionem)
Para a matriz da Gramática simplificada do Ex1:
Precedência de Operadores: Recuperação de Erros
a) Um handle foi encontrado, mas não há regra que o tenha do lado direito.
Estratégia: desempilhar handle (sem ações semânticas) e diagnosticar erro.
Diagnósticos: lado direito "parecido" ao handle desempilhado.
Exemplo: abc desempilhado e
b)
Estratégia:
Modificar (subst, elim, inserir) símbolos da pilha e/ou input
Exemplo: Erros para Gramática Ex1:
E1: quando toda uma expressão é esperada
inserir id na cadeia input
diagnóstico: "missing operand"
E2: expressão começando com ‘)’
eliminar ) da cadeia
diagnóstico: "unbalanced right parenthesis"
E3: id ou ) é seguido por id ou ( :
inserir + na cadeia
diagnóstico: "missing operator"
E4: expressão terminando com ( :
desempilha (
diagnóstico: "missing right parenthesis"