# 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 <assert.h>
+#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 ]AT_API_PREFIX[DEBUG
+ 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");
+ assert (global_result == result);
+ assert (global_count == count);
+ return status;
+}
+]])
+
+
m4_pushdef([AT_CALC_LEX],
[[#include <ctype.h>
-int ]AT_NAME_PREFIX[lex (]AT_LEX_FORMALS[);
-static int get_char (]AT_LEX_FORMALS[);
-static void unget_char (]AT_LEX_PRE_FORMALS[ int c);
+]AT_YYLEX_DECLARE_EXTERN[
+static int get_char (]AT_YYLEX_FORMALS[);
+static void unget_char (]AT_YYLEX_PRE_FORMALS[ int c);
]AT_LOCATION_IF([
-static YYLTYPE last_yylloc;
+static AT_YYLTYPE last_yylloc;
])[
static int
-get_char (]AT_LEX_FORMALS[)
+get_char (]AT_YYLEX_FORMALS[)
{
int res = getc (input);
]AT_USE_LEX_ARGS[;
}
static void
-unget_char (]AT_LEX_PRE_FORMALS[ int c)
+unget_char (]AT_YYLEX_PRE_FORMALS[ int c)
{
]AT_USE_LEX_ARGS[;
]AT_LOCATION_IF([
}
static int
-read_signed_integer (]AT_LEX_FORMALS[)
+read_signed_integer (]AT_YYLEX_FORMALS[)
{
- int c = get_char (]AT_LEX_ARGS[);
+ int c = get_char (]AT_YYLEX_ARGS[);
int sign = 1;
int n = 0;
]AT_USE_LEX_ARGS[;
if (c == '-')
{
- c = get_char (]AT_LEX_ARGS[);
+ c = get_char (]AT_YYLEX_ARGS[);
sign = -1;
}
while (isdigit (c))
{
n = 10 * n + (c - '0');
- c = get_char (]AT_LEX_ARGS[);
+ c = get_char (]AT_YYLEX_ARGS[);
}
- unget_char (]AT_LEX_PRE_ARGS[ c);
+ unget_char (]AT_YYLEX_PRE_ARGS[ c);
return sign * n;
}
| blanks and tabs, returns 0 for EOF. |
`---------------------------------------------------------------*/
-int
-]AT_NAME_PREFIX[lex (]AT_LEX_FORMALS[)
+]AT_YYLEX_PROTOTYPE[
{
- static int init = 1;
int c;
-
- if (init)
- {
- init = 0;
-]AT_LOCATION_IF([
- AT_LOC_LAST_COLUMN = 1;
- AT_LOC_LAST_LINE = 1;
-])[
- }
-
/* Skip current token, then white spaces. */
do
{
AT_LOC_FIRST_LINE = AT_LOC_LAST_LINE;
])[
}
- while ((c = get_char (]AT_LEX_ARGS[)) == ' ' || c == '\t');
+ while ((c = get_char (]AT_YYLEX_ARGS[)) == ' ' || c == '\t');
/* process numbers */
if (c == '.' || isdigit (c))
{
- unget_char (]AT_LEX_PRE_ARGS[ c);
- ]AT_VAL[.ival = read_signed_integer (]AT_LEX_ARGS[);
+ unget_char (]AT_YYLEX_PRE_ARGS[ c);
+ ]AT_VAL[.ival = read_signed_integer (]AT_YYLEX_ARGS[);
return ]AT_TOKEN_PREFIX[NUM;
}
{
semantic_value ival;
};
+%printer { ]AT_SKEL_CC_IF([[yyoutput << $$]],
+ [[fprintf (yyoutput, "%d", $$)]])[; } <ival>;
%code provides
{
-#include <stdio.h>
-/* The input. */
-extern FILE *input;]AT_SKEL_CC_IF([[
-#ifndef YYLTYPE
-# define YYLTYPE ]AT_NAME_PREFIX[::parser::location_type
-#endif
-]])[
+ #include <stdio.h>
+ /* The input. */
+ extern FILE *input;
+ extern semantic_value global_result;
+ extern int global_count;
}
%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(,
-[/* yyerror receives the location if:
- - %location & %pure & %glr
- - %location & %pure & %yacc & %parse-param. */
-static void yyerror (AT_YYERROR_ARG_LOC_IF([YYLTYPE *llocp, ])
- AT_PARAM_IF([semantic_value *result, int *count, ])
- const char *s
- );])[
-int yylex (]AT_LEX_FORMALS[);
+]AT_YYERROR_DECLARE[
+]AT_YYLEX_DECLARE_EXTERN[
}
-]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++). */
-%initial-action {
- @$.initialize (0);
-}
-])])])[
+]AT_SKEL_CC_IF([AT_LOCATION_TYPE_IF([[
+%initial-action
+{
+ @$.first.l = @$.first.c = 1;
+ @$.last = @$.first;
+}]])])[
/* Bison Declarations */
%token CALC_EOF 0 "end of input"
;
%%
+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&
o << '-' << s.last.c - 1;
return o;
}
-]])
-
-/* A C++ error reporting function. */
-void
-AT_NAME_PREFIX::parser::error (AT_LOCATION_IF([const location_type& l, ])const std::string& m)
-{
- 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
-yyerror (AT_YYERROR_ARG_LOC_IF([YYLTYPE *llocp, ])
- AT_PARAM_IF([semantic_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_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);
+]])])[
+]AT_YYERROR_DEFINE[
+]AT_DEFINES_IF([],
+[AT_CALC_LEX
+AT_CALC_MAIN])])
- 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_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_SPACES([FILE])
+# -----------------------
+# Make sure we did not introduce bad spaces. Checked here because all
+# the skeletons are (or should be) exercized here.
+m4_define([AT_CHECK_SPACES],
+[AT_CHECK([$PERL -ne '
+ chomp;
+ print "$.: {$_}\n"
+ if (# No starting/ending empty lines.
+ (eof || $. == 1) && /^\s*$/
+ # No trailing space.
+ || /\s$/
+ # No tabs.
+ || /\t/
+ )' $1
+])dnl
+])
+
+
+# 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]]))
+AT_CHECK_SPACES([calc.AT_SKEL_CC_IF([cc], [c])])
+AT_DEFINES_IF([AT_CHECK_SPACES([calc.AT_SKEL_CC_IF([hh], [h])])])
# Test the priorities.
_AT_CHECK_CALC([$1],
[842])
# Some syntax errors.
-_AT_CHECK_CALC_ERROR([$1], [1], [0 0], [15],
+_AT_CHECK_CALC_ERROR([$1], [1], [1 2], [15],
[1.3: syntax error, unexpected number])
_AT_CHECK_CALC_ERROR([$1], [1], [1//2], [20],
[1.3: syntax error, unexpected '/', expecting number or '-' or '(' or '!'])
# 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], [102],
+_AT_CHECK_CALC_ERROR([$1], [0], [(!) + (1 2) = 1], [102],
[1.10: syntax error, unexpected number
calc: error: 2222 != 1])
-_AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (0 0) = 1], [113],
+_AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (1 2) = 1], [113],
[1.4: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
1.12: syntax error, unexpected number
calc: error: 2222 != 1])
AT_CHECK_CALC_LALR([%defines])
AT_CHECK_CALC_LALR([%locations])
-AT_CHECK_CALC_LALR([%name-prefix="calc"]) dnl test deprecated `='
+AT_CHECK_CALC_LALR([%name-prefix "calc"])
AT_CHECK_CALC_LALR([%verbose])
AT_CHECK_CALC_LALR([%yacc])
AT_CHECK_CALC_LALR([%define parse.error verbose])
AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure %locations])
AT_CHECK_CALC_LALR([%define parse.error verbose %locations])
-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([%define parse.error verbose %locations %defines %define api.prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %name-prefix "calc" %define api.token.prefix "TOK_" %verbose %yacc])
AT_CHECK_CALC_LALR([%debug])
AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %define api.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.push-pull both %define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc])
-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_LALR([%define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
# ----------------------- #
AT_CHECK_CALC_GLR([%defines])
AT_CHECK_CALC_GLR([%locations])
AT_CHECK_CALC_GLR([%name-prefix "calc"])
+AT_CHECK_CALC_GLR([%define api.prefix "calc"])
AT_CHECK_CALC_GLR([%verbose])
AT_CHECK_CALC_GLR([%yacc])
AT_CHECK_CALC_GLR([%define parse.error verbose])
AT_CHECK_CALC_GLR([%debug])
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 parse.error verbose %debug %locations %defines %define api.prefix "calc" %define api.token.prefix "TOK_" %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 %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([%define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
# ----------------------------- #
AT_BANNER([[Simple LALR(1) C++ Calculator.]])
# First let's try using %skeleton
-AT_CHECK_CALC([%skeleton "lalr1.cc" %defines %locations])
+AT_CHECK_CALC([%skeleton "lalr1.cc" %defines])
# AT_CHECK_CALC_LALR1_CC([BISON-OPTIONS])
# ---------------------------------------
# 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] $@)])
+[AT_CHECK_CALC([%language "C++"] $@)])
AT_CHECK_CALC_LALR1_CC([])
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 api.location.type Span])
+AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %define api.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([%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([%locations %pure-parser %define parse.error verbose %debug %define api.prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR1_CC([%locations %pure-parser %define parse.error verbose %debug %define api.prefix "calc" %define api.token.prefix "TOK_" %verbose %yacc])
+
+AT_CHECK_CALC_LALR1_CC([%defines %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_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_LALR1_CC([%pure-parser %define parse.error verbose %debug %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_LALR1_CC([%defines %locations %pure-parser %define parse.error verbose %debug %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
AT_BANNER([[Simple GLR C++ Calculator.]])
# Again, we try also using %skeleton.
-AT_CHECK_CALC([%skeleton "glr.cc" %defines %locations])
+AT_CHECK_CALC([%skeleton "glr.cc"])
# AT_CHECK_CALC_GLR_CC([BISON-OPTIONS])
# -------------------------------------
# Start a testing chunk which compiles `calc' grammar with
# the GLR C++ skeleton, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_GLR_CC],
-[AT_CHECK_CALC([%language "C++" %glr-parser %defines %locations] $@)])
+[AT_CHECK_CALC([%language "C++" %glr-parser] $@)])
AT_CHECK_CALC_GLR_CC([])
-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([%locations])
+AT_CHECK_CALC_GLR_CC([%locations %define api.location.type Span])
+AT_CHECK_CALC_GLR_CC([%defines %define parse.error verbose %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%define parse.error verbose %define api.prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR_CC([%debug])
AT_CHECK_CALC_GLR_CC([%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" %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 %define parse.error verbose %debug %name-prefix "calc" %define api.token.prefix "TOK_" %verbose %yacc])
-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}])
+AT_CHECK_CALC_GLR_CC([%locations %defines %pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_GLR_CC([%locations %defines %pure-parser %define parse.error verbose %debug %define api.prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])