#! /bin/sh yaccs="bison byacc" grammars="error-1 error-2 error-3" ###################################################################### # Demonstrating that the error action is not triggered. cat >error-1.y < #include #include #define YYERROR_VERBOSE 1 #define YYDEBUG 1 static int yylex (void); static void yyerror (const char *msg); %} %% prog: 'x' 'y' 'z' ';' | r error ';' { printf ("* error action *\n"); } | q ';' ; r: 'x'; q: 'x'; %% static int yylex (void) { static const int input[] = { 'x', 'y', 'z', 'x', ';' }; static int counter = 0; if (counter < (sizeof(input) / sizeof (input[0]))) return input[counter++]; else return EOF; } static void yyerror (const char *msg) { fprintf (stderr, "%s\n", msg); } int main (void) { yydebug = !!getenv ("YYDEBUG"); return yyparse (); } EOF ###################################################################### # Same as above, except that because the error action is *not* merged # in the default action (q is first here, before r, contrary to the # previous grammar), the error action *is* triggered. cat >error-2.y < #include #include #define YYERROR_VERBOSE 1 #define YYDEBUG 1 static int yylex (void); static void yyerror (const char *msg); %} %% prog: 'x' 'y' 'z' ';' | r error ';' { printf ("* error action *\n"); } | q ';' ; q: 'x'; r: 'x'; %% static int yylex (void) { static const int input[] = { 'x', 'y', 'z', 'x', ';' }; static int counter = 0; if (counter < (sizeof(input) / sizeof (input[0]))) return input[counter++]; else return EOF; } static void yyerror (const char *msg) { fprintf (stderr, "%s\n", msg); } int main (void) { yydebug = !!getenv ("YYDEBUG"); return yyparse (); } EOF ###################################################################### # We do recover from the error, but the error action is not triggered. cat >error-3.y < #include #include #define YYERROR_VERBOSE 1 #define YYDEBUG 1 static int yylex (void); static void yyerror (const char *msg); %} %% prog: 'x' 'y' 'z' ';' { printf ("'x' 'y' 'z' ';'\n"); } | r error ';' { printf ("r error ';'\n"); } | r 'x' ';' { printf ("r 'x' ';'\n"); } | q ';' { printf ("q ';'\n"); } | q '.' { printf ("q '.'\n"); } ; q: 'x'; r: 'x'; %% static int yylex (void) { static const int input[] = { 'x', 'y', 'x', ';' }; static int counter = 0; if (counter < (sizeof(input) / sizeof (input[0]))) return input[counter++]; else return EOF; } static void yyerror (const char *msg) { fprintf (stderr, "%s\n", msg); } int main (void) { yydebug = !!getenv ("YYDEBUG"); return yyparse (); } EOF for yacc in $yaccs do if test $yacc = bison; then opt="-y" else opt= fi for grammar in $grammars do $yacc $opt $grammar.y mv y.tab.c $grammar.$yacc.c gcc $grammar.$yacc.c -o $grammar.$yacc echo "== $grammar.$yacc" ./$grammar.$yacc done done