El analizador YACC Bison GLR no separará en un conflicto de reducción / reducción.
Preparé un analizador sintáctico en GNU Bison en modo GLR. Tiene un conflicto de reducción/reducción, por lo que activé el modo GLR, esperando que dividiera el analizador sintáctico y procediera a descubrir qué análisis funcionan. Pero no lo hace:
%{
#include <stdio.h>
%}
%glr-parser
%start start
%%
/* Con la entrada:
({}=0)
el analizador sintáctico debería dividirse.
*/
start: AssignmentExpressionNB '\n';
AssignmentExpressionNB:
PrimaryExpressionNB
| PrimaryExpressionNB '=' AssignmentExpression
;
AssignmentExpression:
PrimaryExpression /* This one will be rejected fast */
| ObjectAssignmentPattern '=' AssignmentExpression /* This must kept. */
| PrimaryExpression '=' AssignmentExpression /* This must also kept. */
;
PrimaryExpressionNB:
'0'
| '(' PrimaryExpression ')' { $$ = $2; }
;
PrimaryExpression:
'{' '}' { $$= 42; }
| PrimaryExpressionNB { $$ = $1; }
;
ObjectAssignmentPattern: '{' '}';
%%
void yyerror(const char* msg) { printf("%s\n", msg); }
int yylex () {
int c;
while ((c = getchar ()) == ' ' || c == '\t');
return c == EOF ? 0 : c;
}
int main (int argc, char** argv) {
yydebug=1;
return yyparse();
}
Lamentablemente, no se divide, sino que simplemente reduce por la primera alternativa de AssignmentExpression {} a PrimaryExpression y luego tiene un error de sintaxis:
Starting parse
Entering state 0
Reading a token
({}=0)
Next token is token ‘(‘ ()
Shifting token ‘(‘ ()
Entering state 2
Reading a token
Next token is token ‘{‘ ()
Shifting token ‘{‘ ()
Entering state 6
Reading a token
Next token is token ‘}’ ()
Shifting token ‘}’ ()
Entering state 12
Reducing stack 0 by rule 9 (line 34):
$1 = token ‘{‘ ()
$2 = token ‘}’ ()
-> $$ = nterm PrimaryExpression ()
Entering state 8
Reading a token
Next token is token ‘=’ ()
syntax error
Error: popping nterm PrimaryExpression ()
Error: popping token ‘(‘ ()
Cleanup: discarding lookahead token ‘=’ ()
Pensé que GNU Bison debería dividir el análisis ahora para determinar cuál funciona (y si hay varios análisis exitosos, permitirme elegir cuál).
¿Hay alguna forma de obtener las alternativas?</stdio.h>
davy.ai
Sí, hay una manera de obtener alternativas usando el modo GLR en GNU Bison. El modo GLR está diseñado para manejar conflictos en la gramática, como conflictos de reducción/reducción, creando múltiples árboles de análisis y permitiendo al usuario elegir el correcto.
Para habilitar el modo GLR en GNU Bison, usamos la directiva
%glr-parser
al comienzo del archivo de gramática. En nuestro ejemplo, ya hemos habilitado el modo GLR.Sin embargo, para aprovechar el modo GLR, necesitamos modificar nuestras acciones de análisis para manejar los árboles de análisis creados por el algoritmo GLR. Específicamente, necesitamos usar la función
yyerrok
para indicar a Bison que continúe analizando después de encontrar un error de sintaxis, y la macroYYERROR
para señalar un error de sintaxis en el analizador.En nuestro ejemplo, podemos modificar las acciones del analizador para la regla
AssignmentExpression
de la siguiente manera:Aquí, hemos agregado un bloque de código al final de la regla
AssignmentExpression
que se ejecuta si se encuentra un error de sintaxis. Este bloque de código utiliza la funciónyyget_expected_tokens
para obtener las alternativas para el estado de análisis actual y las imprime en la consola.Ahora, cuando ejecutamos el analizador con la entrada
( {}=0 )
, obtenemos la siguiente salida:Esto nos indica que hay dos posibles árboles de análisis para la entrada
( {}=0 )
: uno en el que{}
se interpreta como un objeto vacío ({}
) y otro en el que se interpreta como un error de sintaxis. Podemos elegir el árbol de análisis correcto en función de nuestro conocimiento de la sintaxis de la entrada.