1 # Simple calculator. -*- Autotest -*-
3 # Copyright (C) 2000-2015, 2018-2021 Free Software Foundation, Inc.
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <https://www.gnu.org/licenses/>.
18 ## ---------------------------------------------------- ##
19 ## Compile the grammar described in the documentation. ##
20 ## ---------------------------------------------------- ##
23 m4_pushdef([AT_CALC_MAIN], [AT_LANG_DISPATCH([$0], $@)])
24 m4_pushdef([AT_CALC_YYLEX], [AT_LANG_DISPATCH([$0], $@)])
31 # _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
32 # -----------------------------------------------
33 # Produce 'calc.y' and, if %header was specified, 'calc-lex.c' or
36 # Don't call this macro directly, because it contains some occurrences
37 # of '$1' etc. which will be interpreted by m4. So you should call it
38 # with $1, $2, and $3 as arguments, which is what AT_DATA_CALC_Y does.
40 # When %header is not passed, generate a single self-contained file.
41 # Otherwise, generate three: calc.y with the parser, calc-lex.c with
42 # the scanner, and calc-main.c with "main()". This is in order to
43 # stress the use of the generated parser header. To avoid code
44 # duplication, AT_CALC_YYLEX and AT_CALC_MAIN contain the body of these
46 m4_pushdef([_AT_DATA_CALC_Y],
47 [m4_if([$1$2$3], $[1]$[2]$[3], [],
48 [m4_fatal([$0: Invalid arguments: $@])])dnl
49 AT_LANG_DISPATCH([$0], $@)])
58 m4_define([AT_CALC_MAIN(c)],
60 #include <stdlib.h> /* exit */
61 #include <string.h> /* strcmp */
67 /* A C++ ]AT_NAME_PREFIX[parse that simulates the C signature. */
69 ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([semantic_value *result, int *count, int *nerrs]))[
71 ]AT_NAME_PREFIX[::parser parser]AT_PARAM_IF([ (result, count, nerrs)])[;
72 #if ]AT_API_PREFIX[DEBUG
73 parser.set_debug_level (1);
75 return parser.parse ();
80 /* Value of the last computation. */
81 semantic_value global_result = 0;
82 /* Total number of computations. */
84 /* Total number of errors. */
88 # define EX_NOINPUT 66
92 open_file (const char *file)
94 FILE *res = (file && *file && strcmp (file, "-")) ? fopen (file, "r") : stdin;
103 /* A C main function. */
105 main (int argc, const char **argv)
107 semantic_value result = 0;
112 /* This used to be alarm (10), but that isn't enough time for a July
113 1995 vintage DEC Alphastation 200 4/100 system, according to
114 Nelson H. F. Beebe. 100 seconds was enough for regular users,
115 but the Hydra build farm, which is heavily loaded needs more. */
119 ]AT_CXX_IF([], [AT_DEBUG_IF([ ]AT_NAME_PREFIX[debug = 1;])])[
123 for (i = 1; i < argc; ++i)
126 if (!strcmp (argv[i], "--exp") && i+1 < argc)
128 input = open_file (argv[i+1]);
130 ]AT_NAME_PREFIX[parse_exp_t res = ]AT_NAME_PREFIX[parse_exp ();
131 printf ("exp => %d (status: %d, errors: %d)\n",
132 res.yystatus == 0 ? res.yyvalue : 0, res.yystatus, res.yynerrs);
133 status = res.yystatus;
136 else if (!strcmp (argv[i], "--num") && i+1 < argc)
138 input = open_file (argv[i+1]);
140 ]AT_NAME_PREFIX[parse_NUM_t res = ]AT_NAME_PREFIX[parse_NUM ();
141 printf ("NUM => %d (status: %d, errors: %d)\n",
142 res.yystatus == 0 ? res.yyvalue : 0, res.yystatus, res.yynerrs);
143 status = res.yystatus;
148 input = open_file (argv[i]);
149 status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count, &nerrs]])[);
151 if (input != stdin && fclose (input))
156 assert (global_result == result); (void) result;
157 assert (global_count == count); (void) count;
158 assert (global_nerrs == nerrs); (void) nerrs;
159 printf ("final: %d %d %d\n", global_result, global_count, global_nerrs);]])[
166 m4_define([AT_CALC_YYLEX(c)],
169 ]AT_YYLEX_DECLARE_EXTERN[
172 static AT_YYLTYPE last_yylloc;
175 get_char (]AT_YYLEX_FORMALS[)
177 int res = getc (input);
180 last_yylloc = AT_LOC;
184 AT_LOC_LAST_COLUMN = 1;
187 AT_LOC_LAST_COLUMN++;
193 unget_char (]AT_YYLEX_PRE_FORMALS[ int c)
197 /* Wrong when C == '\n'. */
198 AT_LOC = last_yylloc;
204 read_integer (]AT_YYLEX_FORMALS[)
206 int c = get_char (]AT_YYLEX_ARGS[);
212 res = 10 * res + (c - '0');
213 c = get_char (]AT_YYLEX_ARGS[);
216 unget_char (]AT_YYLEX_PRE_ARGS[ c);
222 /*---------------------------------------------------------------.
223 | Lexical analyzer returns an integer on the stack and the token |
224 | NUM, or the ASCII character read if not a number. Skips all |
225 | blanks and tabs, returns 0 for EOF. |
226 `---------------------------------------------------------------*/
231 /* Skip white spaces. */
235 AT_LOC_FIRST_COLUMN = AT_LOC_LAST_COLUMN;
236 AT_LOC_FIRST_LINE = AT_LOC_LAST_LINE;
239 while ((c = get_char (]AT_YYLEX_ARGS[)) == ' '
241 || (ignore_eol && c == '\n'));
243 /* Process numbers. */
246 unget_char (]AT_YYLEX_PRE_ARGS[ c);
247 ]AT_VAL[.]AT_VALUE_UNION_IF([NUM], [ival])[ = read_integer (]AT_YYLEX_ARGS[);
248 return ]AT_TOKEN([NUM])[;
251 /* Return end-of-file. */
253 return ]AT_TOKEN([CALC_EOF])[;
255 /* An explicit error raised by the scanner. */
258 fprintf (stderr, "%d.%d: ",
259 AT_LOC_FIRST_LINE, AT_LOC_FIRST_COLUMN);])[
260 fputs ("syntax error: invalid character: '#'\n", stderr);
261 return ]AT_TOKEN(AT_API_PREFIX[][error])[;
264 /* Return single chars. */
270 m4_define([_AT_DATA_CALC_Y(c)],
271 [AT_DATA_GRAMMAR([calc.y],
272 [[/* Infix notation calculator--calc */
276 ]AT_LOCATION_TYPE_SPAN_IF([[
289 # define YYLLOC_DEFAULT(Current, Rhs, N) \
293 (Current).first = YYRHSLOC (Rhs, 1).first; \
294 (Current).last = YYRHSLOC (Rhs, N).last; \
298 (Current).first = (Current).last = YYRHSLOC (Rhs, 0).last; \
304 void location_print (FILE *o, Span s);
305 #define LOCATION_PRINT location_print
309 /* Exercise pre-prologue dependency to %union. */
310 typedef int semantic_value;
313 ]AT_VALUE_UNION_IF([],
314 [[/* Exercise %union. */
319 %printer { ]AT_CXX_IF([[yyo << $$]],
320 [[fprintf (yyo, "%d", $$)]])[; } <]AT_VALUE_UNION_IF([int], [ival])[>;
327 /* Whether \n is a blank. */
328 extern int ignore_eol;
329 extern semantic_value global_result;
330 extern int global_count;
331 extern int global_nerrs;
342 static int power (int base, int exponent);
345 ]AT_YYLEX_DECLARE_EXTERN[
347 ]AT_TOKEN_TRANSLATE_IF([[
353 if (strcmp (cp, "end of input") == 0)
354 return "end of file";
355 else if (strcmp (cp, "number") == 0)
363 ]AT_LOCATION_TYPE_SPAN_IF([[
366 @$.first.l = @$.first.c = 1;
370 /* Bison Declarations */
371 %token CALC_EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of file")], ["end of input"])[
372 %token <]AT_VALUE_UNION_IF([int], [ival])[> NUM "number"
373 %type <]AT_VALUE_UNION_IF([int], [ival])[> exp
375 %nonassoc '=' /* comparison */
378 %precedence NEG /* negation--unary minus */
379 %right '^' /* exponentiation */
381 /* Grammar follows */
385 | input line { ]AT_PARAM_IF([++*count; ++global_count;])[ }
390 | exp '\n' { ]AT_PARAM_IF([*result = global_result = $1;], [USE ($1);])[ }
397 if ($1 != $3)]AT_LANG_CASE(
401 snprintf (buf, sizeof buf, "error: %d != %d", $1, $3);]AT_YYERROR_ARG_LOC_IF([[
402 yyerror (&@$, ]AT_PARAM_IF([result, count, nerrs, ])[buf);]], [[
404 YYLTYPE old_yylloc = yylloc;
406 yyerror (]AT_PARAM_IF([result, count, nerrs, ])[buf);
414 snprintf (buf, sizeof buf, "error: %d != %d", $1, $3);
415 ]AT_GLR_IF([[yyparser.]])[error (]AT_LOCATION_IF([[@$, ]])[buf);
419 | exp '+' exp { $$ = $1 + $3; }
420 | exp '-' exp { $$ = $1 - $3; }
421 | exp '*' exp { $$ = $1 * $3; }
424 if ($3 == 0)]AT_LANG_CASE(
426 {]AT_YYERROR_ARG_LOC_IF([[
427 yyerror (&@3, ]AT_PARAM_IF([result, count, nerrs, ])["error: null divisor");]], [[
429 YYLTYPE old_yylloc = yylloc;
431 yyerr][or (]AT_PARAM_IF([result, count, nerrs, ])["error: null divisor");
438 ]AT_GLR_IF([[yyparser.]])[err][or (]AT_LOCATION_IF([[@3, ]])["error: null divisor");
443 | '-' exp %prec NEG { $$ = -$2; }
444 | exp '^' exp { $$ = power ($1, $3); }
445 | '(' exp ')' { $$ = $2; }
446 | '(' error ')' { $$ = 1111; yyerrok; }
447 | '-' error { $$ = 0; YYERROR; }
448 | '!' '!' { $$ = 0; YYERROR; }
449 | '!' '+' { $$ = 0; YYACCEPT; }
450 | '!' '-' { $$ = 0; YYABORT; }]AT_C_IF([[
451 | '!' '*' { $$ = 0; YYNOMEM; }]])[
456 power (int base, int exponent)
459 assert (0 <= exponent);
460 for (/* Niente */; exponent; --exponent)
465 ]AT_LOCATION_TYPE_SPAN_IF([AT_CXX_IF([[
470 operator<< (std::ostream& o, const Span& s)
472 o << s.first.l << '.' << s.first.c;
473 if (s.first.l != s.last.l)
474 o << '-' << s.last.l << '.' << s.last.c - 1;
475 else if (s.first.c != s.last.c - 1)
476 o << '-' << s.last.c - 1;
482 location_print (FILE *o, Span s)
484 fprintf (o, "%d.%d", s.first.l, s.first.c);
485 if (s.first.l != s.last.l)
486 fprintf (o, "-%d.%d", s.last.l, s.last.c - 1);
487 else if (s.first.c != s.last.c - 1)
488 fprintf (o, "-%d", s.last.c - 1);
496 AT_HEADER_IF([AT_DATA_SOURCE([[calc-lex.]AT_LANG_EXT],
497 [[#include "calc.]AT_LANG_HDR["
500 AT_DATA_SOURCE([[calc-main.]AT_LANG_EXT],
501 [[#include "calc.]AT_LANG_HDR["
505 ])# _AT_DATA_CALC_Y(c)
513 m4_copy([AT_CALC_MAIN(c)], [AT_CALC_MAIN(c++)])
514 m4_copy([AT_CALC_YYLEX(c)], [AT_CALC_YYLEX(c++)])
515 m4_copy([_AT_DATA_CALC_Y(c)], [_AT_DATA_CALC_Y(c++)])
522 # AT_YYLEX_RETURN_VAL
523 # -------------------
524 # Produce the return value for yylex().
525 m4_define([AT_YYLEX_RETURN_VAL],
528 [[Symbol.]AT_TOKEN_PREFIX[$1](m4_ifval([$2], [$2])[]AT_LOCATION_IF([m4_ifval([$2], [, ])[location]])[);]],
529 [[Symbol(TokenKind.]AT_TOKEN_PREFIX[$1]m4_ifval([$2], [, $2])[]AT_LOCATION_IF([[, location]])[);]])]
533 m4_define([AT_CALC_MAIN(d)],
534 [[int main (string[] args)
536 semantic_value result = 0;
539 File input = args.length == 2 ? File (args[1], "r") : stdin;
540 auto l = calcLexer (input);
541 auto p = new YYParser (l);]AT_DEBUG_IF([[
542 p.setDebugLevel (1);]])[
547 m4_define([AT_CALC_YYLEX(d)],
548 [[import std.range.primitives;
551 auto calcLexer(R)(R range)
552 if (isInputRange!R && is (ElementType!R : dchar))
554 return new CalcLexer!R(range);
557 auto calcLexer (File f)
559 import std.algorithm : map, joiner;
560 import std.utf : byDchar;
562 return f.byChunk(1024) // avoid making a syscall roundtrip per char
563 .map!(chunk => cast(char[]) chunk) // because byChunk returns ubyte[]
564 .joiner // combine chunks into a single virtual range of char
565 .calcLexer; // forward to other overload
568 class CalcLexer(R) : Lexer
569 if (isInputRange!R && is (ElementType!R : dchar))
573 this(R r) { input = r; }
582 import std.uni : isNumber;
583 while (input.front.isNumber)
585 res = res * 10 + (input.front - '0');]AT_LOCATION_IF([[
586 location.end.column += 1;]])[
596 import std.uni : isWhite, isNumber;
598 // Skip initial spaces
599 while (!input.empty && input.front != '\n' && isWhite (input.front))
601 input.popFront;]AT_LOCATION_IF([[
602 location.end.column += 1;]])[
608 ]AT_YYLEX_RETURN_VAL([EOF])[
610 if (input.front.isNumber)
611 ]AT_YYLEX_RETURN_VAL([NUM], [parseInt])[
613 // Individual characters
614 auto c = input.front;]AT_LOCATION_IF([[
617 location.end.line += 1;
618 location.end.column = 1;
621 location.end.column += 1;]])[
624 // An explicit error raised by the scanner. */
627 stderr.writeln (]AT_LOCATION_IF([location, ": ", ])["syntax error: invalid character: '#'");
628 ]AT_YYLEX_RETURN_VAL([YYerror])[
633 case '+': ]AT_YYLEX_RETURN_VAL([PLUS])[
634 case '-': ]AT_YYLEX_RETURN_VAL([MINUS])[
635 case '*': ]AT_YYLEX_RETURN_VAL([STAR])[
636 case '/': ]AT_YYLEX_RETURN_VAL([SLASH])[
637 case '(': ]AT_YYLEX_RETURN_VAL([LPAR])[
638 case ')': ]AT_YYLEX_RETURN_VAL([RPAR])[
639 case '\n': ]AT_YYLEX_RETURN_VAL([EOL])[
640 case '=': ]AT_YYLEX_RETURN_VAL([EQUAL])[
641 case '^': ]AT_YYLEX_RETURN_VAL([POW])[
642 case '!': ]AT_YYLEX_RETURN_VAL([NOT])[
643 default: ]AT_YYLEX_RETURN_VAL([YYUNDEF])[
649 m4_define([_AT_DATA_CALC_Y(d)],
650 [AT_DATA_GRAMMAR([calc.y],
651 [[/* Infix notation calculator--calc */
654 alias semantic_value = int;
656 /* Exercise %union. */
657 ]AT_UNION_IF([[]], [[%union
661 %printer { yyo.write($$); } <]AT_UNION_IF([[int]], [[ival]])[>;
664 ]AT_TOKEN_TRANSLATE_IF([[
665 static string _(string s)
670 return "end of file";
680 /* Bison Declarations */
681 %token EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of file")], ["end of input"])[
682 %token <]AT_UNION_IF([[int]], [[ival]])[> NUM "number"
683 %type <]AT_UNION_IF([[int]], [[ival]])[> exp
696 %nonassoc "=" /* comparison */
699 %precedence NEG /* negation--unary minus */
700 %right "^" /* exponentiation */
702 /* Grammar follows */
706 | input line { ]AT_PARAM_IF([++*count; ++global_count;])[ }
711 | exp EOL { ]AT_PARAM_IF([*result = global_result = $1;])[ }
719 yyerror (]AT_LOCATION_IF([[@$, ]])[format ("error: %d != %d", $1, $3));
722 | exp "+" exp { $$ = $1 + $3; }
723 | exp "-" exp { $$ = $1 - $3; }
724 | exp "*" exp { $$ = $1 * $3; }
728 yyerror (]AT_LOCATION_IF([[@3, ]])["error: null divisor");
732 | "-" exp %prec NEG { $$ = -$2; }
733 | exp "^" exp { $$ = power ($1, $3); }
734 | "(" exp ")" { $$ = $2; }
735 | "(" error ")" { $$ = 1111; yyerrok(); }
736 | "-" error { $$ = 0; return YYERROR; }
737 | "!" "!" { $$ = 0; return YYERROR; }
738 | "!" "+" { $$ = 0; return YYACCEPT; }
739 | "!" "-" { $$ = 0; return YYABORT; }
744 power (int base, int exponent)
747 assert (0 <= exponent);
748 for (/* Niente */; exponent; --exponent)
755 ])# _AT_DATA_CALC_Y(d)
763 m4_define([AT_CALC_MAIN(java)],
764 [[public static void main (String[] args) throws IOException
766 Calc p = new Calc (System.in);]], [[
767 CalcLexer l = new CalcLexer (System.in);
768 Calc p = new Calc (l);]])AT_DEBUG_IF([[
769 p.setDebugLevel (1);]])[
770 boolean success = p.parse ();
776 m4_define([AT_CALC_YYLEX(java)],
777 [AT_LEXPARAM_IF([[%code lexer {]],
778 [[%code epilogue { class CalcLexer implements Calc.Lexer {]])[
779 StreamTokenizer st;]AT_LOCATION_IF([[
780 PositionReader reader;]])[
782 public ]AT_LEXPARAM_IF([[YYLexer]], [[CalcLexer]])[ (InputStream is)
784 reader = new PositionReader (new InputStreamReader (is));
785 st = new StreamTokenizer (reader);]], [[
786 st = new StreamTokenizer (new InputStreamReader (is));]])[
788 st.eolIsSignificant (true);
789 st.wordChars ('0', '9');
793 Position start = new Position (1, 0);
794 Position end = new Position (1, 0);
796 public Position getStartPos () {
797 return new Position (start);
800 public Position getEndPos () {
801 return new Position (end);
809 public Object getLVal () {
813 public int yylex() throws IOException {;]AT_LOCATION_IF([[
814 start.set(reader.getPosition());]])[
815 int tkind = st.nextToken();]AT_LOCATION_IF([[
816 end.set(reader.getPosition());]])[
819 case StreamTokenizer.TT_EOF:
821 case StreamTokenizer.TT_EOL:;]AT_LOCATION_IF([[
825 case StreamTokenizer.TT_WORD:
826 yylval = Integer.parseInt(st.sval);]AT_LOCATION_IF([[
827 end.set(reader.getPreviousPosition());]])[
832 System.err.println(]AT_LOCATION_IF([[start + ": " + ]])["syntax error: invalid character: '#'");
838 ]AT_LEXPARAM_IF([], [[}]])[
842 m4_define([_AT_DATA_CALC_Y(java)],
843 [AT_DATA_GRAMMAR([Calc.y],
844 [[/* Infix notation calculator--calc */
845 %define api.prefix {Calc}
846 %define api.parser.class {Calc}
851 %code imports {]AT_LOCATION_IF([[
852 import java.io.BufferedReader;]])[
853 import java.io.IOException;
854 import java.io.InputStream;
855 import java.io.InputStreamReader;
856 import java.io.Reader;
857 import java.io.StreamTokenizer;
863 ]AT_TOKEN_TRANSLATE_IF([[
864 static String i18n(String s)
866 if (s.equals ("end of input"))
867 return "end of file";
868 else if (s.equals ("number"))
876 /* Bison Declarations */
877 %token CALC_EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of file")], ["end of input"])[
878 %token <Integer> NUM "number"
881 %nonassoc '=' /* comparison */
884 %precedence NEG /* negation--unary minus */
885 %right '^' /* exponentiation */
887 /* Grammar follows */
903 if ($1.intValue () != $3.intValue ())
904 yyerror (]AT_LOCATION_IF([[@$, ]])["error: " + $1 + " != " + $3);
906 | exp '+' exp { $$ = $1 + $3; }
907 | exp '-' exp { $$ = $1 - $3; }
908 | exp '*' exp { $$ = $1 * $3; }
911 if ($3.intValue () == 0)
912 yyerror (]AT_LOCATION_IF([[@3, ]])["error: null divisor");
916 | '-' exp %prec NEG { $$ = -$2; }
917 | exp '^' exp { $$ = (int) Math.pow ($1, $3); }
918 | '(' exp ')' { $$ = $2; }
919 | '(' error ')' { $$ = 1111; }
920 | '-' error { $$ = 0; return YYERROR; }
921 | '!' '!' { $$ = 0; return YYERROR; }
922 | '!' '+' { $$ = 0; return YYACCEPT; }
923 | '!' '-' { $$ = 0; return YYABORT; }
928 ]AT_JAVA_POSITION_DEFINE])[
930 ])# _AT_DATA_JAVA_CALC_Y
935 ## ------------------ ##
936 ## Calculator tests. ##
937 ## ------------------ ##
940 # AT_DATA_CALC_Y([BISON-OPTIONS])
941 # -------------------------------
942 # Produce 'calc.y' and, if %header was specified, 'calc-lex.c' or
944 m4_define([AT_DATA_CALC_Y],
945 [_AT_DATA_CALC_Y($[1], $[2], $[3], [$1])
949 # _AT_CHECK_CALC(CALC-OPTIONS, INPUT, [STDOUT], [NUM-STDERR-LINES])
950 # -----------------------------------------------------------------
951 # Run 'calc' on INPUT and expect no STDOUT nor STDERR.
953 # If BISON-OPTIONS contains '%debug' but not '%glr-parser', then
954 # NUM-STDERR-LINES is the number of expected lines on stderr.
955 # Currently this is ignored, though, since the output format is fluctuating.
957 # We don't count GLR's traces yet, since its traces are somewhat
958 # different from LALR's. Likewise for D.
960 # The push traces are the same, except for "Return for a new token", don't
962 m4_define([_AT_CHECK_CALC],
967 sed -e 's/^/ | /' <input
969 [AT_JAVA_PARSER_CHECK([Calc $1 < input], 0, [m4_ifvaln(m4_quote($3), [$3])], [stderr])],
970 [AT_PARSER_CHECK([calc $1 input], 0, [m4_ifvaln(m4_quote($3), [$3])], [stderr])])
971 AT_LANG_MATCH([c\|c++\|java],
973 [AT_CHECK([grep -c -v -E 'Return for a new token:|LAC:' stderr],
975 [m4_n([AT_DEBUG_IF([$4], [0])])])])])
979 # _AT_CHECK_CALC_ERROR($1 = BISON-OPTIONS, $2 = EXIT-STATUS, $3 = INPUT,
981 # $5 = [NUM-STDERR-LINES],
982 # $6 = [CUSTOM-ERROR-MESSAGE])
983 # $7 = [CALC-OPTIONS])
984 # ----------------------------------------------------------------------
985 # Run 'calc' on INPUT, and expect a 'syntax error' message.
987 # If INPUT starts with a slash, it is used as absolute input file name,
988 # otherwise as contents.
990 # NUM-STDERR-LINES is the number of expected lines on stderr.
991 # If BISON-OPTIONS contains '%debug' but not '%glr', then NUM-STDERR-LINES
992 # is the number of expected lines on stderr.
994 # CUSTOM-ERROR-MESSAGE is the expected error message when parse.error
995 # is 'custom' and locations are enabled. Other expected formats are
997 m4_define([_AT_CHECK_CALC_ERROR],
998 [m4_bmatch([$3], [^/],
1000 [AT_JAVA_PARSER_CHECK([Calc $7 < $3], $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])],
1001 [AT_PARSER_CHECK([calc $7 $3], $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])])],
1006 sed -e 's/^/ | /' <input
1008 [AT_JAVA_PARSER_CHECK([Calc $7 < input], $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])],
1009 [AT_PARSER_CHECK([calc $7 input], $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])])
1012 # Normalize the observed and expected error messages, depending upon the
1014 # 1. Remove the traces from observed.
1035 # 2. Create the reference error message.
1039 # 3. If locations are not used, remove them.
1040 AT_YYERROR_SEES_LOC_IF([],
1041 [[sed 's/^[-0-9.]*: //' expout >at-expout
1042 mv at-expout expout]])
1044 # 4. If parse.error is not custom, turn the expected message to
1045 # the traditional one.
1046 AT_ERROR_CUSTOM_IF([], [
1047 AT_PERL_REQUIRE([[-pi -e 'use strict;
1048 s{syntax error on token \[(.*?)\] \(expected: (.*)\)}
1051 my @exps = $][2 =~ /\[(.*?)\]/g;]AT_D_IF([[
1052 # In the case of D, there are no single quotes around the symbols.
1053 $unexp =~ s/'"'(.)'"'/$][1/g;
1054 s/'"'(.)'"'/$][1/g for @exps;]])[
1055 ($][#exps && $][#exps < 4)
1056 ? "syntax error, unexpected $unexp, expecting @{[join(\" or \", @exps)]}"
1057 : "syntax error, unexpected $unexp";
1062 # 5. If parse.error is simple, strip the', unexpected....' part.
1064 [[sed 's/syntax error, .*$/syntax error/' expout >at-expout
1065 mv at-expout expout]])
1067 # 6. Actually check.
1068 AT_CHECK([cat stderr], 0, [expout])
1072 # AT_CHECK_SPACES([FILES])
1073 # ------------------------
1074 # Make sure we did not introduce bad spaces. Checked here because all
1075 # the skeletons are (or should be) exercised here.
1076 m4_define([AT_CHECK_SPACES],
1077 [AT_PERL_CHECK([-ne '
1079 print "$ARGV:$.: {$_}\n"
1080 if (# No starting/ending empty lines.
1081 (eof || $. == 1) && /^\s*$/
1082 # No trailing space.
1091 # AT_CHECK_JAVA_GREP(FILE, [LINE], [COUNT=1])
1092 # -------------------------------------------
1093 # Check that FILE contains exactly COUNT lines matching ^LINE$
1094 # with grep. Unquoted so that COUNT can be a shell expression.
1095 m4_define([AT_CHECK_JAVA_GREP],
1096 [AT_CHECK_UNQUOTED([grep -c '^$2$' $1], [ignore], [m4_default([$3], [1])
1100 # AT_CHECK_CALC([BISON-OPTIONS], [COMPILER-OPTIONS])
1101 # --------------------------------------------------
1102 # Start a testing chunk which compiles 'calc' grammar with
1103 # BISON-OPTIONS, and performs several tests over the parser.
1104 m4_define([AT_CHECK_CALC],
1105 [m4_ifval([$3], [m4_fatal([$0: expected at most two arguments])])
1107 # We use integers to avoid dependencies upon the precision of doubles.
1108 AT_SETUP([Calculator $1 $2])
1110 AT_BISON_OPTION_PUSHDEFS([$1])
1112 AT_DATA_CALC_Y([$1])
1113 AT_FULL_COMPILE(AT_JAVA_IF([[Calc]], [[calc]]), AT_HEADER_IF([[lex], [main]], [[], []]), [$2], [-Wno-deprecated])
1116 [# No direct calls to malloc/free.
1117 AT_CHECK([[$EGREP '(malloc|free) *\(' calc.[ch] | $EGREP -v 'INFRINGES ON USER NAME SPACE']],
1120 AT_PUSH_IF([AT_JAVA_IF(
1121 [# Verify that this is a push parser.
1122 AT_CHECK_JAVA_GREP([[Calc.java]],
1123 [[.*public void push_parse_initialize ().*]])])])
1125 AT_CHECK_SPACES([AT_JAVA_IF([Calc], [calc]).AT_LANG_EXT AT_HEADER_IF([AT_JAVA_IF([Calc], [calc]).AT_LANG_HDR])])
1127 # Test the precedences.
1128 # The Java traces do not show the clean up sequence at the end,
1129 # since it does not support %destructor.
1144 [AT_PARAM_IF([final: 64 12 0])],
1145 [AT_JAVA_IF([1014], [1017])])
1147 # Some syntax errors.
1148 _AT_CHECK_CALC_ERROR([$1], [1], [1 2],
1149 [AT_PARAM_IF([final: 0 0 1])],
1151 [AT_JAVA_IF([1.3-1.4], [1.3])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] ['\n'])]])
1152 _AT_CHECK_CALC_ERROR([$1], [1], [1//2],
1153 [AT_PARAM_IF([final: 0 0 1])],
1155 [AT_JAVA_IF([1.3-1.4], [1.3])[: syntax error on token ['/'] (expected: [number] ['-'] ['('] ['!'])]])
1156 _AT_CHECK_CALC_ERROR([$1], [1], [error],
1157 [AT_PARAM_IF([final: 0 0 1])],
1159 [AT_JAVA_IF([1.1-1.2], [1.1])[: syntax error on token [invalid token] (expected: [number] ['-'] ['\n'] ['('] ['!'])]])
1160 _AT_CHECK_CALC_ERROR([$1], [1], [1 = 2 = 3],
1161 [AT_PARAM_IF([final: 0 0 1])],
1164 [AT_JAVA_IF([1.7-1.8], [1.7])[: syntax error on token ['='] (expected: ['-'] ['+'] ['*'] ['/'] ['^'] ['\n'])]],
1165 [AT_JAVA_IF([1.7-1.8], [1.7])[: syntax error on token ['='] (expected: ['-'] ['+'] ['*'] ['/'] ['^'])]])])
1166 _AT_CHECK_CALC_ERROR([$1], [1],
1169 [AT_PARAM_IF([final: 0 0 1])],
1171 [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'] ['('] ['!'])]])
1172 # Exercise error messages with EOF: work on an empty file.
1173 _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null],
1174 [AT_PARAM_IF([final: 0 0 1])],
1176 [[1.1: syntax error on token ]AT_TOKEN_TRANSLATE_IF([[[end of file]]], [[[end of input]]])[ (expected: [number] ['-'] ['\n'] ['('] ['!'])]])
1178 # Exercise the error token: without it, we die at the first error,
1181 # - have several errors which exercise different shift/discardings
1182 # - (): nothing to pop, nothing to discard
1183 # - (1 + 1 + 1 +): a lot to pop, nothing to discard
1184 # - (* * *): nothing to pop, a lot to discard
1185 # - (1 + 2 * *): some to pop and discard
1187 # - test the action associated to 'error'
1189 # - check the lookahead that triggers an error is not discarded
1190 # when we enter error recovery. Below, the lookahead causing the
1191 # first error is ")", which is needed to recover from the error and
1192 # produce the "0" that triggers the "0 != 1" error.
1194 _AT_CHECK_CALC_ERROR([$1], [0],
1195 [() + (1 + 1 + 1 +) + (* * *) + (1 * 2 * *) = 1],
1196 [AT_PARAM_IF([final: 4444 0 5])],
1198 [AT_JAVA_IF([1.2-1.3], [1.2])[: syntax error on token [')'] (expected: [number] ['-'] ['('] ['!'])
1199 ]AT_JAVA_IF([1.18-1.19], [1.18])[: syntax error on token [')'] (expected: [number] ['-'] ['('] ['!'])
1200 ]AT_JAVA_IF([1.23-1.24], [1.23])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1201 ]AT_JAVA_IF([1.41-1.42], [1.41])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1202 ]AT_JAVA_IF([1.1-1.47], [1.1-46])[: error: 4444 != 1]])
1204 # The same, but this time exercising explicitly triggered syntax errors.
1205 # POSIX says the lookahead causing the error should not be discarded.
1206 _AT_CHECK_CALC_ERROR([$1], [0], [(!!) + (1 2) = 1],
1207 [AT_PARAM_IF([final: 2222 0 2])],
1209 [AT_JAVA_IF([1.11-1.12], [1.11])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] [')'])
1210 ]AT_JAVA_IF([1.1-1.17], [1.1-16])[: error: 2222 != 1]])
1212 _AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (1 2) = 1],
1213 [AT_PARAM_IF([final: 2222 0 3])],
1215 [AT_JAVA_IF([1.4-1.5], [1.4])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1216 ]AT_JAVA_IF([1.12-1.13], [1.12])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] [')'])
1217 ]AT_JAVA_IF([1.1-1.18], [1.1-17])[: error: 2222 != 1]])
1219 # Check that yyerrok works properly: second error is not reported,
1220 # third and fourth are. Parse status is successful.
1221 _AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)],
1222 [AT_PARAM_IF([final: 3333 0 3])],
1224 [AT_JAVA_IF([1.2-1.3], [1.2])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1225 ]AT_JAVA_IF([1.10-1.11], [1.10])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1226 ]AT_JAVA_IF([1.16-1.17], [1.16])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])]])
1231 # !+ => YYACCEPT, !- => YYABORT, !! => YYERROR, !* => YYNOMEM.
1234 # Java lacks the traces at the end for cleaning the stack
1236 # -Cleanup: popping token '+' (1.1: )
1237 # -Cleanup: popping nterm exp (1.1: 7)
1238 _AT_CHECK_CALC([], [1 + 2 * 3 + !+ ++],
1239 [AT_PARAM_IF([final: 0 0 0])],
1240 [AT_JAVA_IF([77], [80])])
1242 _AT_CHECK_CALC_ERROR([$1], [1], [1 + 2 * 3 + !- ++],
1243 [AT_PARAM_IF([final: 0 0 0])],
1247 _AT_CHECK_CALC_ERROR([$1], [2], [1 + 2 * 3 + !* ++],
1248 [AT_PARAM_IF([final: 0 0 1])],
1250 [1.14: memory exhausted])])
1255 # Check that returning YYerror from the scanner properly enters
1256 # error-recovery without issuing a second error message.
1258 _AT_CHECK_CALC_ERROR([$1], [0], [(#) + (#) = 2222],
1259 [AT_PARAM_IF([final: 2222 0 0])],
1261 [[1.2: syntax error: invalid character: '#'
1262 1.8: syntax error: invalid character: '#']])
1264 _AT_CHECK_CALC_ERROR([$1], [0], [(1 + #) = 1111],
1265 [AT_PARAM_IF([final: 1111 0 0])],
1267 [[1.6: syntax error: invalid character: '#']])
1269 _AT_CHECK_CALC_ERROR([$1], [0], [(# + 1) = 1111],
1270 [AT_PARAM_IF([final: 1111 0 0])],
1272 [[1.2: syntax error: invalid character: '#']])
1274 _AT_CHECK_CALC_ERROR([$1], [0], [(1 + # + 1) = 1111],
1275 [AT_PARAM_IF([final: 1111 0 0])],
1277 [[1.6: syntax error: invalid character: '#']])
1279 _AT_CHECK_CALC_ERROR([$1], [0], [(1 + 1) / (1 - 1)],
1280 [AT_PARAM_IF([final: 2 0 1])],
1282 [AT_JAVA_IF([1.11-1.18], [1.11-17])[: error: null divisor]])
1284 # Multiple start symbols.
1286 _AT_CHECK_CALC([--num], [[123]],
1287 [[NUM => 123 (status: 0, errors: 0)]],
1288 [AT_JAVA_IF([1014], [1017])])
1289 _AT_CHECK_CALC_ERROR([$1], [1], [1 + 2 * 3],
1290 [NUM => 0 (status: 1, errors: 1)],
1292 [[1.3: syntax error, unexpected '+', expecting end of file]],
1295 _AT_CHECK_CALC([--exp], [[1 + 2 * 3]],
1296 [[exp => 7 (status: 0, errors: 0)]],
1297 [AT_JAVA_IF([1014], [1017])])
1301 AT_BISON_OPTION_POPDEFS
1309 # ----------------- #
1310 # LALR Calculator. #
1311 # ----------------- #
1313 AT_BANNER([[LALR(1) Calculator.]])
1315 # AT_CHECK_CALC_LALR([BISON-OPTIONS])
1316 # -----------------------------------
1317 # Start a testing chunk which compiles 'calc' grammar with
1318 # BISON-OPTIONS, and performs several tests over the parser.
1319 m4_define([AT_CHECK_CALC_LALR],
1320 [AT_CHECK_CALC($@)])
1322 AT_CHECK_CALC_LALR([%define parse.trace])
1324 AT_CHECK_CALC_LALR([%header])
1325 AT_CHECK_CALC_LALR([%debug %locations])
1326 AT_CHECK_CALC_LALR([%locations %define api.location.type {Span}])
1328 AT_CHECK_CALC_LALR([%name-prefix "calc"])
1329 AT_CHECK_CALC_LALR([%verbose])
1330 AT_CHECK_CALC_LALR([%yacc])
1331 AT_CHECK_CALC_LALR([%define parse.error detailed])
1332 AT_CHECK_CALC_LALR([%define parse.error verbose])
1334 AT_CHECK_CALC_LALR([%define api.pure full %locations])
1335 AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %locations])
1336 AT_CHECK_CALC_LALR([%define parse.error detailed %locations])
1338 AT_CHECK_CALC_LALR([%define parse.error detailed %locations %header %define api.prefix {calc} %verbose %yacc])
1339 AT_CHECK_CALC_LALR([%define parse.error detailed %locations %header %name-prefix "calc" %define api.token.prefix {TOK_} %verbose %yacc])
1341 AT_CHECK_CALC_LALR([%debug])
1342 AT_CHECK_CALC_LALR([%define parse.error detailed %debug %locations %header %name-prefix "calc" %verbose %yacc])
1343 AT_CHECK_CALC_LALR([%define parse.error detailed %debug %locations %header %define api.prefix {calc} %verbose %yacc])
1345 AT_CHECK_CALC_LALR([%define api.pure full %define parse.error detailed %debug %locations %header %name-prefix "calc" %verbose %yacc])
1346 AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %define parse.error detailed %debug %locations %header %define api.prefix {calc} %verbose %yacc])
1348 AT_CHECK_CALC_LALR([%define api.pure %define parse.error detailed %debug %locations %header %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1350 AT_CHECK_CALC_LALR([%no-lines %define api.pure %define parse.error detailed %debug %locations %header %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1351 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}])
1352 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}])
1354 # parse.error custom.
1355 AT_CHECK_CALC_LALR([%define parse.error custom])
1356 AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc}])
1357 AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc} %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1358 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])
1359 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])
1362 AT_CHECK_CALC_LALR([%start input exp NUM %define api.value.type union])
1363 AT_CHECK_CALC_LALR([%start input exp NUM %define api.value.type union %locations %define parse.error detailed])
1366 # ---------------- #
1368 # ---------------- #
1370 AT_BANNER([[GLR Calculator.]])
1372 m4_define([AT_CHECK_CALC_GLR],
1373 [AT_CHECK_CALC([%glr-parser] $@)])
1377 AT_CHECK_CALC_GLR([%header])
1378 AT_CHECK_CALC_GLR([%locations])
1379 AT_CHECK_CALC_GLR([%locations %define api.location.type {Span}])
1380 AT_CHECK_CALC_GLR([%name-prefix "calc"])
1381 AT_CHECK_CALC_GLR([%define api.prefix {calc}])
1382 AT_CHECK_CALC_GLR([%verbose])
1383 AT_CHECK_CALC_GLR([%define parse.error verbose])
1385 AT_CHECK_CALC_GLR([%define api.pure %locations])
1386 AT_CHECK_CALC_GLR([%define parse.error verbose %locations])
1388 AT_CHECK_CALC_GLR([%define parse.error custom %locations %header %name-prefix "calc" %verbose])
1389 AT_CHECK_CALC_GLR([%define parse.error detailed %locations %header %name-prefix "calc" %verbose])
1390 AT_CHECK_CALC_GLR([%define parse.error verbose %locations %header %name-prefix "calc" %verbose])
1392 AT_CHECK_CALC_GLR([%debug])
1393 AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %header %name-prefix "calc" %verbose])
1394 AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %header %define api.prefix {calc} %define api.token.prefix {TOK_} %verbose])
1396 AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %header %name-prefix "calc" %verbose])
1398 AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %header %name-prefix "calc" %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1399 AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %header %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1401 AT_CHECK_CALC_GLR([%no-lines %define api.pure %define parse.error verbose %debug %locations %header %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1404 # ---------------------- #
1405 # LALR1 C++ Calculator. #
1406 # ---------------------- #
1408 AT_BANNER([[LALR(1) C++ Calculator.]])
1410 # First let's try using %skeleton
1411 AT_CHECK_CALC([%skeleton "lalr1.cc" %header])
1413 m4_define([AT_CHECK_CALC_LALR1_CC],
1414 [AT_CHECK_CALC([%language "C++" $1], [$2])])
1416 AT_CHECK_CALC_LALR1_CC([])
1417 AT_CHECK_CALC_LALR1_CC([%locations])
1418 AT_CHECK_CALC_LALR1_CC([%locations], [$NO_EXCEPTIONS_CXXFLAGS])
1419 AT_CHECK_CALC_LALR1_CC([%locations %define api.location.type {Span}])
1420 AT_CHECK_CALC_LALR1_CC([%header %locations %define parse.error verbose %name-prefix "calc" %verbose])
1422 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %define api.prefix {calc} %verbose])
1423 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %name-prefix "calc" %verbose])
1425 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %define api.prefix {calc} %verbose])
1426 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %define api.prefix {calc} %define api.token.prefix {TOK_} %verbose])
1428 AT_CHECK_CALC_LALR1_CC([%header %locations %define parse.error verbose %debug %name-prefix "calc" %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1430 AT_CHECK_CALC_LALR1_CC([%define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1431 AT_CHECK_CALC_LALR1_CC([%header %locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1433 AT_CHECK_CALC_LALR1_CC([%header %locations %define api.location.file none])
1434 AT_CHECK_CALC_LALR1_CC([%header %locations %define api.location.file "my-location.hh"])
1436 AT_CHECK_CALC_LALR1_CC([%no-lines %header %locations %define api.location.file "my-location.hh"])
1438 AT_CHECK_CALC_LALR1_CC([%locations %define parse.lac full %define parse.error verbose])
1439 AT_CHECK_CALC_LALR1_CC([%locations %define parse.lac full %define parse.error detailed])
1440 AT_CHECK_CALC_LALR1_CC([%locations %define parse.lac full %define parse.error detailed %define parse.trace])
1442 AT_CHECK_CALC_LALR1_CC([%define parse.error custom])
1443 AT_CHECK_CALC_LALR1_CC([%define parse.error custom %locations %define api.prefix {calc} %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1444 AT_CHECK_CALC_LALR1_CC([%define parse.error custom %locations %define api.prefix {calc} %parse-param {semantic_value *result}{int *count}{int *nerrs} %define parse.lac full])
1446 # -------------------- #
1447 # GLR C++ Calculator. #
1448 # -------------------- #
1450 AT_BANNER([[GLR C++ Calculator.]])
1452 # Again, we try also using %skeleton.
1453 AT_CHECK_CALC([%skeleton "glr.cc"])
1454 AT_CHECK_CALC([%skeleton "glr2.cc"])
1456 m4_define([AT_CHECK_CALC_GLR_CC],
1457 [AT_CHECK_CALC([%language "C++" %glr-parser] $@) # glr.cc
1458 AT_CHECK_CALC([%skeleton "glr2.cc"] $@)
1461 AT_CHECK_CALC_GLR_CC([])
1462 AT_CHECK_CALC_GLR_CC([%locations])
1463 AT_CHECK_CALC_GLR_CC([%locations %define api.location.type {Span}])
1464 AT_CHECK_CALC_GLR_CC([%header %define parse.error verbose %name-prefix "calc" %verbose])
1465 AT_CHECK_CALC_GLR_CC([%define parse.error verbose %define api.prefix {calc} %verbose])
1467 AT_CHECK_CALC_GLR_CC([%debug])
1469 AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %verbose])
1470 AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %define api.token.prefix {TOK_} %verbose])
1472 AT_CHECK_CALC_GLR_CC([%locations %header %define parse.error verbose %debug %name-prefix "calc" %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1473 AT_CHECK_CALC_GLR_CC([%locations %header %define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1475 AT_CHECK_CALC_GLR_CC([%no-lines %locations %header %define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1478 # -------------------- #
1479 # LALR1 D Calculator. #
1480 # -------------------- #
1482 AT_BANNER([[LALR(1) D Calculator.]])
1484 # First let's try using %skeleton
1485 AT_CHECK_CALC([%skeleton "lalr1.d"])
1487 m4_define([AT_CHECK_CALC_LALR1_D],
1488 [AT_CHECK_CALC([%language "D" $1], [$2])])
1490 AT_CHECK_CALC_LALR1_D([])
1491 AT_CHECK_CALC_LALR1_D([%locations])
1492 #AT_CHECK_CALC_LALR1_D([%locations %define api.location.type {Span}])
1493 AT_CHECK_CALC_LALR1_D([%define parse.error detailed %define api.prefix {calc} %verbose])
1495 AT_CHECK_CALC_LALR1_D([%debug])
1497 AT_CHECK_CALC_LALR1_D([%define parse.error custom])
1498 AT_CHECK_CALC_LALR1_D([%locations %define parse.error custom])
1499 AT_CHECK_CALC_LALR1_D([%locations %define parse.error detailed])
1500 AT_CHECK_CALC_LALR1_D([%locations %define parse.error simple])
1501 AT_CHECK_CALC_LALR1_D([%define parse.error detailed %debug %verbose])
1502 AT_CHECK_CALC_LALR1_D([%define parse.error detailed %debug %define api.symbol.prefix {SYMB_} %define api.token.prefix {TOK_} %verbose])
1504 AT_CHECK_CALC_LALR1_D([%locations %define parse.lac full %define parse.error detailed])
1505 AT_CHECK_CALC_LALR1_D([%locations %define parse.lac full %define parse.error custom])
1506 AT_CHECK_CALC_LALR1_D([%locations %define parse.lac full %define parse.error detailed %define parse.trace])
1508 #AT_CHECK_CALC_LALR1_D([%locations %define parse.error detailed %debug %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1509 #AT_CHECK_CALC_LALR1_D([%locations %define parse.error detailed %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1511 AT_CHECK_CALC_LALR1_D([%define api.token.constructor %locations %define parse.error custom %define api.value.type union])
1512 AT_CHECK_CALC_LALR1_D([%define api.token.constructor %locations %define parse.error detailed])
1513 AT_CHECK_CALC_LALR1_D([%define api.push-pull both])
1514 AT_CHECK_CALC_LALR1_D([%define parse.trace %define parse.error custom %locations %define api.push-pull both %define parse.lac full])
1516 # ----------------------- #
1517 # LALR1 Java Calculator. #
1518 # ----------------------- #
1520 AT_BANNER([[LALR(1) Java Calculator.]])
1522 m4_define([AT_CHECK_CALC_LALR1_JAVA],
1523 [AT_CHECK_CALC([%language "Java" $1], [$2])])
1525 AT_CHECK_CALC_LALR1_JAVA
1526 AT_CHECK_CALC_LALR1_JAVA([%define parse.error custom])
1527 AT_CHECK_CALC_LALR1_JAVA([%define parse.error detailed])
1528 AT_CHECK_CALC_LALR1_JAVA([%define parse.error verbose])
1529 AT_CHECK_CALC_LALR1_JAVA([%locations %define parse.error custom])
1530 AT_CHECK_CALC_LALR1_JAVA([%locations %define parse.error detailed])
1531 AT_CHECK_CALC_LALR1_JAVA([%locations %define parse.error verbose])
1532 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error verbose])
1533 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error verbose %locations %lex-param {InputStream is}])
1535 AT_CHECK_CALC_LALR1_JAVA([%define api.push-pull both])
1536 AT_CHECK_CALC_LALR1_JAVA([%define api.push-pull both %define parse.error detailed %locations])
1537 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error custom %locations %lex-param {InputStream is} %define api.push-pull both])
1538 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error verbose %locations %lex-param {InputStream is} %define api.push-pull both])
1541 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error custom %locations %define parse.lac full])
1542 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error custom %locations %define api.push-pull both %define parse.lac full])
1545 m4_popdef([AT_CALC_MAIN])
1546 m4_popdef([AT_CALC_YYLEX])