# Simple calculator. -*- Autotest -*-
-# Copyright (C) 2000-2010 Free Software Foundation, Inc.
+# Copyright (C) 2000-2012 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
# 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 <stdlib.h> /* abort */
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#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 <ctype.h>
{
unget_char (]AT_LEX_PRE_ARGS[ c);
]AT_VAL[.ival = read_signed_integer (]AT_LEX_ARGS[);
- return NUM;
+ return ]AT_TOKEN_PREFIX[NUM;
}
/* Return end-of-file. */
if (c == EOF)
- return CALC_EOF;
+ return ]AT_TOKEN_PREFIX[CALC_EOF;
/* Return single chars. */
return c;
Point last;
};
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
-do { \
- if (N) \
- { \
- (Current).first = (Rhs)[1].first; \
- (Current).last = (Rhs)[N].last; \
- } \
- else \
- { \
- (Current).first = (Current).last = (Rhs)[0].last; \
- } \
-} while (false)
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (N) \
+ { \
+ (Current).first = YYRHSLOC (Rhs, 1).first; \
+ (Current).last = YYRHSLOC (Rhs, N).last; \
+ } \
+ else \
+ { \
+ (Current).first = (Current).last = YYRHSLOC (Rhs, 0).last; \
+ } \
+ while (false)
]])[
/* Exercise pre-prologue dependency to %union. */
{
#include <stdio.h>
/* 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
%code
{
-#include <stdlib.h>
+#include <assert.h>
#include <string.h>
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#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(,
int yylex (]AT_LEX_FORMALS[);
}
-]AT_SKEL_CC_IF([AT_LOCATION_TYPE_IF([], [
+]AT_SKEL_CC_IF([AT_LOCATION_IF([AT_LOCATION_TYPE_IF([], [
/* The lalr1.cc skeleton, for backward compatibility, defines
a constructor for position that initializes the filename. The
glr.cc skeleton does not (and in fact cannot: location/position
are stored in a union, from which objects with constructors are
- excluded in C++. */
+ excluded in C++). */
%initial-action {
- @$.initialize (0);
+ @$.initialize ();
}
-])])[
+])])])[
/* Bison Declarations */
%token CALC_EOF 0 "end of input"
%token <ival> NUM "number"
%type <ival> exp
-%nonassoc '=' /* comparison */
+%nonassoc '=' /* comparison */
%left '-' '+'
%left '*' '/'
-%left NEG /* negation--unary minus */
-%right '^' /* exponentiation */
+%precedence NEG /* negation--unary minus */
+%right '^' /* exponentiation */
/* Grammar follows */
%%
;
%%
+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&
/* A C++ error reporting function. */
void
-AT_NAME_PREFIX::parser::error (const location_type& l, const std::string& m)
+AT_NAME_PREFIX::parser::error (AT_LOCATION_IF([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
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;
- if (exponent < 0)
- exit (3);
- 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
# If BISON-OPTIONS contains `%location', then make sure the ERROR-LOCATION
# is correctly output on stderr.
#
-# If BISON-OPTIONS contains `%error-verbose', then make sure the
+# If BISON-OPTIONS contains `%define parse.error verbose', then make sure the
# IF-YYERROR-VERBOSE message is properly output after `syntax error, '
# on STDERR.
#
[[sed 's/^[-0-9.]*: //' expout >at-expout
mv at-expout expout]])
# 4. If error-verbose is not used, strip the`, unexpected....' part.
-m4_bmatch([$1], [%error-verbose], [],
+m4_bmatch([$1], [%define parse.error verbose], [],
[[sed 's/syntax error, .*$/syntax error/' expout >at-expout
mv at-expout expout]])
# 5. Check
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],
AT_CHECK_CALC_LALR([%name-prefix="calc"]) dnl test deprecated `='
AT_CHECK_CALC_LALR([%verbose])
AT_CHECK_CALC_LALR([%yacc])
-AT_CHECK_CALC_LALR([%error-verbose])
+AT_CHECK_CALC_LALR([%define parse.error verbose])
AT_CHECK_CALC_LALR([%define api.pure %locations])
AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure %locations])
-AT_CHECK_CALC_LALR([%error-verbose %locations])
+AT_CHECK_CALC_LALR([%define parse.error verbose %locations])
-AT_CHECK_CALC_LALR([%error-verbose %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %name-prefix "calc" %define api.tokens.prefix "TOK_" %verbose %yacc])
AT_CHECK_CALC_LALR([%debug])
-AT_CHECK_CALC_LALR([%error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR([%define api.pure %error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure %error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR([%define api.pure %error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_LALR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
# ----------------------- #
AT_CHECK_CALC_GLR([%name-prefix "calc"])
AT_CHECK_CALC_GLR([%verbose])
AT_CHECK_CALC_GLR([%yacc])
-AT_CHECK_CALC_GLR([%error-verbose])
+AT_CHECK_CALC_GLR([%define parse.error verbose])
AT_CHECK_CALC_GLR([%define api.pure %locations])
-AT_CHECK_CALC_GLR([%error-verbose %locations])
+AT_CHECK_CALC_GLR([%define parse.error verbose %locations])
-AT_CHECK_CALC_GLR([%error-verbose %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR([%define parse.error verbose %locations %defines %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR([%debug])
-AT_CHECK_CALC_GLR([%error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %define api.tokens.prefix "TOK_" %verbose %yacc])
-AT_CHECK_CALC_GLR([%define api.pure %error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_GLR([%define api.pure %error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
# ----------------------------- #
# Start a testing chunk which compiles `calc' grammar with
# the C++ skeleton, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_LALR1_CC],
-[AT_CHECK_CALC([%language "C++" %defines %locations] $@)])
+[AT_CHECK_CALC([%language "C++" %defines] $@)])
AT_CHECK_CALC_LALR1_CC([])
-AT_CHECK_CALC_LALR1_CC([%define location_type Span])
-AT_CHECK_CALC_LALR1_CC([%error-verbose %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR1_CC([%error-verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR1_CC([%locations])
+AT_CHECK_CALC_LALR1_CC([%locations %define location_type Span])
+AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %name-prefix "calc" %verbose %yacc])
+
+AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR1_CC([%pure-parser %error-verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR1_CC([%locations %pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR1_CC([%locations %pure-parser %define parse.error verbose %debug %name-prefix "calc" %define api.tokens.prefix "TOK_" %verbose %yacc])
-AT_CHECK_CALC_LALR1_CC([%pure-parser %error-verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_LALR1_CC([%locations %pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
[AT_CHECK_CALC([%language "C++" %glr-parser %defines %locations] $@)])
AT_CHECK_CALC_GLR_CC([])
-AT_CHECK_CALC_GLR_CC([%error-verbose %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%define location_type Span])
+AT_CHECK_CALC_GLR_CC([%define parse.error verbose %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR_CC([%debug])
-AT_CHECK_CALC_GLR_CC([%error-verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_GLR_CC([%pure-parser %error-verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%pure-parser %define parse.error verbose %debug %name-prefix "calc" %define api.tokens.prefix "TOK_" %verbose %yacc])
-AT_CHECK_CALC_GLR_CC([%pure-parser %error-verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_GLR_CC([%pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])