X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/82c035a8238ea0f6a7cdb8d937ba97534ab620dd..283f1e64820fc8f498a4e9ef5128a347b5876039:/tests/actions.at diff --git a/tests/actions.at b/tests/actions.at index 78531fcd..2e707bde 100644 --- a/tests/actions.at +++ b/tests/actions.at @@ -31,22 +31,25 @@ AT_SETUP([Mid-rule actions]) AT_DATA([[input.y]], [[%{ -#include -#include -static void yyerror (const char *msg); -static int yylex (void); +# include +# include + static void yyerror (const char *msg); + static int yylex (void); +# define YYDEBUG 1 +# define YYERROR_VERBOSE 1 %} %% -exp: { printf ("0\n"); } - '1' { printf ("1\n"); } - '2' { printf ("2\n"); } - '3' { printf ("3\n"); } - '4' { printf ("4\n"); } - '5' { printf ("5\n"); } - '6' { printf ("6\n"); } - '7' { printf ("7\n"); } - '8' { printf ("8\n"); } - '9' { printf ("9\n"); } +exp: { putchar ('0'); } + '1' { putchar ('1'); } + '2' { putchar ('2'); } + '3' { putchar ('3'); } + '4' { putchar ('4'); } + '5' { putchar ('5'); } + '6' { putchar ('6'); } + '7' { putchar ('7'); } + '8' { putchar ('8'); } + '9' { putchar ('9'); } + { putchar ('\n'); } ; %% static int @@ -69,19 +72,297 @@ main (void) } ]]) -AT_CHECK([bison input.y -d -v -o input.c]) -AT_CHECK([$CC $CFLAGS $CPPFLAGS input.c -o input], 0, [], [ignore]) -AT_CHECK([input], 0, -[[0 -1 -2 -3 -4 -5 -6 -7 -8 -9 +AT_CHECK([bison -d -v -o input.c input.y]) +AT_COMPILE([input]) +AT_PARSER_CHECK([./input], 0, +[[0123456789 +]]) + +AT_CLEANUP + + + +## ---------------- ## +## Exotic Dollars. ## +## ---------------- ## + +AT_SETUP([Exotic Dollars]) + +AT_DATA([[input.y]], +[[%{ +# include +# include + static void yyerror (const char *msg); + static int yylex (void); +# define YYDEBUG 1 +# define YYERROR_VERBOSE 1 +%} + +%union +{ + int val; +}; + +%type a_1 a_2 a_5 + sum_of_the_five_previous_values + +%% +exp: a_1 a_2 { $$ = 3; } { $$ = $3 + 1; } a_5 + sum_of_the_five_previous_values + { + printf ("%d\n", $6); + } +; +a_1: { $$ = 1; }; +a_2: { $$ = 2; }; +a_5: { $$ = 5; }; + +sum_of_the_five_previous_values: + { + $$ = $0 + $-1 + $-2 + $-3 + $-4; + } +; + +%% +static int +yylex (void) +{ + return EOF; +} + +static void +yyerror (const char *msg) +{ + fprintf (stderr, "%s\n", msg); +} + +int +main (void) +{ + return yyparse (); +} +]]) + +AT_CHECK([bison -d -v -o input.c input.y]) +AT_COMPILE([input]) +AT_PARSER_CHECK([./input], 0, +[[15 +]]) + +AT_CLEANUP + + + +## -------------------------- ## +## Printers and Destructors. ## +## -------------------------- ## + +# _AT_CHECK_PRINTER_AND_DESTRUCTOR($1, $2, $3, BISON-DIRECTIVE) +# ------------------------------------------------------------- +m4_define([_AT_CHECK_PRINTER_AND_DESTRUCTOR], +[m4_if([$1$2$3], $[1]$[2]$[3], [], + [m4_fatal([$0: Invalid arguments: $@])])dnl + +AT_SETUP([Printers and Destructors: $4]) + +# Make sure complex $n work. + +AT_DATA([[input.y]], +[[$4 +%{ +#include +#include +#include + +static int yylex (void); +static void yyerror (const char *msg); +%} +%error-verbose +%debug +%verbose +%locations +%union +{ + int ival; +} +%type 'x' thing line input + +%printer { fprintf (yyout, "%d@%d", $$, @$.first_line); } + input line thing 'x' + +%destructor + { fprintf (stdout, "Freeing nterm input (%d@%d)\n", $$, @$.first_line); } + input + +%destructor + { fprintf (stdout, "Freeing nterm line (%d@%d)\n", $$, @$.first_line); } + line + +%destructor + { fprintf (stdout, "Freeing nterm thing (%d@%d)\n", $$, @$.first_line); } + thing + +%destructor + { fprintf (stdout, "Freeing token 'x' (%d@%d)\n", $$, @$.first_line); } + 'x' + +%% +input: + /* Nothing. */ + { + $$ = 0; + printf ("input(%d@%d): /* Nothing */';'\n", $$, @$.first_line); + } +| line input /* Right recursive to load the stack so that popping at + EOF can be exercised. */ + { + $$ = 2; + printf ("input(%d@%d): line(%d@%d) input(%d@%d)';'\n", + $$, @$.first_line, $1, @1.first_line, $2, @2.first_line); + } +; + +line: + thing thing thing ';' + { + $$ = $1; + printf ("line(%d@%d): thing(%d@%d) thing(%d@%d) thing(%d@%d) ';'\n", + $$, @$.first_line, $1, @1.first_line, $2, @2.first_line, + $3, @3.first_line); + } +| thing thing ';' + { + $$ = $1; + printf ("line(%d@%d): thing(%d@%d) thing(%d@%d) ';'\n", + $$, @$.first_line, $1, @1.first_line, $2, @2.first_line); + } +| thing ';' + { + $$ = $1; + printf ("line(%d@%d): thing(%d@%d) ';'\n", + $$, @$.first_line, $1, @1.first_line); + } +| error ';' + { + $$ = -1; + printf ("line(%d@%d): error(@%d) ';'\n", + $$, @$.first_line, @1.first_line); + } +; + +thing: + 'x' + { + $$ = $1; + printf ("thing(%d@%d): 'x'(%d@%d)\n", + $$, @$.first_line, $1, @1.first_line); + } +; +%% +static int +yylex (void) +{ + static const unsigned int input[] = + { + /* Exericise the discarding of stack top and input until `error' + can be reduced. */ + 'x', 'x', 'x', 'x', 'x', 'x', ';', + + /* Load the stack and provoke an error that cannot be caught by + the grammar, to check that the stack is cleared. */ + 'x', 'x', ';', + 'x', ';', + 'y' + }; + static unsigned int counter = 0; + + if (counter < (sizeof(input) / sizeof (input[0]))) + { + yylval.ival = counter; + /* As in BASIC, line numbers go from 10 to 10. */ + yylloc.first_line = 10 * counter; + printf ("sending: '%c' (value = %d, line %d)\n", + input[counter], yylval.ival, yylloc.first_line); + return (int) input[counter++]; + } + else + { + printf ("sending: EOF\n"); + return EOF; + } +} + +static void +yyerror (const char *msg) +{ + fprintf (stdout, "%d: %s\n", yylloc.first_line, msg); +} + +int +main (void) +{ + yydebug = !!getenv ("YYDEBUG"); + if (yyparse ()) + { + fprintf (stdout, "Parsing FAILED.\n"); + exit (1); + } + fprintf (stdout, "Successful parse.\n"); + return 0; +} +]]) + +AT_CHECK([bison -o input.c input.y]) +AT_COMPILE([input]) +AT_PARSER_CHECK([./input], 1, +[[sending: 'x' (value = 0, line 0) +thing(0@0): 'x'(0@0) +sending: 'x' (value = 1, line 10) +thing(1@10): 'x'(1@10) +sending: 'x' (value = 2, line 20) +thing(2@20): 'x'(2@20) +sending: 'x' (value = 3, line 30) +30: parse error, unexpected 'x', expecting ';' +Freeing nterm thing (2@20) +Freeing nterm thing (1@10) +Freeing nterm thing (0@0) +Freeing token 'x' (3@30) +sending: 'x' (value = 4, line 40) +Freeing token 'x' (4@40) +sending: 'x' (value = 5, line 50) +Freeing token 'x' (5@50) +sending: ';' (value = 6, line 60) +line(-1@50): error(@50) ';' +sending: 'x' (value = 7, line 70) +thing(7@70): 'x'(7@70) +sending: 'x' (value = 8, line 80) +thing(8@80): 'x'(8@80) +sending: ';' (value = 9, line 90) +line(7@70): thing(7@70) thing(8@80) ';' +sending: 'x' (value = 10, line 100) +thing(10@100): 'x'(10@100) +sending: ';' (value = 11, line 110) +line(10@100): thing(10@100) ';' +sending: 'y' (value = 12, line 120) +120: parse error, unexpected $undefined, expecting $end or 'x' +sending: EOF +Freeing nterm line (10@100) +Freeing nterm line (7@70) +Freeing nterm line (-1@50) +Parsing FAILED. ]]) AT_CLEANUP +]) + + +# AT_CHECK_PRINTER_AND_DESTRUCTOR([BISON-OPTIONS]) +# ------------------------------------------------ +# Produce `calc.y'. +m4_define([AT_CHECK_PRINTER_AND_DESTRUCTOR], +[_AT_CHECK_PRINTER_AND_DESTRUCTOR($[1], $[2], $[3], [$1]) +]) + + +AT_CHECK_PRINTER_AND_DESTRUCTOR() +AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser])