# 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>
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(,
are stored in a union, from which objects with constructors are
excluded in C++. */
%initial-action {
- @$.initialize (0);
+ @$.initialize ();
}
])])[
%token <ival> NUM "number"
%type <ival> exp
-%nonassoc '=' /* comparison */
+%nonassoc '=' /* comparison */
%left '-' '+'
%left '*' '/'
%left NEG /* negation--unary minus */
;
%%
+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&
(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
])
-# 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],
[AT_CHECK_CALC([%language "C++" %glr-parser %defines %locations] $@)])
AT_CHECK_CALC_GLR_CC([])
+AT_CHECK_CALC_GLR_CC([%define location_type Span])
AT_CHECK_CALC_GLR_CC([%error-verbose %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR_CC([%debug])