Las declaraciones de precedencia y asociatividad mediante las palabras reservadas %left , %right , %nonassoc se utilizan para modificar estos criterios por defecto. La declaración de token s mediante la palabra reservada %token no modifica la precedencia. Si lo hacen las declaraciones realizadas usando las palabras left , right y nonassoc .
* tiene
mayor precedencia que + pero la misma que /.
expr : expr '+' expr
tiene la precedencia del token +.
prec token, donde token es un token con
la precedencia que deseamos. Vea el uso del token dummy
en el siguiente ejercicio.
Para ilustrar las reglas anteriores usaremos el siguiente
programa jison:
[~/jison/jison-prec(ast)]$ cat -n precedencia.jison
1 %token NUMBER
2 %left '@'
3 %right '&' dummy
4 %%
5 s
6 : list { console.log($list); }
7 ;
8
9 list
10 :
11 {
12 $$ = [];
13 }
14 | list '\n'
15 {
16 $$ = $1;
17 }
18 | list e
19 {
20 $$ = $1;
21 $$.push($e);
22 }
23 ;
24
25 e : NUMBER
26 {
27 $$ = "NUMBER ("+yytext+")";
28 }
29 | e '&' e
30 {
31 $$ = [ "&", $e1, $e2];
32 }
33 | e '@' e %prec dummy
34 {
35 $$ = ["@", $e1, $e2];
36 }
37 ;
38
39 %%
Obsérvese la siguiente ejecución:
[~/jison/jison-prec(ast)]$ cat input.txt 2@3@4 2&3&4 [~/jison/jison-prec(ast)]$ node precedencia.js input.txt [ [ '@', [ '@', 'NUMBER (2)', 'NUMBER (3)' ], 'NUMBER (4)' ], [ '&', 'NUMBER (2)', [ '&', 'NUMBER (3)', 'NUMBER (4)' ] ] ]
Compilamos a continuación con bison usando la opción -v para
producir información sobre los conflictos y las tablas de salto y
de acciones:
[~/jison/jison-prec(ast)]$ bison -v precedencia.jison precedencia.jison:6.31: warning: stray `$' precedencia.jison:21.27: warning: stray `$' precedencia.jison:31.31: warning: stray `$' precedencia.jison:31.36: warning: stray `$' precedencia.jison:35.30: warning: stray `$' precedencia.jison:35.35: warning: stray `$'
La opción -v genera el fichero Precedencia.output
el cual contiene información detallada sobre el autómata:
[~/jison/jison-prec(ast)]$ cat precedencia.output
Grammar
0 $accept: s $end
1 s: list
2 list: /* empty */
3 | list '\n'
4 | list e
5 e: NUMBER
6 | e '&' e
7 | e '@' e
Terminals, with rules where they appear
$end (0) 0
'\n' (10) 3
'&' (38) 6
'@' (64) 7
error (256)
NUMBER (258) 5
dummy (259)
Nonterminals, with rules where they appear
$accept (8)
on left: 0
s (9)
on left: 1, on right: 0
list (10)
on left: 2 3 4, on right: 1 3 4
e (11)
on left: 5 6 7, on right: 4 6 7
state 0
0 $accept: . s $end
$default reduce using rule 2 (list)
s go to state 1
list go to state 2
state 1
0 $accept: s . $end
$end shift, and go to state 3
state 2
1 s: list .
3 list: list . '\n'
4 | list . e
NUMBER shift, and go to state 4
'\n' shift, and go to state 5
$default reduce using rule 1 (s)
e go to state 6
state 3
0 $accept: s $end .
$default accept
state 4
5 e: NUMBER .
$default reduce using rule 5 (e)
state 5
3 list: list '\n' .
$default reduce using rule 3 (list)
state 6
4 list: list e .
6 e: e . '&' e
7 | e . '@' e
'@' shift, and go to state 7
'&' shift, and go to state 8
$default reduce using rule 4 (list)
state 7
7 e: e '@' . e
NUMBER shift, and go to state 4
e go to state 9
state 8
6 e: e '&' . e
NUMBER shift, and go to state 4
e go to state 10
state 9
6 e: e . '&' e
7 | e . '@' e
7 | e '@' e .
'&' shift, and go to state 8
$default reduce using rule 7 (e)
state 10
6 e: e . '&' e
6 | e '&' e .
7 | e . '@' e
'&' shift, and go to state 8
$default reduce using rule 6 (e)
La presencia de conflictos, aunque no siempre, en muchos casos es debida a la introducción de ambiguedad en la gramática. Si el conflicto es de desplazamiento-reducción se puede resolver explicitando alguna regla que rompa la ambiguedad. Los conflictos de reducción-reducción suelen producirse por un diseño erróneo de la gramática. En tales casos, suele ser mas adecuado modificar la gramática.
Casiano Rodríguez León