mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
See http://www.gnu.org/prep/maintain/maintain.html#Copyright-Notices * HACKING, Makefile.am, NEWS, PACKAGING, README, README-alpha: * TODO, bootstrap, bootstrap.conf: * build-aux/update-b4-copyright, cfg.mk, configure.ac: * data/README, data/bison.m4, data/c++-skel.m4, data/c++.m4: * data/c-skel.m4, data/c.m4, data/glr.c, data/glr.cc: * data/java-skel.m4, data/java.m4, data/lalr1.cc: * data/lalr1.java, data/local.mk, data/location.cc: * data/stack.hh, data/variant.hh, data/xslt/bison.xsl: * data/xslt/xml2dot.xsl, data/xslt/xml2text.xsl: * data/xslt/xml2xhtml.xsl, data/yacc.c, djgpp/Makefile.maint: * djgpp/README.in, djgpp/config.bat, djgpp/config.sed: * djgpp/config.site, djgpp/config_h.sed, djgpp/djunpack.bat: * djgpp/local.mk, djgpp/subpipe.c, djgpp/subpipe.h: * djgpp/testsuite.sed, doc/bison.texinfo, doc/local.mk: * doc/refcard.tex, etc/README, etc/bench.pl.in, etc/local.mk: * examples/calc++/Makefile.am, examples/extexi: * examples/local.mk, lib/abitset.c, lib/abitset.h: * lib/bbitset.h, lib/bitset.c, lib/bitset.h: * lib/bitset_stats.c, lib/bitset_stats.h, lib/bitsetv-print.c: * lib/bitsetv-print.h, lib/bitsetv.c, lib/bitsetv.h: * lib/ebitset.c, lib/ebitset.h, lib/get-errno.c: * lib/get-errno.h, lib/lbitset.c, lib/lbitset.h: * lib/libiberty.h, lib/local.mk, lib/main.c, lib/timevar.c: * lib/timevar.def, lib/timevar.h, lib/vbitset.c: * lib/vbitset.h, lib/yyerror.c, m4/bison-i18n.m4: * m4/c-working.m4, m4/cxx.m4, m4/subpipe.m4, m4/timevar.m4: * src/AnnotationList.c, src/AnnotationList.h: * src/InadequacyList.c, src/InadequacyList.h, src/LR0.c: * src/LR0.h, src/Sbitset.c, src/Sbitset.h, src/assoc.c: * src/assoc.h, src/closure.c, src/closure.h, src/complain.c: * src/complain.h, src/conflicts.c, src/conflicts.h: * src/derives.c, src/derives.h, src/files.c, src/files.h: * src/flex-scanner.h, src/getargs.c, src/getargs.h: * src/gram.c, src/gram.h, src/graphviz.c, src/ielr.c: * src/ielr.h, src/lalr.c, src/lalr.h, src/local.mk: * src/location.c, src/location.h, src/main.c: * src/muscle-tab.c, src/muscle-tab.h, src/named-ref.c: * src/named-ref.h, src/nullable.c, src/nullable.h: * src/output.c, src/output.h, src/parse-gram.y: * src/print-xml.c, src/print-xml.h, src/print.c, src/print.h: * src/print_graph.c, src/print_graph.h, src/reader.c: * src/reader.h, src/reduce.c, src/reduce.h, src/relation.c: * src/relation.h, src/scan-code.h, src/scan-code.l: * src/scan-gram.h, src/scan-gram.l, src/scan-skel.h: * src/scan-skel.l, src/state.c, src/state.h, src/symlist.c: * src/symlist.h, src/symtab.c, src/symtab.h, src/system.h: * src/tables.c, src/tables.h, src/uniqstr.c, src/uniqstr.h: * tests/actions.at, tests/atlocal.in, tests/c++.at: * tests/calc.at, tests/conflicts.at, tests/cxx-type.at: * tests/existing.at, tests/glr-regression.at: * tests/headers.at, tests/input.at, tests/java.at: * tests/local.at, tests/local.mk, tests/named-refs.at: * tests/output.at, tests/push.at, tests/reduce.at: * tests/regression.at, tests/sets.at, tests/skeletons.at: * tests/synclines.at, tests/testsuite.at, tests/torture.at: Don't use date ranges in copyright notices. Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
730 lines
22 KiB
Plaintext
730 lines
22 KiB
Plaintext
# Simple calculator. -*- Autotest -*-
|
|
|
|
# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
|
|
# 2009, 2010 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
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
## ---------------------------------------------------- ##
|
|
## Compile the grammar described in the documentation. ##
|
|
## ---------------------------------------------------- ##
|
|
|
|
|
|
# ------------------------- #
|
|
# Helping Autotest macros. #
|
|
# ------------------------- #
|
|
|
|
|
|
# _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
|
|
# -----------------------------------------------
|
|
# Produce `calc.y' and, if %defines was specified, `calc-lex.c' or
|
|
# `calc-lex.cc'.
|
|
#
|
|
# 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.
|
|
m4_define([_AT_DATA_CALC_Y],
|
|
[m4_if([$1$2$3], $[1]$[2]$[3], [],
|
|
[m4_fatal([$0: Invalid arguments: $@])])dnl
|
|
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_LOCATION_IF([
|
|
static YYLTYPE last_yylloc;
|
|
])[
|
|
static int
|
|
get_char (]AT_LEX_FORMALS[)
|
|
{
|
|
int res = getc (input);
|
|
]AT_USE_LEX_ARGS[;
|
|
]AT_LOCATION_IF([
|
|
last_yylloc = AT_LOC;
|
|
if (res == '\n')
|
|
{
|
|
AT_LOC_LAST_LINE++;
|
|
AT_LOC_LAST_COLUMN = 1;
|
|
}
|
|
else
|
|
AT_LOC_LAST_COLUMN++;
|
|
])[
|
|
return res;
|
|
}
|
|
|
|
static void
|
|
unget_char (]AT_LEX_PRE_FORMALS[ int c)
|
|
{
|
|
]AT_USE_LEX_ARGS[;
|
|
]AT_LOCATION_IF([
|
|
/* Wrong when C == `\n'. */
|
|
AT_LOC = last_yylloc;
|
|
])[
|
|
ungetc (c, input);
|
|
}
|
|
|
|
static int
|
|
read_signed_integer (]AT_LEX_FORMALS[)
|
|
{
|
|
int c = get_char (]AT_LEX_ARGS[);
|
|
int sign = 1;
|
|
int n = 0;
|
|
|
|
]AT_USE_LEX_ARGS[;
|
|
if (c == '-')
|
|
{
|
|
c = get_char (]AT_LEX_ARGS[);
|
|
sign = -1;
|
|
}
|
|
|
|
while (isdigit (c))
|
|
{
|
|
n = 10 * n + (c - '0');
|
|
c = get_char (]AT_LEX_ARGS[);
|
|
}
|
|
|
|
unget_char (]AT_LEX_PRE_ARGS[ c);
|
|
|
|
return sign * n;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------.
|
|
| Lexical analyzer returns an integer on the stack and the token |
|
|
| NUM, or the ASCII character read if not a number. Skips all |
|
|
| blanks and tabs, returns 0 for EOF. |
|
|
`---------------------------------------------------------------*/
|
|
|
|
int
|
|
]AT_NAME_PREFIX[lex (]AT_LEX_FORMALS[)
|
|
{
|
|
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_LOCATION_IF(
|
|
[ AT_LOC_FIRST_COLUMN = AT_LOC_LAST_COLUMN;
|
|
AT_LOC_FIRST_LINE = AT_LOC_LAST_LINE;
|
|
])[
|
|
}
|
|
while ((c = get_char (]AT_LEX_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[);
|
|
return ]AT_TOKEN_PREFIX[NUM;
|
|
}
|
|
|
|
/* Return end-of-file. */
|
|
if (c == EOF)
|
|
return ]AT_TOKEN_PREFIX[CALC_EOF;
|
|
|
|
/* Return single chars. */
|
|
return c;
|
|
}
|
|
]])
|
|
|
|
AT_DATA_GRAMMAR([calc.y],
|
|
[[/* Infix notation calculator--calc */
|
|
]$4
|
|
AT_SKEL_CC_IF(
|
|
[%define global_tokens_and_yystype])[
|
|
%code requires
|
|
{
|
|
]AT_LOCATION_TYPE_IF([[
|
|
# include <iostream>
|
|
struct Point
|
|
{
|
|
int l;
|
|
int c;
|
|
};
|
|
|
|
struct Span
|
|
{
|
|
Point first;
|
|
Point last;
|
|
};
|
|
|
|
# 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. */
|
|
typedef int semantic_value;
|
|
}
|
|
|
|
/* Exercise %union. */
|
|
%union
|
|
{
|
|
semantic_value 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
|
|
]])[
|
|
}
|
|
|
|
%code
|
|
{
|
|
#include <stdlib.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_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);
|
|
}
|
|
])])])[
|
|
|
|
/* Bison Declarations */
|
|
%token CALC_EOF 0 "end of input"
|
|
%token <ival> NUM "number"
|
|
%type <ival> exp
|
|
|
|
%nonassoc '=' /* comparison */
|
|
%left '-' '+'
|
|
%left '*' '/'
|
|
%precedence NEG /* negation--unary minus */
|
|
%right '^' /* exponentiation */
|
|
|
|
/* Grammar follows */
|
|
%%
|
|
input:
|
|
line
|
|
| input line { ]AT_PARAM_IF([++*count; ++global_count;])[ }
|
|
;
|
|
|
|
line:
|
|
'\n'
|
|
| exp '\n' { ]AT_PARAM_IF([*result = global_result = $1], [USE ($1)])[; }
|
|
;
|
|
|
|
exp:
|
|
NUM { $$ = $1; }
|
|
| exp '=' exp
|
|
{
|
|
if ($1 != $3)
|
|
fprintf (stderr, "calc: error: %d != %d\n", $1, $3);
|
|
$$ = $1;
|
|
}
|
|
| exp '+' exp { $$ = $1 + $3; }
|
|
| exp '-' exp { $$ = $1 - $3; }
|
|
| exp '*' exp { $$ = $1 * $3; }
|
|
| exp '/' exp { $$ = $1 / $3; }
|
|
| '-' exp %prec NEG { $$ = -$2; }
|
|
| exp '^' exp { $$ = power ($1, $3); }
|
|
| '(' exp ')' { $$ = $2; }
|
|
| '(' error ')' { $$ = 1111; yyerrok; }
|
|
| '!' { $$ = 0; YYERROR; }
|
|
| '-' error { $$ = 0; YYERROR; }
|
|
;
|
|
%%
|
|
|
|
]AT_SKEL_CC_IF(
|
|
[AT_LOCATION_TYPE_IF([[
|
|
std::ostream&
|
|
operator<< (std::ostream& o, const Span& s)
|
|
{
|
|
o << s.first.l << '.' << s.first.c;
|
|
if (s.first.l != s.last.l)
|
|
o << '-' << s.last.l << '.' << s.last.c - 1;
|
|
else if (s.first.c != s.last.c - 1)
|
|
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;
|
|
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_DATA_SOURCE([[calc-lex.c]AT_SKEL_CC_IF([[c]])],
|
|
[[#include "calc.h]AT_SKEL_CC_IF([[h]])["
|
|
|
|
]AT_CALC_LEX])])
|
|
m4_popdef([AT_CALC_LEX])
|
|
])# _AT_DATA_CALC_Y
|
|
|
|
|
|
# AT_DATA_CALC_Y([BISON-OPTIONS])
|
|
# -------------------------------
|
|
# Produce `calc.y' and, if %defines was specified, `calc-lex.c' or
|
|
# `calc-lex.cc'.
|
|
m4_define([AT_DATA_CALC_Y],
|
|
[_AT_DATA_CALC_Y($[1], $[2], $[3], [$1])
|
|
])
|
|
|
|
|
|
|
|
# _AT_CHECK_CALC(BISON-OPTIONS, INPUT, [NUM-STDERR-LINES])
|
|
# --------------------------------------------------------
|
|
# Run `calc' on INPUT and expect no STDOUT nor STDERR.
|
|
#
|
|
# If BISON-OPTIONS contains `%debug' but not `%glr-parser', then
|
|
#
|
|
# NUM-STDERR-LINES is the number of expected lines on stderr.
|
|
# Currently this is ignored, though, since the output format is fluctuating.
|
|
#
|
|
# We don't count GLR's traces yet, since its traces are somewhat
|
|
# different from LALR's.
|
|
m4_define([_AT_CHECK_CALC],
|
|
[AT_DATA([[input]],
|
|
[[$2
|
|
]])
|
|
AT_PARSER_CHECK([./calc input], 0, [], [stderr])
|
|
])
|
|
|
|
|
|
# _AT_CHECK_CALC_ERROR(BISON-OPTIONS, EXIT-STATUS, INPUT,
|
|
# [NUM-STDERR-LINES],
|
|
# [VERBOSE-AND-LOCATED-ERROR-MESSAGE])
|
|
# ---------------------------------------------------------
|
|
# Run `calc' on INPUT, and expect a `syntax error' message.
|
|
#
|
|
# If INPUT starts with a slash, it is used as absolute input file name,
|
|
# otherwise as contents.
|
|
#
|
|
# NUM-STDERR-LINES is the number of expected lines on stderr.
|
|
# Currently this is ignored, though, since the output format is fluctuating.
|
|
#
|
|
# If BISON-OPTIONS contains `%location', then make sure the ERROR-LOCATION
|
|
# is correctly output on stderr.
|
|
#
|
|
# If BISON-OPTIONS contains `%define parse.error verbose', then make sure the
|
|
# IF-YYERROR-VERBOSE message is properly output after `syntax error, '
|
|
# on STDERR.
|
|
#
|
|
# If BISON-OPTIONS contains `%debug' but not `%glr', then NUM-STDERR-LINES
|
|
# is the number of expected lines on stderr.
|
|
m4_define([_AT_CHECK_CALC_ERROR],
|
|
[m4_bmatch([$3], [^/],
|
|
[AT_PARSER_CHECK([./calc $3], $2, [], [stderr])],
|
|
[AT_DATA([[input]],
|
|
[[$3
|
|
]])
|
|
AT_PARSER_CHECK([./calc input], $2, [], [stderr])])
|
|
|
|
# Normalize the observed and expected error messages, depending upon the
|
|
# options.
|
|
# 1. Remove the traces from observed.
|
|
sed '/^Starting/d
|
|
/^Entering/d
|
|
/^Stack/d
|
|
/^Reading/d
|
|
/^Reducing/d
|
|
/^Return/d
|
|
/^Shifting/d
|
|
/^state/d
|
|
/^Cleanup:/d
|
|
/^Error:/d
|
|
/^Next/d
|
|
/^Now/d
|
|
/^Discarding/d
|
|
/ \$[[0-9$]]* = /d
|
|
/^yydestructor:/d' stderr >at-stderr
|
|
mv at-stderr stderr
|
|
# 2. Create the reference error message.
|
|
AT_DATA([[expout]],
|
|
[$5
|
|
])
|
|
# 3. If locations are not used, remove them.
|
|
AT_YYERROR_SEES_LOC_IF([],
|
|
[[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], [%define parse.error verbose], [],
|
|
[[sed 's/syntax error, .*$/syntax error/' expout >at-expout
|
|
mv at-expout expout]])
|
|
# 5. Check
|
|
AT_CHECK([cat stderr], 0, [expout])
|
|
])
|
|
|
|
|
|
# AT_CHECK_CALC([BISON-OPTIONS, [EXPECTED-TO-FAIL]])
|
|
# --------------------------------------------------
|
|
# 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], [AT_CHECK([exit 77])])
|
|
|
|
AT_BISON_OPTION_PUSHDEFS([$1])
|
|
|
|
AT_DATA_CALC_Y([$1])
|
|
AT_FULL_COMPILE([calc], [AT_DEFINES_IF([[lex]])])
|
|
|
|
# Test the priorities.
|
|
_AT_CHECK_CALC([$1],
|
|
[1 + 2 * 3 = 7
|
|
1 + 2 * -3 = -5
|
|
|
|
-1^2 = -1
|
|
(-1)^2 = 1
|
|
|
|
---1 = -1
|
|
|
|
1 - 2 - 3 = -4
|
|
1 - (2 - 3) = 2
|
|
|
|
2^2^3 = 256
|
|
(2^2)^3 = 64],
|
|
[842])
|
|
|
|
# Some syntax errors.
|
|
_AT_CHECK_CALC_ERROR([$1], [1], [0 0], [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 '!'])
|
|
_AT_CHECK_CALC_ERROR([$1], [1], [error], [5],
|
|
[1.1: syntax error, unexpected $undefined])
|
|
_AT_CHECK_CALC_ERROR([$1], [1], [1 = 2 = 3], [30],
|
|
[1.7: syntax error, unexpected '='])
|
|
_AT_CHECK_CALC_ERROR([$1], [1],
|
|
[
|
|
+1],
|
|
[20],
|
|
[2.1: syntax error, unexpected '+'])
|
|
# Exercise error messages with EOF: work on an empty file.
|
|
_AT_CHECK_CALC_ERROR([$1], [1], [/dev/null], [4],
|
|
[1.1: syntax error, unexpected end of input])
|
|
|
|
# Exercise the error token: without it, we die at the first error,
|
|
# 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],
|
|
[250],
|
|
[1.2: syntax error, unexpected ')', expecting number or '-' or '(' or '!'
|
|
1.18: syntax error, unexpected ')', expecting number or '-' or '(' or '!'
|
|
1.23: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
|
|
1.41: 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], [102],
|
|
[1.10: syntax error, unexpected number
|
|
calc: error: 2222 != 1])
|
|
_AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (0 0) = 1], [113],
|
|
[1.4: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
|
|
1.12: syntax error, unexpected number
|
|
calc: error: 2222 != 1])
|
|
|
|
# Check that yyerrok works properly: second error is not reported,
|
|
# third and fourth are. Parse status is succesfull.
|
|
_AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)], [113],
|
|
[1.2: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
|
|
1.10: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
|
|
1.16: syntax error, unexpected '*', expecting number or '-' or '(' or '!'])
|
|
|
|
AT_BISON_OPTION_POPDEFS
|
|
|
|
AT_CLEANUP
|
|
])# AT_CHECK_CALC
|
|
|
|
|
|
|
|
|
|
# ------------------------ #
|
|
# Simple LALR Calculator. #
|
|
# ------------------------ #
|
|
|
|
AT_BANNER([[Simple LALR(1) Calculator.]])
|
|
|
|
# AT_CHECK_CALC_LALR([BISON-OPTIONS])
|
|
# -----------------------------------
|
|
# Start a testing chunk which compiles `calc' grammar with
|
|
# BISON-OPTIONS, and performs several tests over the parser.
|
|
m4_define([AT_CHECK_CALC_LALR],
|
|
[AT_CHECK_CALC($@)])
|
|
|
|
AT_CHECK_CALC_LALR()
|
|
|
|
AT_CHECK_CALC_LALR([%defines])
|
|
AT_CHECK_CALC_LALR([%locations])
|
|
|
|
AT_CHECK_CALC_LALR([%name-prefix="calc"]) dnl test deprecated `='
|
|
AT_CHECK_CALC_LALR([%verbose])
|
|
AT_CHECK_CALC_LALR([%yacc])
|
|
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([%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([%debug])
|
|
AT_CHECK_CALC_LALR([%define parse.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 %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
|
|
|
|
|
|
# ----------------------- #
|
|
# Simple GLR Calculator. #
|
|
# ----------------------- #
|
|
|
|
AT_BANNER([[Simple GLR Calculator.]])
|
|
|
|
# AT_CHECK_CALC_GLR([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_GLR],
|
|
[AT_CHECK_CALC([%glr-parser] $@)])
|
|
|
|
|
|
AT_CHECK_CALC_GLR()
|
|
|
|
AT_CHECK_CALC_GLR([%defines])
|
|
AT_CHECK_CALC_GLR([%locations])
|
|
AT_CHECK_CALC_GLR([%name-prefix "calc"])
|
|
AT_CHECK_CALC_GLR([%verbose])
|
|
AT_CHECK_CALC_GLR([%yacc])
|
|
AT_CHECK_CALC_GLR([%define parse.error verbose])
|
|
|
|
AT_CHECK_CALC_GLR([%define api.pure %locations])
|
|
AT_CHECK_CALC_GLR([%define parse.error verbose %locations])
|
|
|
|
AT_CHECK_CALC_GLR([%define parse.error verbose %locations %defines %name-prefix "calc" %verbose %yacc])
|
|
|
|
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 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}])
|
|
|
|
|
|
# ----------------------------- #
|
|
# Simple LALR1 C++ Calculator. #
|
|
# ----------------------------- #
|
|
|
|
AT_BANNER([[Simple LALR(1) C++ Calculator.]])
|
|
|
|
# First let's try using %skeleton
|
|
AT_CHECK_CALC([%skeleton "lalr1.cc" %defines %locations])
|
|
|
|
# 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_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 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 %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
|
|
|
|
|
|
|
|
# --------------------------- #
|
|
# Simple GLR C++ Calculator. #
|
|
# --------------------------- #
|
|
|
|
AT_BANNER([[Simple GLR C++ Calculator.]])
|
|
|
|
# Again, we try also using %skeleton.
|
|
AT_CHECK_CALC([%skeleton "glr.cc" %defines %locations])
|
|
|
|
# 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_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([%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" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
|