X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/63d0fb9ce4bcf5069bd17f43348705ee03a562a9..9c2b381f793545f0fe78b8dfeb86aa8d02940953:/tests/calc.at diff --git a/tests/calc.at b/tests/calc.at index 63c3233f..aade61cc 100644 --- a/tests/calc.at +++ b/tests/calc.at @@ -1,5 +1,5 @@ # Checking the output filenames. -*- Autotest -*- -# Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. +# Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -50,57 +50,33 @@ AT_DATA_GRAMMAR([calc.y], extern void perror (const char *s); /* Exercise pre-prologue dependency to %union. */ -typedef int value_t; +typedef int value; -static value_t global_result = 0; +static value global_result = 0; static int global_count = 0; +]AT_LALR1_CC_IF([typedef yy::Location YYLTYPE;])[ %} /* Exercise %union. */ %union { - value_t ival; + value ival; }; %{ -#if YYPURE -# define LOC (*yylloc) -# define VAL (*yylval) -#else -# define LOC (yylloc) -# define VAL (yylval) -#endif - -#define YYLLOC_FORMAL ]AT_LOCATION_IF([, YYLTYPE *yylloc])[ -#define YYLLOC_ARG ]AT_LOCATION_IF([, yylloc])[ -#define USE_YYLLOC ]AT_LOCATION_IF([(void) yylloc;])[ - -#if YYPURE -# define LEX_FORMALS YYSTYPE *yylval YYLLOC_FORMAL -# define LEX_ARGS yylval YYLLOC_ARG -# define USE_LEX_ARGS (void) yylval; USE_YYLLOC -# define LEX_PRE_FORMALS LEX_FORMALS, -# define LEX_PRE_ARGS LEX_ARGS, -#else -# define LEX_FORMALS void -# define LEX_PRE_FORMALS -# define LEX_ARGS -# define LEX_PRE_ARGS -# define USE_LEX_ARGS -#endif - static int power (int base, int exponent); +]AT_LALR1_CC_IF([], [ /* yyerror receives the location if: - %location & %pure & %glr - %location & %pure & %yacc & %parse-param. */ -static void yyerror (]AT_YYERROR_ARG_LOC_IF([YYLTYPE *yylloc, ])[ - ]AT_PARAM_IF([value_t *result, int *count, ])[ +static void yyerror (AT_YYERROR_ARG_LOC_IF([YYLTYPE *yylloc, ]) + AT_PARAM_IF([value *result, int *count, ]) const char *s - ); -static int yylex (LEX_FORMALS); -static int yygetc (LEX_FORMALS); -static void yyungetc (LEX_PRE_FORMALS int c); + );])[ +static int yylex (]AT_LEX_FORMALS[); +static int yygetc (]AT_LEX_FORMALS[); +static void yyungetc (]AT_LEX_PRE_FORMALS[ int c); %} /* Bison Declarations */ @@ -141,82 +117,116 @@ exp: | '-' exp %prec NEG { $$ = -$2; } | exp '^' exp { $$ = power ($1, $3); } | '(' exp ')' { $$ = $2; } -| '(' error ')' { $$ = 0; } +| '(' error ')' { $$ = 1111; } +| '!' { YYERROR; } ; %% /* The input. */ static FILE *yyin; -static void -yyerror (]AT_YYERROR_ARG_LOC_IF([YYLTYPE *yylloc, ])[ - ]AT_PARAM_IF([value_t *result, int *count, ])[ - const char *s - ) +]AT_LALR1_CC_IF( +[/* Currently, print_ is required in C++. */ +void +yy::Parser::print_ () { -]AT_PARAM_IF([(void) result; (void) count; ])[ -]AT_YYERROR_SEES_LOC_IF([ - fprintf (stderr, "%d.%d-%d.%d: ", - LOC.first_line, LOC.first_column, - LOC.last_line, LOC.last_column); -])[ - fprintf (stderr, "%s\n", s); +AT_LOCATION_IF([ + std::cerr << location;]) } +/* A C++ error reporting function. */ +void +yy::Parser::error_ () +{ + std::cerr << AT_LOCATION_IF([location << ": " << ])message << std::endl; +} + +int +yyparse (void) +{ + yy::Parser parser = yy::Parser (!!YYDEBUG[]AT_LOCATION_IF([, + yy::Location::Location ()])); + return parser.parse (); +} +], +[static void +yyerror (AT_YYERROR_ARG_LOC_IF([YYLTYPE *yylloc, ]) + AT_PARAM_IF([value *result, int *count, ]) + const char *s) +{ +AT_PARAM_IF([(void) result; (void) count;]) +AT_YYERROR_SEES_LOC_IF([ + fprintf (stderr, "%d.%d", + 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); + else if (AT_LOC.first_column != AT_LOC.last_column - 1) + fprintf (stderr, "-%d", + AT_LOC.last_column - 1); + fprintf (stderr, ": ");]) + fprintf (stderr, "%s\n", s); +}])[ + ]AT_LOCATION_IF([ static YYLTYPE last_yylloc; ])[ static int -yygetc (LEX_FORMALS) +yygetc (]AT_LEX_FORMALS[) { int res = getc (yyin); - USE_LEX_ARGS; + ]AT_USE_LEX_ARGS[; ]AT_LOCATION_IF([ - last_yylloc = LOC; + last_yylloc = AT_LOC; if (res == '\n') { - LOC.last_line++; - LOC.last_column = 1; +AT_LALR1_CC_IF( +[ AT_LOC.end.line++; + AT_LOC.end.column = 0;], +[ AT_LOC.last_line++; + AT_LOC.last_column = 0;]) } else - LOC.last_column++; +AT_LALR1_CC_IF( +[ AT_LOC.end.column++;], +[ AT_LOC.last_column++;]) ])[ return res; } static void -yyungetc (LEX_PRE_FORMALS int c) +yyungetc (]AT_LEX_PRE_FORMALS[ int c) { - USE_LEX_ARGS; + ]AT_USE_LEX_ARGS[; ]AT_LOCATION_IF([ /* Wrong when C == `\n'. */ - LOC = last_yylloc; + AT_LOC = last_yylloc; ])[ ungetc (c, yyin); } static int -read_signed_integer (LEX_FORMALS) +read_signed_integer (]AT_LEX_FORMALS[) { - int c = yygetc (LEX_ARGS); + int c = yygetc (]AT_LEX_ARGS[); int sign = 1; int n = 0; - USE_LEX_ARGS; + ]AT_USE_LEX_ARGS[; if (c == '-') { - c = yygetc (LEX_ARGS); + c = yygetc (]AT_LEX_ARGS[); sign = -1; } while (isdigit (c)) { n = 10 * n + (c - '0'); - c = yygetc (LEX_ARGS); + c = yygetc (]AT_LEX_ARGS[); } - yyungetc (LEX_PRE_ARGS c); + yyungetc (]AT_LEX_PRE_ARGS[ c); return sign * n; } @@ -230,7 +240,7 @@ read_signed_integer (LEX_FORMALS) `---------------------------------------------------------------*/ static int -yylex (LEX_FORMALS) +yylex (]AT_LEX_FORMALS[) { static int init = 1; int c; @@ -238,31 +248,34 @@ yylex (LEX_FORMALS) if (init) { init = 0; -]AT_LOCATION_IF([ - LOC.last_column = 1; - LOC.last_line = 1; -])[ +]AT_LALR1_CC_IF([], +[AT_LOCATION_IF([ + AT_LOC.last_column = 0; + AT_LOC.last_line = 1; +])])[ } -]AT_LOCATION_IF([ - LOC.first_column = LOC.last_column; - LOC.first_line = LOC.last_line; -])[ +]AT_LOCATION_IF([AT_LALR1_CC_IF( +[ AT_LOC.begin = AT_LOC.end;], +[ AT_LOC.first_column = AT_LOC.last_column; + AT_LOC.first_line = AT_LOC.last_line; +])])[ /* Skip white space. */ - while ((c = yygetc (LEX_ARGS)) == ' ' || c == '\t') + while ((c = yygetc (]AT_LEX_ARGS[)) == ' ' || c == '\t') { -]AT_LOCATION_IF([ - LOC.first_column = LOC.last_column; - LOC.first_line = LOC.last_line; -])[ +]AT_LOCATION_IF([AT_LALR1_CC_IF( +[ AT_LOC.begin = AT_LOC.end;], +[ AT_LOC.first_column = AT_LOC.last_column; + AT_LOC.first_line = AT_LOC.last_line; +])])[ } /* process numbers */ if (c == '.' || isdigit (c)) { - yyungetc (LEX_PRE_ARGS c); - VAL.ival = read_signed_integer (LEX_ARGS); + yyungetc (]AT_LEX_PRE_ARGS[ c); + ]AT_VAL[.ival = read_signed_integer (]AT_LEX_ARGS[); return NUM; } @@ -285,10 +298,11 @@ power (int base, int exponent) return res; } + int main (int argc, const char **argv) { - value_t result = 0; + value result = 0; int count = 0; int status; @@ -303,9 +317,8 @@ main (int argc, const char **argv) exit (1); } -#if YYDEBUG - yydebug = 1; -#endif +]AT_LALR1_CC_IF([], [m4_bmatch([$4], [%debug], +[ yydebug = 1;])])[ status = yyparse (]AT_PARAM_IF([&result, &count])[); if (global_result != result) abort (); @@ -421,14 +434,19 @@ AT_CHECK([cat stderr], 0, [expout]) m4_define([AT_CHECK_PUSHDEFS], [m4_if([$1$2], $[1]$[2], [], [m4_fatal([$0: Invalid arguments: $@])])dnl +m4_pushdef([AT_LALR1_CC_IF], +[m4_bmatch([$3], ["lalr1.cc"], [$1], [$2])]) +m4_pushdef([AT_GLR_IF], +[m4_bmatch([$3], [%glr-parser], [$1], [$2])]) +# Using yacc.c? +m4_pushdef([AT_YACC_IF], +[m4_bmatch([$3], [%glr-parser\|%skeleton], [$2], [$1])]) m4_pushdef([AT_PARAM_IF], [m4_bmatch([$3], [%parse-param], [$1], [$2])]) m4_pushdef([AT_LOCATION_IF], [m4_bmatch([$3], [%locations], [$1], [$2])]) m4_pushdef([AT_PURE_IF], [m4_bmatch([$3], [%pure-parser], [$1], [$2])]) -m4_pushdef([AT_GLR_IF], -[m4_bmatch([$3], [%glr-parser], [$1], [$2])]) m4_pushdef([AT_PURE_AND_LOC_IF], [m4_bmatch([$3], [%locations.*%pure-parser\|%pure-parser.*%locations], [$1], [$2])]) @@ -439,25 +457,65 @@ m4_pushdef([AT_GLR_OR_PARAM_IF], m4_pushdef([AT_YYERROR_ARG_LOC_IF], [AT_GLR_OR_PARAM_IF([AT_PURE_AND_LOC_IF([$1], [$2])], [$2])]) -# yyerror cannot see the locations if !glr & pure & !param. +# yyerror always sees the locations (when activated), except if +# yacc & pure & !param. m4_pushdef([AT_YYERROR_SEES_LOC_IF], -[AT_LOCATION_IF([AT_GLR_IF([$1], - [AT_PURE_IF([AT_PARAM_IF([$1], [$2])], - [$1])])], +[AT_LOCATION_IF([AT_YACC_IF([AT_PURE_IF([AT_PARAM_IF([$1], [$2])], + [$1])], + [$1])], [$2])]) + +# The interface is pure: either because %pure-parser, or because we +# are using the C++ parsers. +m4_pushdef([AT_PURE_LEX_IF], +[AT_PURE_IF([$1], + [AT_LALR1_CC_IF([$1], [$2])])]) + +AT_PURE_LEX_IF( +[m4_pushdef([AT_LOC], [(*yylloc)]) + m4_pushdef([AT_VAL], [(*yylval)]) + m4_pushdef([AT_LEX_FORMALS], + [YYSTYPE *yylval[]AT_LOCATION_IF([, YYLTYPE *yylloc])]) + m4_pushdef([AT_LEX_ARGS], + [yylval[]AT_LOCATION_IF([, yylloc])]) + m4_pushdef([AT_USE_LEX_ARGS], + [(void) yylval;AT_LOCATION_IF([(void) yylloc])]) + m4_pushdef([AT_LEX_PRE_FORMALS], + [AT_LEX_FORMALS, ]) + m4_pushdef([AT_LEX_PRE_ARGS], + [AT_LEX_ARGS, ]) +], +[m4_pushdef([AT_LOC], [(yylloc)]) + m4_pushdef([AT_VAL], [(yylval)]) + m4_pushdef([AT_LEX_FORMALS], [void]) + m4_pushdef([AT_LEX_ARGS], []) + m4_pushdef([AT_USE_LEX_ARGS], []) + m4_pushdef([AT_LEX_PRE_FORMALS], []) + m4_pushdef([AT_LEX_PRE_ARGS], []) ]) +])# AT_CALC_PUSHDEFS # AT_CALC_POPDEFS # --------------- m4_define([AT_CHECK_POPDEFS], -[m4_popdef([AT_YYERROR_SEES_LOC_IF]) +[m4_popdef([AT_LEX_PRE_ARGS]) +m4_popdef([AT_LEX_PRE_FORMALS]) +m4_popdef([AT_USE_LEX_ARGS]) +m4_popdef([AT_LEX_ARGS]) +m4_popdef([AT_LEX_FORMALS]) +m4_popdef([AT_VAL]) +m4_popdef([AT_LOC]) +m4_popdef([AT_PURE_LEX_IF]) +m4_popdef([AT_YYERROR_SEES_LOC_IF]) m4_popdef([AT_YYERROR_ARG_LOC_IF]) m4_popdef([AT_GLR_OR_PARAM_IF]) m4_popdef([AT_PURE_AND_LOC_IF]) -m4_popdef([AT_GLR_IF]) m4_popdef([AT_LOCATION_IF]) m4_popdef([AT_PARAM_IF]) +m4_popdef([AT_YACC_IF]) +m4_popdef([AT_GLR_IF]) +m4_popdef([AT_LALR1_CC_IF]) ]) @@ -478,7 +536,10 @@ AT_DATA_CALC_Y([$1]) AT_CHECK([bison -o calc.c calc.y], [0], [], []) -AT_COMPILE([calc]) +AT_LALR1_CC_IF( +[AT_CHECK([$CXX --version || exit 77], 0, ignore, ignore) +AT_COMPILE_CXX([calc])], +[AT_COMPILE([calc])]) # Test the priorities. _AT_CHECK_CALC([$1], @@ -499,30 +560,52 @@ _AT_CHECK_CALC([$1], # Some syntax errors. _AT_CHECK_CALC_ERROR([$1], [1], [0 0], [11], - [1.3-1.4: syntax error, unexpected "number"]) + [1.2: syntax error, unexpected "number"]) _AT_CHECK_CALC_ERROR([$1], [1], [1//2], [15], - [1.3-1.4: syntax error, unexpected '/', expecting "number" or '-' or '(']) + [1.2: syntax error, unexpected '/', expecting "number" or '-' or '(' or '!']) _AT_CHECK_CALC_ERROR([$1], [1], [error], [4], - [1.1-1.2: syntax error, unexpected $undefined, expecting "number" or '-' or '\n' or '(']) + [1.0: syntax error, unexpected $undefined]) _AT_CHECK_CALC_ERROR([$1], [1], [1 = 2 = 3], [22], - [1.7-1.8: syntax error, unexpected '=']) + [1.6: syntax error, unexpected '=']) _AT_CHECK_CALC_ERROR([$1], [1], [ +1], [14], - [2.1-2.2: syntax error, unexpected '+']) + [2.0: syntax error, unexpected '+']) # Exercise error messages with EOF: work on an empty file. _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null], [4], - [1.1-1.2: syntax error, unexpected "end of input", expecting "number" or '-' or '\n' or '(']) + [1.0: syntax error, unexpected "end of input"]) # Exercise the error token: without it, we die at the first error, -# hence be sure i. to have several errors, ii. to test the action -# associated to `error'. -_AT_CHECK_CALC_ERROR([$1], [0], [(1 ++ 2) + (0 0) = 1], [82], -[1.5-1.6: syntax error, unexpected '+', expecting "number" or '-' or '(' -1.15-1.16: syntax error, unexpected "number" -calc: error: 0 != 1]) - +# hence be sure to +# +# - have several errors which exercise different shift/discardings +# - (): nothing to pop, nothing to discard +# - (1 + 1 + 1 +): a lot to pop, nothing to discard +# - (* * *): nothing to pop, a lot to discard +# - (1 + 2 * *): some to pop and discard +# +# - test the action associated to `error' +# +# - check the lookahead that triggers an error is not discarded +# when we enter error recovery. Below, the lookahead causing the +# first error is ")", which is needed to recover from the error and +# produce the "0" that triggers the "0 != 1" error. +# +_AT_CHECK_CALC_ERROR([$1], [0], + [() + (1 + 1 + 1 +) + (* * *) + (1 * 2 * *) = 1], + [156], +[1.1: syntax error, unexpected ')', expecting "number" or '-' or '(' or '!' +1.17: syntax error, unexpected ')', expecting "number" or '-' or '(' or '!' +1.22: syntax error, unexpected '*', expecting "number" or '-' or '(' or '!' +1.40: syntax error, unexpected '*', expecting "number" or '-' or '(' or '!' +calc: error: 4444 != 1]) + +# The same, but this time exercising explicitly triggered syntax errors. +# POSIX says the lookahead causing the error should not be discarded. +_AT_CHECK_CALC_ERROR([$1], [0], [(!) + (0 0) = 1], [64], +[1.9: syntax error, unexpected "number" +calc: error: 2222 != 1]) AT_CHECK_POPDEFS AT_CLEANUP @@ -562,7 +645,7 @@ AT_CHECK_CALC_LALR([%error-verbose %debug %locations %defines %name-prefix="calc AT_CHECK_CALC_LALR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc]) -AT_CHECK_CALC_LALR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc %parse-param {value_t *result}, {result} %parse-param {int *count}, {count}]) +AT_CHECK_CALC_LALR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc %parse-param {value *result} %parse-param {int *count}]) # ----------------------- # @@ -597,4 +680,40 @@ AT_CHECK_CALC_GLR([%error-verbose %debug %locations %defines %name-prefix="calc" AT_CHECK_CALC_GLR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc]) -AT_CHECK_CALC_GLR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc %parse-param {value_t *result}, {result} %parse-param {int *count}, {count}]) +AT_CHECK_CALC_GLR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc %parse-param {value *result} %parse-param {int *count}]) + + +# ----------------------------- # +# Simple LALR1 C++ Calculator. # +# ----------------------------- # + +AT_BANNER([[Simple LALR1 C++ Calculator.]]) + +# AT_CHECK_CALC_LALR1_CC([BISON-OPTIONS]) +# --------------------------------------- +# Start a testing chunk which compiles `calc' grammar with +# BISON-OPTIONS and %glr-parser, and performs several tests over the parser. +m4_define([AT_CHECK_CALC_LALR1_CC], +[AT_CHECK_CALC([%skeleton "lalr1.cc"] $@)]) + +# AT_CHECK_CALC_LALR1_CC() + +AT_CHECK_CALC_LALR1_CC([%defines %locations]) + +AT_CHECK_CALC_LALR1_CC([%defines]) +# AT_CHECK_CALC_LALR1_CC([%locations]) +# AT_CHECK_CALC_LALR1_CC([%name-prefix="calc"]) +# AT_CHECK_CALC_LALR1_CC([%verbose]) +# AT_CHECK_CALC_LALR1_CC([%yacc]) +# AT_CHECK_CALC_LALR1_CC([%error-verbose]) + +# AT_CHECK_CALC_LALR1_CC([%error-verbose %locations]) + +AT_CHECK_CALC_LALR1_CC([%error-verbose %locations %defines %name-prefix="calc" %verbose %yacc]) + +# AT_CHECK_CALC_LALR1_CC([%debug]) +AT_CHECK_CALC_LALR1_CC([%error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc]) + +AT_CHECK_CALC_LALR1_CC([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc]) + +# AT_CHECK_CALC_LALR1_CC([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc %parse-param {value *result} %parse-param {int *count}])