Originariamente inviato da edriv
-1 + -5 in algebra non avrebbe nessun senso, mentre dovresti scrivere (-1)+(-5).
L'ambiguità è risolta dando precedenza all'operatore unario in fase di analisi sintattica, o altrimenti forire una grammatica non ambigua ottenibile a partire da una ambigua utilizzando tecniche come la fattorizzazione sinistra ad esempio
dagli appunti presi da Compilers
by Alfred V. Aho, Ravi Sethi, Jeffrey D. Ullman
Analisi discendente - parser predittivo
• L’analisi discendente può richiedere il backtrack: per un
simbolo input a è possibile applicare più produzioni:
A => a1 |…|an se esistono più alternative (a1 …an ) che
iniziano con a. Rimedio: fattorizzazione sinistra
• L’analisi discendente non è applicabile se la grammatica è
ricorsiva sinistra (left recursive), cioè se A Þ Aa (A non
terminale). Rimedio: eliminazione ricorsione sinistra
es:
<stmt> => if <expr> then <stmt>
| if <expr> then <stmt> else <stmt>
fattorizzazione sinistra:
<stmt> => if <expr> then <stmt><S>
<S> ® e | else <stmt>
oppure ancora in fase di generazione di codice durante la discesa del parse tree,
un pezzo del generatore di codice un mini-compilatore pascal
codice:
/* versione unaria */
case T_MINUS: // Token -
/* se numero di operandi == 1 */
if (n->opr.nops == 1)
{
gencode(n->opr.op[0]);
fprintf(g_code_file, "\t%s\n", get_instr(I_NEG));
break;
}
........
default:
gencode(n->opr.op[0]);
gencode(n->opr.op[1]);
switch (n->opr.oper)
{
case T_PLUS: // Token +
fprintf(g_code_file, "\t%s\n",
get_instr(I_ADD));
break;
case T_MINUS: // Token -
fprintf(g_code_file, "\t%s\n",
get_instr(I_SUB));
break;
........
codice:
program test1;
var x: integer;
begin
x := -1 + -5;
end.
codice:
compiling test1.pas ...
Symbol table
------------
id: 'test1', declared: false
id: 'x', declared: true
Syntax tree
-----------
opr: T_SEMICOLON
1-opr: T_ASSIGNMENT
2-id: 'x', declared: true
2-opr: T_PLUS
3-opr: T_MINUS
4-value: 1
3-opr: T_MINUS
4-value: 5
genera questo codice
codice:
pushINT 1
neg
pushINT 5
neg
add
pop x
che valutato da correttamente -6