token
no modifica la precedencia. Si lo hacen las declaraciones realizadas usando las palabras left
, right
y nonassoc
. Los tokens declarados en la misma línea
tienen igual precedencia. La precedencia es mayor cuanto mas abajo en
el texto. Así, en el ejemplo que sigue, el token *
tiene
mayor precedencia que +
pero la misma que /
.
expr : expr '+' expr
tiene la precedencia del token +
.
Por tanto es imposible declarar dos tokens con diferente asociatividad y la misma precedencia.
prec token
, donde token
es un token
con la precedencia que deseamos. Vea el uso del token dummy
en el siguiente ejercicio.
%{ #define YYSTYPE double #include <stdio.h> %} %token NUMBER %left '@' %right '&' dummy %% list : | list '\n' | list e ; e : NUMBER | e '&' e | e '@' e %prec dummy ; %% extern FILE * yyin; main(int argc, char **argv) { if (argc > 1) yyin = fopen(argv[1],"r"); yydebug = 1; yyparse(); } yyerror(char *s) { printf("%s\n",s); }
yacc
11.2.1
Responda a las siguientes cuestiones:
4@3@5
, 4&3&5
, 4@3&5
, 4&3@5
.
e : e '@' e
?
0 $accept : list $end 1 list : 2 | list '\n' 3 | list e 4 e : NUMBER 5 | e '&' e 6 | e '@' e
state 0 $accept : . list $end (0) list : . (1) . reduce 1 list goto 1 state 1 $accept : list . $end (0) list : list . '\n' (2) list : list . e (3) $end accept NUMBER shift 2 '\n' shift 3 . error e goto 4 state 2 e : NUMBER . (4) . reduce 4 state 3 list : list '\n' . (2) . reduce 2 state 4 list : list e . (3) e : e . '&' e (5) e : e . '@' e (6) '@' shift 5 '&' shift 6 $end reduce 3 NUMBER reduce 3 '\n' reduce 3 |
state 5 e : e '@' . e (6) NUMBER shift 2 . error e goto 7 state 6 e : e '&' . e (5) NUMBER shift 2 . error e goto 8 state 7 e : e . '&' e (5) e : e . '@' e (6) e : e '@' e . (6) '&' shift 6 $end reduce 6 NUMBER reduce 6 '@' reduce 6 '\n' reduce 6 state 8 e : e . '&' e (5) e : e '&' e . (5) e : e . '@' e (6) '&' shift 6 $end reduce 5 NUMBER reduce 5 '@' reduce 5 '\n' reduce 5 |
7 terminals, 3 nonterminals 7 grammar rules, 9 states
1@2&3
, al establecer la variable yydebug = 1
y definir la macro YYDEBUG
:
$ hocprec yydebug: state 0, reducing by rule 1 (list :) yydebug: after reduction, shifting from state 0 to state 1 1@2&3 yydebug: state 1, reading 257 (NUMBER) yydebug: state 1, shifting to state 2 yydebug: state 2, reducing by rule 4 (e : NUMBER) yydebug: after reduction, shifting from state 1 to state 4 yydebug: state 4, reading 64 ('@') yydebug: state 4, shifting to state 5 yydebug: state 5, reading 257 (NUMBER) yydebug: state 5, shifting to state 2 yydebug: state 2, reducing by rule 4 (e : NUMBER) yydebug: after reduction, shifting from state 5 to state 7 yydebug: state 7, reading 38 ('&') yydebug: state 7, shifting to state 6
%left '@'
?. ¿O quizá es porque la precedencia de @
es menor que la de &
? La respuesta es que la precedencia
asignada por la declaración
e : e '@' e %prec dummy
&
con su misma precedencia.
Al pasar a ser asociativa a derechas (debido a que
dummy
lo es), se debe desplazar y no reducir.
1&2@3
. Compara tus predicciones con los resultados.
$ hocprec yydebug: state 0, reducing by rule 1 (list :) yydebug: after reduction, shifting from state 0 to state 1 1&2@3 yydebug: state 1, reading 257 (NUMBER) yydebug: state 1, shifting to state 2 yydebug: state 2, reducing by rule 4 (e : NUMBER) yydebug: after reduction, shifting from state 1 to state 4 yydebug: state 4, reading 38 ('&') yydebug: state 4, shifting to state 6 yydebug: state 6, reading 257 (NUMBER) yydebug: state 6, shifting to state 2 yydebug: state 2, reducing by rule 4 (e : NUMBER) yydebug: after reduction, shifting from state 6 to state 8 yydebug: state 8, reading 64 ('@') yydebug: state 8, reducing by rule 5 (e : e '&' e)
e
e & e
@
. La regla tiene mayor precedencia
que el token,dado que la precedencia de la regla es la de
&
.