diff options
author | Akim Demaille <akim.demaille@gmail.com> | 2020-09-27 13:07:57 +0200 |
---|---|---|
committer | Akim Demaille <akim.demaille@gmail.com> | 2020-09-28 19:26:53 +0200 |
commit | 9b18cac96bdad4a71b546a3c16ca4b7e25c0a657 (patch) | |
tree | 28512cdb98f6d0825f6c369ff4aee67d0bd69849 /tests/calc.at | |
parent | c19c1e7ec5c579c66190ec35b010f6d3dca73f98 (diff) | |
download | bison-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.at | 165 |
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. # # ---------------- # |