Ich lese ein "Compiler Konstruktion, Prinzipien und Praxis" Buch von Kenneth Louden und versuchen, Fehlerkorrektur in Yacc zu verstehen.spezifische Fehlerbeseitigung in Bison/Yacc
Der Autor gibt ein Beispiel mit dem folgenden Grammatik:
%{
#include <stdio.h>
#include <ctype.h>
int yylex();
int yyerror();
%}
%%
command : exp { printf("%d\n", $1); }
; /* allows printing of the result */
exp : exp '+' term { $$ = $1 + $3; }
| exp '-' term { $$ = $1 - $3; }
| term { $$ = $1; }
;
term : term '*' factor { $$ = $1 * $3; }
| factor { $$ = $1; }
;
factor : NUMBER { $$ = $1; }
| '(' exp ')' { $$ = $2; }
;
%%
int main() {
return yyparse();
}
int yylex() {
int c;
/* eliminate blanks*/
while((c = getchar()) == ' ');
if (isdigit(c)) {
ungetc(c, stdin);
scanf("%d\n", &yylval);
return (NUMBER);
}
/* makes the parse stop */
if (c == '\n') return 0;
return (c);
}
int yyerror(char * s) {
fprintf(stderr, "%s\n", s);
return 0;
} /* allows for printing of an error message */
Welche der folgenden Zustandstabelle erzeugt (nachfolgend als Tabelle 5.11 später)
Zahlen in den Kürzungen entsprechen folgenden Produktionen:
(1) command : exp.
(2) exp : exp + term.
(3) exp : exp - term.
(4) exp : term.
(5) term : term * factor.
(6) term : factor.
(7) factor : NUMBER.
(8) factor : (exp).
Dann gibt Dr. Louden das folgende Beispiel:
Überlegen Sie, was, wenn ein Fehler-Produktion auf die yacc Definition wurden hinzugefügt hapen würde
factor : NUMBER {$$ = $1;} | '(' exp ')' {$$=$2;} | error {$$ = 0;} ;
erste fehlerhafte Eingabe Betrachten 2 ++ 3 als Im vorherigen Beispiel (Wir verwenden weiterhin Tabelle 5.11, obwohl die zusätzliche Fehlererzeugung zu einer leicht abweichenden Tabelle führt.) Wie zuvor erreicht der Parser den folgenden Punkt:
parsing stack input $0 exp 2 + 7 +3$
Nun ist die Fehler-Produktion für
factor
wird vorsehen, dass Fehler a Rechts Vorgriffs-in Zustand 7 und Fehler sofort verschoben auf dem Stapel sein und zufactor
reduziert, 0 den Wert verursacht zurückgegeben werden . Nun hat der Parser den folgenden Punkt erreicht:parsing stack input $0 exp 2 + 7 factor 4 +3$
Dies ist eine normale Situation, und der Parser wird weiterhin normalerweise bis zum Ende auszuführen. Der Effekt ist der Eingang als 2 + 0 + 3 zu interpretieren - die 0 zwischen den beiden + Symbole gibt es, weil dort die Fehler pseudotoken eingeführt wird, und durch die Wirkung für den Fehler Produktion, Fehler wird als äquivalent zu einem Faktor mit dem Wert betrachtet 0.
Meine Frage ist ganz einfach:
wie er, indem man die Grammatik wußte, dass, um von diesem spezifischen zu erholen Fehler (2 ++ 3) Er muss einen Fehler Pseudotoken zur factor
Produktion hinzufügen? Gibt es einen einfachen Weg, es zu tun? Oder der einzige Weg, dies zu tun ist, mehrere Beispiele mit der Zustandstabelle auszuarbeiten und zu erkennen, dass dieser spezielle Fehler in diesem gegebenen Zustand auftritt und daher, wenn ich einen Fehler Pseudotoken zu einer bestimmten spezifischen Produktion hinzufüge, wird der Fehler behoben .
Jede Hilfe wird geschätzt.
Danke für die Antwort. Aber ich bin immer noch nicht klar. Lass mich die Frage neu formulieren. Sagen wir, ich habe eine Aufgabe, um dieses spezielle Problem zu lösen, d. H. Eine Eingabe von ** 2 ++ 3 ** oder allgemeiner gesagt ** NUMMER + NUMMER **. Woher weiß ich das, wenn ich mir die Grammatik anschaue, die ich benötige, um einen "Fehler" -Pseudoknoten in die "Faktor" -Produktion einzufügen? – flashburn
@flashburn: Ich entschuldige mich dafür, dass Sie Ihre Frage vollständig falsch gelesen haben. Ich habe eine neue Antwort geschrieben, die hilfreicher sein könnte, aber die allgemeine Antwort lautet: "Es ist eine Kunst, keine Wissenschaft." (was in der Antwort enthalten ist, aber vielleicht nicht genug hervorgehoben wird.) – rici