summaryrefslogtreecommitdiff
path: root/tests/calc.at
diff options
context:
space:
mode:
authorAkim Demaille <akim.demaille@gmail.com>2020-09-27 13:07:57 +0200
committerAkim Demaille <akim.demaille@gmail.com>2020-09-28 19:26:53 +0200
commit9b18cac96bdad4a71b546a3c16ca4b7e25c0a657 (patch)
tree28512cdb98f6d0825f6c369ff4aee67d0bd69849 /tests/calc.at
parentc19c1e7ec5c579c66190ec35b010f6d3dca73f98 (diff)
downloadbison-9b18cac96bdad4a71b546a3c16ca4b7e25c0a657.tar.gz
multistart: start more thorough testing
* tests/local.at (AT_MULTISTART_IF): New. * tests/calc.at: Adjust to check multiple start symbols. * data/skeletons/yacc.c (yy_parse_impl): Fix.
Diffstat (limited to 'tests/calc.at')
-rw-r--r--tests/calc.at165
1 files changed, 115 insertions, 50 deletions
diff --git a/tests/calc.at b/tests/calc.at
index 0da2bbeb..e44000a2 100644
--- a/tests/calc.at
+++ b/tests/calc.at
@@ -57,6 +57,8 @@ AT_LANG_DISPATCH([$0], $@)])
# AT_CALC_MAIN(c).
m4_define([AT_CALC_MAIN(c)],
[[#include <assert.h>
+#include <stdlib.h> /* exit */
+#include <string.h> /* strcmp */
#include <unistd.h>
]AT_CXX_IF([[
@@ -82,6 +84,18 @@ int global_count = 0;
/* Total number of errors. */
int global_nerrs = 0;
+static FILE *
+open_file (const char *file)
+{
+ FILE *res = (file && *file && strcmp (file, "-")) ? fopen (file, "r") : stdin;
+ if (!res)
+ {
+ perror (file);
+ exit (3);
+ }
+ return res;
+}
+
/* A C main function. */
int
main (int argc, const char **argv)
@@ -89,7 +103,7 @@ main (int argc, const char **argv)
semantic_value result = 0;
int count = 0;
int nerrs = 0;]])[
- int status;
+ int status = 0;
/* 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
@@ -98,21 +112,43 @@ main (int argc, const char **argv)
alarm (200);
- if (argc == 2)
- input = fopen (argv[1], "r");
- else
- input = stdin;
-
- if (!input)
- {
- perror (argv[1]);
- return 3;
- }
-
]AT_CXX_IF([], [AT_DEBUG_IF([ ]AT_NAME_PREFIX[debug = 1;])])[
- status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count, &nerrs]])[);
- if (fclose (input))
- perror ("fclose");]AT_PARAM_IF([[
+
+ {
+ int i;
+ for (i = 1; i < argc; ++i)
+ {
+]AT_MULTISTART_IF([[
+ if (!strcmp (argv[i], "--exp") && i+1 < argc)
+ {
+ input = open_file (argv[i+1]);
+ ignore_eol = 1;
+ ]AT_NAME_PREFIX[parse_exp_t res = ]AT_NAME_PREFIX[parse_exp ();
+ printf ("exp => %d (status: %d, errors: %d)\n",
+ res.yystatus == 0 ? res.yyvalue : 0, res.yystatus, res.yynerrs);
+ status = res.yystatus;
+ ++i;
+ }
+ else if (!strcmp (argv[i], "--num") && i+1 < argc)
+ {
+ input = open_file (argv[i+1]);
+ ignore_eol = 1;
+ ]AT_NAME_PREFIX[parse_NUM_t res = ]AT_NAME_PREFIX[parse_NUM ();
+ printf ("NUM => %d (status: %d, errors: %d)\n",
+ res.yystatus == 0 ? res.yyvalue : 0, res.yystatus, res.yynerrs);
+ status = res.yystatus;
+ ++i;
+ }
+ else]])[
+ {
+ input = open_file (argv[i]);
+ status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count, &nerrs]])[);
+ }
+ if (input != stdin && fclose (input))
+ perror ("fclose");
+ }
+ }
+]AT_PARAM_IF([[
assert (global_result == result); (void) result;
assert (global_count == count); (void) count;
assert (global_nerrs == nerrs); (void) nerrs;
@@ -196,13 +232,15 @@ read_integer (]AT_YYLEX_FORMALS[)
AT_LOC_FIRST_LINE = AT_LOC_LAST_LINE;
])[
}
- while ((c = get_char (]AT_YYLEX_ARGS[)) == ' ' || c == '\t');
+ while ((c = get_char (]AT_YYLEX_ARGS[)) == ' '
+ || c == '\t'
+ || (ignore_eol && c == '\n'));
/* Process numbers. */
if (isdigit (c))
{
unget_char (]AT_YYLEX_PRE_ARGS[ c);
- ]AT_VAL[.ival = read_integer (]AT_YYLEX_ARGS[);
+ ]AT_VAL[.]AT_VALUE_UNION_IF([NUM], [ival])[ = read_integer (]AT_YYLEX_ARGS[);
return ]AT_CXX_IF([AT_NAMESPACE::parser::token::])[]AT_TOKEN_PREFIX[NUM;
}
@@ -268,19 +306,22 @@ void location_print (FILE *o, Span s);
typedef int semantic_value;
}
-/* Exercise %union. */
+]AT_VALUE_UNION_IF([],
+[[/* Exercise %union. */
%union
{
semantic_value ival;
-};
+};]])[
%printer { ]AT_CXX_IF([[yyo << $$]],
- [[fprintf (yyo, "%d", $$)]])[; } <ival>;
+ [[fprintf (yyo, "%d", $$)]])[; } <]AT_VALUE_UNION_IF([int], [ival])[>;
%code provides
{
#include <stdio.h>
/* The input. */
extern FILE *input;
+ /* Whether \n is a blank. */
+ extern int ignore_eol;
extern semantic_value global_result;
extern int global_count;
extern int global_nerrs;
@@ -293,6 +334,7 @@ void location_print (FILE *o, Span s);
#define USE(Var)
FILE *input;
+ int ignore_eol = 0;
static int power (int base, int exponent);
]AT_YYERROR_DECLARE[
@@ -323,8 +365,8 @@ void location_print (FILE *o, Span s);
/* Bison Declarations */
%token CALC_EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of input")], ["end of input"])[
-%token <ival> NUM "number"
-%type <ival> exp
+%token <]AT_VALUE_UNION_IF([int], [ival])[> NUM "number"
+%type <]AT_VALUE_UNION_IF([int], [ival])[> exp
%nonassoc '=' /* comparison */
%left '-' '+'
@@ -654,7 +696,7 @@ input:
line:
EOL
-| exp EOL { ]AT_PARAM_IF([*result = global_result = $1;], [USE ($1);])[ }
+| exp EOL { ]AT_PARAM_IF([*result = global_result = $1;])[ }
;
exp:
@@ -678,7 +720,7 @@ exp:
| "-" exp %prec NEG { $$ = -$2; }
| exp "^" exp { $$ = power ($1, $3); }
| "(" exp ")" { $$ = $2; }
-| "(" error ")" { $$ = 1111; yyerrok; }
+| "(" error ")" { $$ = 1111; }
| "!" { $$ = 0; return YYERROR; }
| "-" error { $$ = 0; return YYERROR; }
;
@@ -889,8 +931,8 @@ m4_define([AT_DATA_CALC_Y],
])
-# _AT_CHECK_CALC(BISON-OPTIONS, INPUT, [STDOUT], [NUM-STDERR-LINES])
-# ------------------------------------------------------------------
+# _AT_CHECK_CALC(CALC-OPTIONS, INPUT, [STDOUT], [NUM-STDERR-LINES])
+# -----------------------------------------------------------------
# Run 'calc' on INPUT and expect no STDOUT nor STDERR.
#
# If BISON-OPTIONS contains '%debug' but not '%glr-parser', then
@@ -907,8 +949,8 @@ m4_define([_AT_CHECK_CALC],
[$2
])
AT_JAVA_IF(
- [AT_JAVA_PARSER_CHECK([Calc < input], 0, [AT_PARAM_IF([m4_n([$3])])], [stderr])],
- [AT_PARSER_CHECK([calc input], 0, [AT_PARAM_IF([m4_n([$3])])], [stderr])])
+ [AT_JAVA_PARSER_CHECK([Calc $1 < input], 0, [m4_ifvaln(m4_quote($3), [$3])], [stderr])],
+ [AT_PARSER_CHECK([calc $1 input], 0, [m4_ifvaln(m4_quote($3), [$3])], [stderr])])
AT_LANG_MATCH([c\|c++\|java],
[AT_GLR_IF([],
[AT_CHECK([grep -c -v 'Return for a new token:' stderr],
@@ -921,6 +963,7 @@ AT_LANG_MATCH([c\|c++\|java],
# $4 = [STDOUT],
# $5 = [NUM-STDERR-LINES],
# $6 = [CUSTOM-ERROR-MESSAGE])
+# $7 = [CALC-OPTIONS])
# ----------------------------------------------------------------------
# Run 'calc' on INPUT, and expect a 'syntax error' message.
#
@@ -937,14 +980,14 @@ AT_LANG_MATCH([c\|c++\|java],
m4_define([_AT_CHECK_CALC_ERROR],
[m4_bmatch([$3], [^/],
[AT_JAVA_IF(
- [AT_JAVA_PARSER_CHECK([Calc < $3], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])],
- [AT_PARSER_CHECK([calc $3], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])])],
+ [AT_JAVA_PARSER_CHECK([Calc $7 < $3], $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])],
+ [AT_PARSER_CHECK([calc $7 $3], $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])])],
[AT_DATA([[input]],
[[$3
]])
AT_JAVA_IF(
- [AT_JAVA_PARSER_CHECK([Calc < input], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])],
- [AT_PARSER_CHECK([calc input], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])])
+ [AT_JAVA_PARSER_CHECK([Calc $7 < input], $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])],
+ [AT_PARSER_CHECK([calc $7 input], $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])])
])
# Normalize the observed and expected error messages, depending upon the
@@ -1063,7 +1106,7 @@ AT_CHECK_SPACES([AT_JAVA_IF([Calc], [calc]).AT_LANG_EXT AT_HEADER_IF([AT_JAVA_IF
# Test the precedences.
# The Java traces do not show the clean up sequence at the end,
# since it does not support %destructor.
-_AT_CHECK_CALC([$1],
+_AT_CHECK_CALC([],
[[1 + 2 * 3 = 7
1 + 2 * -3 = -5
@@ -1077,24 +1120,24 @@ _AT_CHECK_CALC([$1],
2^2^3 = 256
(2^2)^3 = 64]],
-[[final: 64 12 0]],
+[AT_PARAM_IF([final: 64 12 0])],
[AT_JAVA_IF([1014], [1017])])
# Some syntax errors.
_AT_CHECK_CALC_ERROR([$1], [1], [1 2],
- [[final: 0 0 1]],
+ [AT_PARAM_IF([final: 0 0 1])],
[15],
[AT_JAVA_IF([1.3-1.4], [1.3])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] ['\n'])]])
_AT_CHECK_CALC_ERROR([$1], [1], [1//2],
- [[final: 0 0 1]],
+ [AT_PARAM_IF([final: 0 0 1])],
[20],
[AT_JAVA_IF([1.3-1.4], [1.3])[: syntax error on token ['/'] (expected: [number] ['-'] ['('] ['!'])]])
_AT_CHECK_CALC_ERROR([$1], [1], [error],
- [[final: 0 0 1]],
+ [AT_PARAM_IF([final: 0 0 1])],
[5],
[AT_JAVA_IF([1.1-1.2], [1.1])[: syntax error on token [invalid token] (expected: [number] ['-'] ['\n'] ['('] ['!'])]])
_AT_CHECK_CALC_ERROR([$1], [1], [1 = 2 = 3],
- [[final: 0 0 1]],
+ [AT_PARAM_IF([final: 0 0 1])],
[30],
[AT_LAC_IF(
[AT_JAVA_IF([1.7-1.8], [1.7])[: syntax error on token ['='] (expected: ['-'] ['+'] ['*'] ['/'] ['^'] ['\n'])]],
@@ -1102,12 +1145,12 @@ _AT_CHECK_CALC_ERROR([$1], [1], [1 = 2 = 3],
_AT_CHECK_CALC_ERROR([$1], [1],
[
+1],
- [[final: 0 0 1]],
+ [AT_PARAM_IF([final: 0 0 1])],
[20],
[AT_JAVA_IF([2.1-2.2], [2.1])[: syntax error on token ['+'] (expected: ]AT_TOKEN_TRANSLATE_IF([[[end of file]]], [[[end of input]]])[ [number] ['-'] ['\n'] ['('] ['!'])]])
# Exercise error messages with EOF: work on an empty file.
_AT_CHECK_CALC_ERROR([$1], [1], [/dev/null],
- [[final: 0 0 1]],
+ [AT_PARAM_IF([final: 0 0 1])],
[4],
[[1.1: syntax error on token ]AT_TOKEN_TRANSLATE_IF([[[end of file]]], [[[end of input]]])[ (expected: [number] ['-'] ['\n'] ['('] ['!'])]])
@@ -1129,7 +1172,7 @@ _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null],
#
_AT_CHECK_CALC_ERROR([$1], [0],
[() + (1 + 1 + 1 +) + (* * *) + (1 * 2 * *) = 1],
- [[final: 4444 0 5]],
+ [AT_PARAM_IF([final: 4444 0 5])],
[250],
[AT_JAVA_IF([1.2-1.3], [1.2])[: syntax error on token [')'] (expected: [number] ['-'] ['('] ['!'])
]AT_JAVA_IF([1.18-1.19], [1.18])[: syntax error on token [')'] (expected: [number] ['-'] ['('] ['!'])
@@ -1140,13 +1183,13 @@ _AT_CHECK_CALC_ERROR([$1], [0],
# 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], [(!) + (1 2) = 1],
- [[final: 2222 0 2]],
+ [AT_PARAM_IF([final: 2222 0 2])],
[102],
[AT_JAVA_IF([1.10-1.11], [1.10])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] [')'])
]AT_JAVA_IF([1.1-1.16], [1.1-15])[: error: 2222 != 1]])
_AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (1 2) = 1],
- [[final: 2222 0 3]],
+ [AT_PARAM_IF([final: 2222 0 3])],
[113],
[AT_JAVA_IF([1.4-1.5], [1.4])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
]AT_JAVA_IF([1.12-1.13], [1.12])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] [')'])
@@ -1155,7 +1198,7 @@ _AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (1 2) = 1],
# Check that yyerrok works properly: second error is not reported,
# third and fourth are. Parse status is successful.
_AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)],
- [[final: 3333 0 3]],
+ [AT_PARAM_IF([final: 3333 0 3])],
[113],
[AT_JAVA_IF([1.2-1.3], [1.2])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
]AT_JAVA_IF([1.10-1.11], [1.10])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
@@ -1168,31 +1211,48 @@ _AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)],
# error-recovery without issuing a second error message.
_AT_CHECK_CALC_ERROR([$1], [0], [(#) + (#) = 2222],
- [[final: 2222 0 0]],
+ [AT_PARAM_IF([final: 2222 0 0])],
[102],
[[1.2: syntax error: invalid character: '#'
1.8: syntax error: invalid character: '#']])
_AT_CHECK_CALC_ERROR([$1], [0], [(1 + #) = 1111],
- [[final: 1111 0 0]],
+ [AT_PARAM_IF([final: 1111 0 0])],
[102],
[[1.6: syntax error: invalid character: '#']])
_AT_CHECK_CALC_ERROR([$1], [0], [(# + 1) = 1111],
- [[final: 1111 0 0]],
+ [AT_PARAM_IF([final: 1111 0 0])],
[102],
[[1.2: syntax error: invalid character: '#']])
_AT_CHECK_CALC_ERROR([$1], [0], [(1 + # + 1) = 1111],
- [[final: 1111 0 0]],
+ [AT_PARAM_IF([final: 1111 0 0])],
[102],
[[1.6: syntax error: invalid character: '#']])
_AT_CHECK_CALC_ERROR([$1], [0], [(1 + 1) / (1 - 1)],
- [[final: 2 0 1]],
+ [AT_PARAM_IF([final: 2 0 1])],
[102],
[AT_JAVA_IF([1.11-1.18], [1.11-17])[: error: null divisor]])
+# Multiple start symbols.
+AT_MULTISTART_IF([
+_AT_CHECK_CALC([--num], [[123]],
+ [[NUM => 123 (status: 0, errors: 0)]],
+ [AT_JAVA_IF([1014], [1017])])
+_AT_CHECK_CALC_ERROR([$1], [1], [1 + 2 * 3],
+ [NUM => 0 (status: 1, errors: 1)],
+ [102],
+ [[1.3: syntax error, unexpected '+', expecting end of file]],
+ [--num])
+
+_AT_CHECK_CALC([--exp], [[1 + 2 * 3]],
+ [[exp => 7 (status: 0, errors: 0)]],
+ [AT_JAVA_IF([1014], [1017])])
+])
+
+
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
@@ -1246,13 +1306,18 @@ AT_CHECK_CALC_LALR([%no-lines %define api.pure %define parse.error detailed %deb
AT_CHECK_CALC_LALR([%no-lines %define api.pure %define parse.error verbose %debug %locations %header %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result}{int *count}{int *nerrs}])
AT_CHECK_CALC_LALR([%no-lines %define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result}{int *count}{int *nerrs}])
-
+# parse.error custom.
AT_CHECK_CALC_LALR([%define parse.error custom])
AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc}])
AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc} %parse-param {semantic_value *result}{int *count}{int *nerrs}])
AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc} %parse-param {semantic_value *result}{int *count}{int *nerrs} %define api.push-pull both %define api.pure full])
AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc} %parse-param {semantic_value *result}{int *count}{int *nerrs} %define api.push-pull both %define api.pure full %define parse.lac full])
+# multistart.
+AT_CHECK_CALC_LALR([%start input exp NUM %define api.value.type union])
+AT_CHECK_CALC_LALR([%start input exp NUM %define api.value.type union %locations %define parse.error detailed])
+
+
# ---------------- #
# GLR Calculator. #
# ---------------- #