X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/dd5611579b3978eff5c4aa22dc8459b8f53c2fc0..eb46d61f4dacd21975156938eb83432dcc4ad720:/tests/calc.at diff --git a/tests/calc.at b/tests/calc.at index f0e30ad3..bd52d7cb 100644 --- a/tests/calc.at +++ b/tests/calc.at @@ -33,9 +33,80 @@ # Don't call this macro directly, because it contains some occurrences # of `$1' etc. which will be interpreted by m4. So you should call it # with $1, $2, and $3 as arguments, which is what AT_DATA_CALC_Y does. +# +# When %defines is not passed, generate a single self-contained file. +# Otherwise, generate three: calc.y with the parser, calc-lex.c with +# the scanner, and calc-main.c with "main()". This is in order to +# stress the use of the generated parser header. To avoid code +# duplication, AT_CALC_LEX and AT_CALC_MAIN contain the body of these +# two later files. m4_define([_AT_DATA_CALC_Y], [m4_if([$1$2$3], $[1]$[2]$[3], [], [m4_fatal([$0: Invalid arguments: $@])])dnl + +m4_pushdef([AT_CALC_MAIN], +[#include /* abort */ +#if HAVE_UNISTD_H +# include +#else +# undef alarm +# define alarm(seconds) /* empty */ +#endif + +AT_SKEL_CC_IF([[ +/* A C++ ]AT_NAME_PREFIX[parse that simulates the C signature. */ +int +]AT_NAME_PREFIX[parse (]AT_PARAM_IF([semantic_value *result, int *count]))[ +{ + ]AT_NAME_PREFIX[::parser parser]AT_PARAM_IF([ (result, count)])[; +#if YYDEBUG + parser.set_debug_level (1); +#endif + return parser.parse (); +} +]])[ + +semantic_value global_result = 0; +int global_count = 0; + +/* A C main function. */ +int +main (int argc, const char **argv) +{ + semantic_value result = 0; + int count = 0; + int status; + + /* This used to be alarm (10), but that isn't enough time for + a July 1995 vintage DEC Alphastation 200 4/100 system, + according to Nelson H. F. Beebe. 100 seconds is enough. */ + alarm (100); + + if (argc == 2) + input = fopen (argv[1], "r"); + else + input = stdin; + + if (!input) + { + perror (argv[1]); + return 3; + } + +]AT_SKEL_CC_IF([], [m4_bmatch([$4], [%debug], +[ ]AT_NAME_PREFIX[debug = 1;])])[ + status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count]])[); + if (fclose (input)) + perror ("fclose"); + if (global_result != result) + abort (); + if (global_count != count) + abort (); + return status; +} +]]) + + m4_pushdef([AT_CALC_LEX], [[#include @@ -198,7 +269,9 @@ AT_SKEL_CC_IF( { #include /* The input. */ -extern FILE *input;]AT_SKEL_CC_IF([[ +extern FILE *input; +extern semantic_value global_result; +extern int global_count;]AT_SKEL_CC_IF([[ #ifndef YYLTYPE # define YYLTYPE ]AT_NAME_PREFIX[::parser::location_type #endif @@ -207,19 +280,11 @@ extern FILE *input;]AT_SKEL_CC_IF([[ %code { -#include +#include #include -#if HAVE_UNISTD_H -# include -#else -# undef alarm -# define alarm(seconds) /* empty */ -#endif #define USE(Var) FILE *input; -static semantic_value global_result = 0; -static int global_count = 0; static int power (int base, int exponent); ]AT_SKEL_CC_IF(, @@ -240,7 +305,7 @@ int yylex (]AT_LEX_FORMALS[); are stored in a union, from which objects with constructors are excluded in C++. */ %initial-action { - @$.initialize (0); + @$.initialize (); } ])])[ @@ -249,7 +314,7 @@ int yylex (]AT_LEX_FORMALS[); %token NUM "number" %type exp -%nonassoc '=' /* comparison */ +%nonassoc '=' /* comparison */ %left '-' '+' %left '*' '/' %left NEG /* negation--unary minus */ @@ -288,6 +353,16 @@ exp: ; %% +static int +power (int base, int exponent) +{ + int res = 1; + assert (0 <= exponent); + for (/* Niente */; exponent; --exponent) + res *= base; + return res; +} + ]AT_SKEL_CC_IF( [AT_LOCATION_TYPE_IF([[ std::ostream& @@ -309,17 +384,6 @@ AT_NAME_PREFIX::parser::error (const location_type& l, const std::string& m) (void) l; std::cerr << AT_LOCATION_IF([l << ": " << ])m << std::endl; } - -/* A C++ yyparse that simulates the C signature. */ -int -yyparse (AT_PARAM_IF([semantic_value *result, int *count])) -{ - AT_NAME_PREFIX::parser parser[]AT_PARAM_IF([ (result, count)]); -#if YYDEBUG - parser.set_debug_level (1); -#endif - return parser.parse (); -} ], [/* A C error reporting function. */ static void @@ -333,67 +397,29 @@ AT_YYERROR_SEES_LOC_IF([ AT_LOC_FIRST_LINE, AT_LOC_FIRST_COLUMN); if (AT_LOC_FIRST_LINE != AT_LOC_LAST_LINE) fprintf (stderr, "-%d.%d", - AT_LOC_LAST_LINE, AT_LOC_LAST_COLUMN - 1); + AT_LOC_LAST_LINE, AT_LOC_LAST_COLUMN - 1); else if (AT_LOC_FIRST_COLUMN != AT_LOC_LAST_COLUMN - 1) fprintf (stderr, "-%d", - AT_LOC_LAST_COLUMN - 1); + AT_LOC_LAST_COLUMN - 1); fprintf (stderr, ": ");]) fprintf (stderr, "%s\n", s); }])[ -]AT_DEFINES_IF(, [AT_CALC_LEX])[ - -static int -power (int base, int exponent) -{ - int res = 1; - assert (0 <= exponent); - for (/* Niente */; exponent; --exponent) - res *= base; - return res; -} - - -/* A C main function. */ -int -main (int argc, const char **argv) -{ - semantic_value result = 0; - int count = 0; - int status; - - /* This used to be alarm (10), but that isn't enough time for - a July 1995 vintage DEC Alphastation 200 4/100 system, - according to Nelson H. F. Beebe. 100 seconds is enough. */ - alarm (100); - - if (argc == 2) - input = fopen (argv[1], "r"); - else - input = stdin; - - if (!input) - { - perror (argv[1]); - return 3; - } - -]AT_SKEL_CC_IF([], [m4_bmatch([$4], [%debug], -[ yydebug = 1;])])[ - status = yyparse (]AT_PARAM_IF([[&result, &count]])[); - if (fclose (input)) - perror ("fclose"); - if (global_result != result) - abort (); - if (global_count != count) - abort (); - return status; -} +]AT_DEFINES_IF([], +[AT_CALC_LEX +AT_CALC_MAIN])[ ]]) + AT_DEFINES_IF([AT_DATA_SOURCE([[calc-lex.c]AT_SKEL_CC_IF([[c]])], [[#include "calc.h]AT_SKEL_CC_IF([[h]])[" -]AT_CALC_LEX])]) +]AT_CALC_LEX]) +AT_DATA_SOURCE([[calc-main.c]AT_SKEL_CC_IF([[c]])], +[[#include "calc.h]AT_SKEL_CC_IF([[h]])[" + +]AT_CALC_MAIN]) +]) +m4_popdef([AT_CALC_MAIN]) m4_popdef([AT_CALC_LEX]) ])# _AT_DATA_CALC_Y @@ -492,21 +518,20 @@ AT_CHECK([cat stderr], 0, [expout]) ]) -# AT_CHECK_CALC([BISON-OPTIONS, [EXPECTED-TO-FAIL]]) -# -------------------------------------------------- +# AT_CHECK_CALC([BISON-OPTIONS]) +# ------------------------------ # Start a testing chunk which compiles `calc' grammar with # BISON-OPTIONS, and performs several tests over the parser. -# However, if EXPECTED-TO-FAIL is nonempty, this test is expected to fail. m4_define([AT_CHECK_CALC], -[# We use integers to avoid dependencies upon the precision of doubles. -AT_SETUP([Calculator $1]) +[m4_ifval([$2], [m4_fatal([$0: expected a single argument])]) -m4_ifval([$2], [AT_CHECK([exit 77])]) +# We use integers to avoid dependencies upon the precision of doubles. +AT_SETUP([Calculator $1]) AT_BISON_OPTION_PUSHDEFS([$1]) AT_DATA_CALC_Y([$1]) -AT_FULL_COMPILE([calc], [AT_DEFINES_IF([[lex]])]) +AT_FULL_COMPILE([calc], AT_DEFINES_IF([[lex], [main]])) # Test the priorities. _AT_CHECK_CALC([$1],