Update URLs to prefer https: to http:
[bison.git] / tests / calc.at
blobbf7752f7f25c2d00dbe5cd8a5db68809c87f895e
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 ## ---------------------------------------------------- ##
22 # -------------- #
23 # AT_CALC_MAIN.  #
24 # -------------- #
26 m4_pushdef([AT_CALC_MAIN],   [AT_LANG_DISPATCH([$0], $@)])
28 # Whether token translation is supported.
29 m4_pushdef([AT_TOKEN_TRANSLATE_IF],
30 [AT_ERROR_CUSTOM_IF([$1], [AT_ERROR_DETAILED_IF([$1], [$2])])])
32 m4_define([AT_CALC_MAIN(c)],
33 [[#include <assert.h>
34 #include <unistd.h>
36 ]AT_CXX_IF([[
37 namespace
39   /* A C++ ]AT_NAME_PREFIX[parse that simulates the C signature.  */
40   int
41   ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([semantic_value *result, int *count, int *nerrs]))[
42   {
43     ]AT_NAME_PREFIX[::parser parser]AT_PARAM_IF([ (result, count, nerrs)])[;
44   #if ]AT_API_PREFIX[DEBUG
45     parser.set_debug_level (1);
46   #endif
47     return parser.parse ();
48   }
50 ]])[
52 /* Value of the last computation.  */
53 semantic_value global_result = 0;
54 /* Total number of computations.  */
55 int global_count = 0;
56 /* Total number of errors.  */
57 int global_nerrs = 0;
59 /* A C main function.  */
60 int
61 main (int argc, const char **argv)
62 {]AT_PARAM_IF([[
63   semantic_value result = 0;
64   int count = 0;
65   int nerrs = 0;]])[
66   int status;
68   /* This used to be alarm (10), but that isn't enough time for a July
69      1995 vintage DEC Alphastation 200 4/100 system, according to
70      Nelson H. F. Beebe.  100 seconds was enough for regular users,
71      but the Hydra build farm, which is heavily loaded needs more.  */
73   alarm (200);
75   if (argc == 2)
76     input = fopen (argv[1], "r");
77   else
78     input = stdin;
80   if (!input)
81     {
82       perror (argv[1]);
83       return 3;
84     }
86 ]AT_CXX_IF([], [AT_DEBUG_IF([  ]AT_NAME_PREFIX[debug = 1;])])[
87   status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count, &nerrs]])[);
88   if (fclose (input))
89     perror ("fclose");]AT_PARAM_IF([[
90   assert (global_result == result); (void) result;
91   assert (global_count  == count);  (void) count;
92   assert (global_nerrs  == nerrs);  (void) nerrs;
93   printf ("final: %d %d %d\n", global_result, global_count, global_nerrs);]])[
94   return status;
96 ]])
98 m4_copy([AT_CALC_MAIN(c)], [AT_CALC_MAIN(c++)])
100 m4_define([AT_CALC_MAIN(d)],
101 [[int main (string[] args)
102 {]AT_PARAM_IF([[
103   semantic_value result = 0;
104   int count = 0;]])[
106   File input = args.length == 2 ? File (args[1], "r") : stdin;
107   auto l = calcLexer (input);
108   auto p = new YYParser (l);]AT_DEBUG_IF([[
109   p.setDebugLevel (1);]])[
110   return !p.parse ();
115 m4_define([AT_CALC_MAIN(java)],
116 [[public static void main (String[] args) throws IOException
117   {]AT_LEXPARAM_IF([[
118     Calc p = new Calc (System.in);]], [[
119     CalcLexer l = new CalcLexer (System.in);
120     Calc p = new Calc (l);]])AT_DEBUG_IF([[
121     p.setDebugLevel (1);]])[
122     boolean success = p.parse ();
123     if (!success)
124       System.exit (1);
125   }
129 # --------------- #
130 # AT_CALC_YYLEX.  #
131 # --------------- #
133 m4_pushdef([AT_CALC_YYLEX],   [AT_LANG_DISPATCH([$0], $@)])
136 m4_define([AT_CALC_YYLEX(c)],
137 [[#include <ctype.h>
139 ]AT_YYLEX_DECLARE_EXTERN[
141 ]AT_LOCATION_IF([
142 static AT_YYLTYPE last_yylloc;
144 static int
145 get_char (]AT_YYLEX_FORMALS[)
147   int res = getc (input);
148   ]AT_USE_LEX_ARGS[;
149 ]AT_LOCATION_IF([
150   last_yylloc = AT_LOC;
151   if (res == '\n')
152     {
153       AT_LOC_LAST_LINE++;
154       AT_LOC_LAST_COLUMN = 1;
155     }
156   else
157     AT_LOC_LAST_COLUMN++;
159   return res;
162 static void
163 unget_char (]AT_YYLEX_PRE_FORMALS[ int c)
165   ]AT_USE_LEX_ARGS[;
166 ]AT_LOCATION_IF([
167   /* Wrong when C == '\n'. */
168   AT_LOC = last_yylloc;
170   ungetc (c, input);
173 static int
174 read_integer (]AT_YYLEX_FORMALS[)
176   int c = get_char (]AT_YYLEX_ARGS[);
177   int res = 0;
179   ]AT_USE_LEX_ARGS[;
180   while (isdigit (c))
181     {
182       res = 10 * res + (c - '0');
183       c = get_char (]AT_YYLEX_ARGS[);
184     }
186   unget_char (]AT_YYLEX_PRE_ARGS[ c);
188   return res;
192 /*---------------------------------------------------------------.
193 | Lexical analyzer returns an integer on the stack and the token |
194 | NUM, or the ASCII character read if not a number.  Skips all   |
195 | blanks and tabs, returns 0 for EOF.                            |
196 `---------------------------------------------------------------*/
198 ]AT_YYLEX_PROTOTYPE[
200   int c;
201   /* Skip white spaces.  */
202   do
203     {
204 ]AT_LOCATION_IF([
205       AT_LOC_FIRST_COLUMN = AT_LOC_LAST_COLUMN;
206       AT_LOC_FIRST_LINE   = AT_LOC_LAST_LINE;
208     }
209   while ((c = get_char (]AT_YYLEX_ARGS[)) == ' ' || c == '\t');
211   /* Process numbers.   */
212   if (isdigit (c))
213     {
214       unget_char (]AT_YYLEX_PRE_ARGS[ c);
215       ]AT_VAL[.ival = read_integer (]AT_YYLEX_ARGS[);
216       return ]AT_CXX_IF([AT_NAMESPACE::parser::token::])[]AT_TOKEN_PREFIX[NUM;
217     }
219   /* Return end-of-file.  */
220   if (c == EOF)
221     return ]AT_CXX_IF([AT_NAMESPACE::parser::token::])[]AT_TOKEN_PREFIX[CALC_EOF;
223   /* An explicit error raised by the scanner. */
224   if (c == '#')
225     {]AT_LOCATION_IF([
226       fprintf (stderr, "%d.%d: ",
227                AT_LOC_FIRST_LINE, AT_LOC_FIRST_COLUMN);])[
228       fputs ("syntax error: invalid character: '#'\n", stderr);
229       return ]AT_CXX_IF([AT_NAMESPACE::parser::token::])[]AT_TOKEN_PREFIX[]AT_API_PREFIX[error;
230     }
232   /* Return single chars. */
233   return c;
237 m4_copy([AT_CALC_YYLEX(c)], [AT_CALC_YYLEX(c++)])
239 m4_define([AT_CALC_YYLEX(d)],
240 [[import std.range.primitives;
241 import std.stdio;
243 auto calcLexer(R)(R range)
244   if (isInputRange!R && is (ElementType!R : dchar))
246   return new CalcLexer!R(range);
249 auto calcLexer (File f)
251   import std.algorithm : map, joiner;
252   import std.utf : byDchar;
254   return f.byChunk(1024)        // avoid making a syscall roundtrip per char
255           .map!(chunk => cast(char[]) chunk) // because byChunk returns ubyte[]
256           .joiner               // combine chunks into a single virtual range of char
257           .calcLexer;           // forward to other overload
260 class CalcLexer(R) : Lexer
261   if (isInputRange!R && is (ElementType!R : dchar))
263   R input;
265   this(R r) {
266     input = r;
267   }
269   ]AT_YYERROR_DEFINE[
271   YYSemanticType semanticVal_;]AT_LOCATION_IF([[
272   YYLocation location = new YYLocation;
274   public final @property YYPosition startPos()
275   {
276     return location.begin;
277   }
279   public final @property YYPosition endPos()
280   {
281     return location.end;
282   }
283 ]])[
284   public final @property YYSemanticType semanticVal()
285   {
286     return semanticVal_;
287   }
289   int parseInt ()
290   {
291     auto res = 0;
292     import std.uni : isNumber;
293     while (input.front.isNumber)
294       {
295         res = res * 10 + (input.front - '0');]AT_LOCATION_IF([[
296         location.end.column += 1;]])[
297         input.popFront;
298       }
299     return res;
300   }
302   int yylex ()
303   {]AT_LOCATION_IF([[
304     location.begin = location.end;]])[
306     import std.uni : isWhite, isNumber;
308     // Skip initial spaces
309     while (!input.empty && input.front != '\n' && isWhite (input.front))
310       {
311         input.popFront;]AT_LOCATION_IF([[
312         location.begin.column += 1;
313         location.end.column += 1;]])[
314       }
316     // EOF.
317     if (input.empty)
318       return TokenKind.CALC_EOF;
320     // Numbers.
321     if (input.front.isNumber)
322       {
323         semanticVal_.ival = parseInt;
324         return TokenKind.NUM;
325       }
327     // Individual characters
328     auto c = input.front;]AT_LOCATION_IF([[
329     if (c == '\n')
330       {
331         location.end.line += 1;
332         location.end.column = 1;
333       }
334     else
335       location.end.column += 1;]])[
336     input.popFront;
338     // An explicit error raised by the scanner. */
339     if (c == '#')
340       {
341         stderr.writeln (]AT_LOCATION_IF([location, ": ", ])["syntax error: invalid character: '#'");
342         return TokenKind.YYerror;
343       }
345     return c;
346   }
351 m4_define([AT_CALC_YYLEX(java)],
352 [AT_LEXPARAM_IF([[%code lexer {]],
353                 [[%code epilogue { class CalcLexer implements Calc.Lexer {]])[
354   StreamTokenizer st;]AT_LOCATION_IF([[
355   PositionReader reader;]])[
357   public ]AT_LEXPARAM_IF([[YYLexer]], [[CalcLexer]])[ (InputStream is)
358   {]AT_LOCATION_IF([[
359     reader = new PositionReader (new InputStreamReader (is));
360     st = new StreamTokenizer (reader);]], [[
361     st = new StreamTokenizer (new InputStreamReader (is));]])[
362     st.resetSyntax ();
363     st.eolIsSignificant (true);
364     st.wordChars ('0', '9');
365   }
367 ]AT_LOCATION_IF([[
368   Position start = new Position (1, 0);
369   Position end = new Position (1, 0);
371   public Position getStartPos () {
372     return new Position (start);
373   }
375   public Position getEndPos () {
376     return new Position (end);
377   }
379 ]])[
380   ]AT_YYERROR_DEFINE[
382   Integer yylval;
384   public Object getLVal () {
385     return yylval;
386   }
388   public int yylex () throws IOException {;]AT_LOCATION_IF([[
389     start.set (reader.getPosition ());]])[
390     int tkind = st.nextToken ();]AT_LOCATION_IF([[
391     end.set (reader.getPosition ());]])[
392     switch (tkind)
393       {
394       case StreamTokenizer.TT_EOF:
395         return CALC_EOF;
396       case StreamTokenizer.TT_EOL:;]AT_LOCATION_IF([[
397         end.line += 1;
398         end.column = 0;]])[
399         return (int) '\n';
400       case StreamTokenizer.TT_WORD:
401         yylval = new Integer (st.sval);]AT_LOCATION_IF([[
402         end.set (reader.getPreviousPosition ());]])[
403         return NUM;
404       case ' ': case '\t':
405         return yylex ();
406       case '#':
407         System.err.println(]AT_LOCATION_IF([[start + ": " + ]])["syntax error: invalid character: '#'");
408         return YYerror;
409       default:
410         return tkind;
411       }
412   }
413 ]AT_LEXPARAM_IF([], [[}]])[
418 # -------------- #
419 # AT_DATA_CALC.  #
420 # -------------- #
423 # _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
424 # -----------------------------------------------
425 # Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
426 # 'calc-lex.cc'.
428 # Don't call this macro directly, because it contains some occurrences
429 # of '$1' etc. which will be interpreted by m4.  So you should call it
430 # with $1, $2, and $3 as arguments, which is what AT_DATA_CALC_Y does.
432 # When %defines is not passed, generate a single self-contained file.
433 # Otherwise, generate three: calc.y with the parser, calc-lex.c with
434 # the scanner, and calc-main.c with "main()".  This is in order to
435 # stress the use of the generated parser header.  To avoid code
436 # duplication, AT_CALC_YYLEX and AT_CALC_MAIN contain the body of these
437 # two later files.
438 m4_pushdef([_AT_DATA_CALC_Y],
439 [m4_if([$1$2$3], $[1]$[2]$[3], [],
440        [m4_fatal([$0: Invalid arguments: $@])])dnl
441 AT_LANG_DISPATCH([$0], $@)])
443 m4_define([_AT_DATA_CALC_Y(c)],
444 [AT_DATA_GRAMMAR([calc.y],
445 [[/* Infix notation calculator--calc */
446 ]$4[
447 ]AT_LANG_MATCH(
448 [d], [[
449 %code imports {
450   alias semantic_value = int;
453 [c\|c++], [[
454 %code requires
456 ]AT_LOCATION_TYPE_SPAN_IF([[
457   typedef struct
458   {
459     int l;
460     int c;
461   } Point;
463   typedef struct
464   {
465     Point first;
466     Point last;
467   } Span;
469 # define YYLLOC_DEFAULT(Current, Rhs, N)                                \
470   do                                                                    \
471     if (N)                                                              \
472       {                                                                 \
473         (Current).first = YYRHSLOC (Rhs, 1).first;                      \
474         (Current).last  = YYRHSLOC (Rhs, N).last;                       \
475       }                                                                 \
476     else                                                                \
477       {                                                                 \
478         (Current).first = (Current).last = YYRHSLOC (Rhs, 0).last;      \
479       }                                                                 \
480   while (0)
482 ]AT_C_IF(
483 [[#include <stdio.h>
484 void location_print (FILE *o, Span s);
485 #define LOCATION_PRINT location_print
486 ]])[
488 ]])[
489   /* Exercise pre-prologue dependency to %union.  */
490   typedef int semantic_value;
492 ]])[
494 /* Exercise %union. */
495 %union
497   semantic_value ival;
499 %printer { ]AT_CXX_IF([[yyo << $$]],
500                       [[fprintf (yyo, "%d", $$)]])[; } <ival>;
502 ]AT_LANG_MATCH([c\|c++], [[
503 %code provides
505   #include <stdio.h>
506   /* The input.  */
507   extern FILE *input;
508   extern semantic_value global_result;
509   extern int global_count;
510   extern int global_nerrs;
513 %code
515   #include <assert.h>
516   #include <string.h>
517   #define USE(Var)
519   FILE *input;
520   static int power (int base, int exponent);
522   ]AT_YYERROR_DECLARE[
523   ]AT_YYLEX_DECLARE_EXTERN[
525   ]AT_TOKEN_TRANSLATE_IF([[
526 #define N_
527     static
528     const char *
529     _ (const char *cp)
530     {
531       if (strcmp (cp, "end of input") == 0)
532         return "end of file";
533       else if (strcmp (cp, "number") == 0)
534         return "nombre";
535       else
536         return cp;
537     }
538   ]])[
540 ]])[
542 ]AT_LOCATION_TYPE_SPAN_IF([[
543 %initial-action
545   @$.first.l = @$.first.c = 1;
546   @$.last = @$.first;
547 }]])[
549 /* Bison Declarations */
550 %token CALC_EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of input")], ["end of input"])[
551 %token <ival> NUM   "number"
552 %type  <ival> exp
554 %nonassoc '='   /* comparison          */
555 %left '-' '+'
556 %left '*' '/'
557 %precedence NEG /* negation--unary minus */
558 %right '^'      /* exponentiation        */
560 /* Grammar follows */
562 input:
563   line
564 | input line         { ]AT_PARAM_IF([++*count; ++global_count;])[ }
567 line:
568   '\n'
569 | exp '\n'           { ]AT_PARAM_IF([*result = global_result = $1;], [AT_D_IF([], [USE ($1);])])[ }
572 exp:
573   NUM
574 | exp '=' exp
575   {
576     if ($1 != $3)]AT_LANG_CASE(
577       [c], [[
578       {
579         char buf[1024];
580         snprintf (buf, sizeof buf, "calc: error: %d != %d", $1, $3);]AT_YYERROR_ARG_LOC_IF([[
581         yyerror (&@$, ]AT_PARAM_IF([result, count, nerrs, ])[buf);]], [[
582         {
583           YYLTYPE old_yylloc = yylloc;
584           yylloc = @$;
585           yyerror (]AT_PARAM_IF([result, count, nerrs, ])[buf);
586           yylloc = old_yylloc;
587         }
588         ]])[
589       }]],
590       [c++], [[
591       {
592         char buf[1024];
593         snprintf (buf, sizeof buf, "calc: error: %d != %d", $1, $3);
594         ]AT_GLR_IF([[yyparser.]])[error (]AT_LOCATION_IF([[@$, ]])[buf);
595       }]],
596       [d], [[
597       yyerror (]AT_LOCATION_IF([[@$, ]])[format ("calc: error: %d != %d", $1, $3));]])[
598     $$ = $1;
599   }
600 | exp '+' exp        { $$ = $1 + $3; }
601 | exp '-' exp        { $$ = $1 - $3; }
602 | exp '*' exp        { $$ = $1 * $3; }
603 | exp '/' exp        { $$ = $1 / $3; }
604 | '-' exp  %prec NEG { $$ = -$2; }
605 | exp '^' exp        { $$ = power ($1, $3); }
606 | '(' exp ')'        { $$ = $2; }
607 | '(' error ')'      { $$ = 1111; ]AT_D_IF([], [yyerrok;])[ }
608 | '!'                { $$ = 0; ]AT_D_IF([return YYERROR], [YYERROR])[; }
609 | '-' error          { $$ = 0; ]AT_D_IF([return YYERROR], [YYERROR])[; }
614 power (int base, int exponent)
616   int res = 1;
617   assert (0 <= exponent);
618   for (/* Niente */; exponent; --exponent)
619     res *= base;
620   return res;
623 ]AT_LOCATION_TYPE_SPAN_IF([AT_CXX_IF([[
624 #include <iostream>
625 namespace
627   std::ostream&
628   operator<< (std::ostream& o, const Span& s)
629   {
630     o << s.first.l << '.' << s.first.c;
631     if (s.first.l != s.last.l)
632       o << '-' << s.last.l << '.' << s.last.c - 1;
633     else if (s.first.c != s.last.c - 1)
634       o << '-' << s.last.c - 1;
635     return o;
636   }
638 ]], [[
639 void
640 location_print (FILE *o, Span s)
642   fprintf (o, "%d.%d", s.first.l, s.first.c);
643   if (s.first.l != s.last.l)
644     fprintf (o, "-%d.%d", s.last.l, s.last.c - 1);
645   else if (s.first.c != s.last.c - 1)
646     fprintf (o, "-%d", s.last.c - 1);
648 ]])])[
649 ]AT_YYERROR_DEFINE[
650 ]AT_DEFINES_IF([],
651 [AT_CALC_YYLEX
652 AT_CALC_MAIN])])
654 AT_DEFINES_IF([AT_DATA_SOURCE([[calc-lex.]AT_LANG_EXT],
655 [[#include "calc.]AT_LANG_HDR["
657 ]AT_CALC_YYLEX])
658 AT_DATA_SOURCE([[calc-main.]AT_LANG_EXT],
659 [[#include "calc.]AT_LANG_HDR["
661 ]AT_CALC_MAIN])
663 ])# _AT_DATA_CALC_Y
666 m4_copy([_AT_DATA_CALC_Y(c)], [_AT_DATA_CALC_Y(c++)])
667 m4_copy([_AT_DATA_CALC_Y(c)], [_AT_DATA_CALC_Y(d)])
669 m4_define([_AT_DATA_CALC_Y(java)],
670 [AT_DATA_GRAMMAR([Calc.y],
671 [[/* Infix notation calculator--calc */
672 %define api.prefix {Calc}
673 %define api.parser.class {Calc}
674 %define public
676 ]$4[
678 %code imports {]AT_LOCATION_IF([[
679   import java.io.BufferedReader;]])[
680   import java.io.IOException;
681   import java.io.InputStream;
682   import java.io.InputStreamReader;
683   import java.io.Reader;
684   import java.io.StreamTokenizer;
687 %code {
688   ]AT_CALC_MAIN[
690   ]AT_TOKEN_TRANSLATE_IF([[
691     static String i18n(String s)
692     {
693       if (s.equals ("end of input"))
694         return "end of file";
695       else if (s.equals ("number"))
696         return "nombre";
697       else
698         return s;
699     }
700   ]])[
703 /* Bison Declarations */
704 %token CALC_EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of input")], ["end of input"])[
705 %token <Integer> NUM "number"
706 %type  <Integer> exp
708 %nonassoc '='       /* comparison            */
709 %left '-' '+'
710 %left '*' '/'
711 %precedence NEG     /* negation--unary minus */
712 %right '^'          /* exponentiation        */
714 /* Grammar follows */
716 input:
717   line
718 | input line
721 line:
722   '\n'
723 | exp '\n'
726 exp:
727   NUM
728 | exp '=' exp
729   {
730     if ($1.intValue () != $3.intValue ())
731       yyerror (]AT_LOCATION_IF([[@$, ]])["calc: error: " + $1 + " != " + $3);
732   }
733 | exp '+' exp        { $$ = $1 + $3; }
734 | exp '-' exp        { $$ = $1 - $3; }
735 | exp '*' exp        { $$ = $1 * $3; }
736 | exp '/' exp        { $$ = $1 / $3; }
737 | '-' exp  %prec NEG { $$ = -$2; }
738 | exp '^' exp        { $$ = (int) Math.pow ($1, $3); }
739 | '(' exp ')'        { $$ = $2; }
740 | '(' error ')'      { $$ = 1111; }
741 | '!'                { $$ = 0; return YYERROR; }
742 | '-' error          { $$ = 0; return YYERROR; }
744 ]AT_CALC_YYLEX[
745 ]AT_LOCATION_IF([[
747 ]AT_JAVA_POSITION_DEFINE])[
749 ])# _AT_DATA_JAVA_CALC_Y
753 # AT_DATA_CALC_Y([BISON-OPTIONS])
754 # -------------------------------
755 # Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
756 # 'calc-lex.cc'.
757 m4_define([AT_DATA_CALC_Y],
758 [_AT_DATA_CALC_Y($[1], $[2], $[3], [$1])
763 # _AT_CHECK_CALC(BISON-OPTIONS, INPUT, [STDOUT], [NUM-STDERR-LINES])
764 # ------------------------------------------------------------------
765 # Run 'calc' on INPUT and expect no STDOUT nor STDERR.
767 # If BISON-OPTIONS contains '%debug' but not '%glr-parser', then
768 # NUM-STDERR-LINES is the number of expected lines on stderr.
769 # Currently this is ignored, though, since the output format is fluctuating.
771 # We don't count GLR's traces yet, since its traces are somewhat
772 # different from LALR's.  Likewise for D.
774 # The push traces are the same, except for "Return for a new token", don't
775 # count them.
776 m4_define([_AT_CHECK_CALC],
777 [AT_DATA([[input]],
780 AT_JAVA_IF(
781   [AT_JAVA_PARSER_CHECK([Calc < input], 0, [AT_PARAM_IF([m4_n([$3])])], [stderr])],
782   [AT_PARSER_CHECK([calc input],        0, [AT_PARAM_IF([m4_n([$3])])], [stderr])])
783 AT_LANG_MATCH([c\|c++\|java],
784   [AT_GLR_IF([],
785     [AT_CHECK([grep -c -v 'Return for a new token:' stderr],
786               [ignore],
787               [m4_n([AT_DEBUG_IF([$4], [0])])])])])
791 # _AT_CHECK_CALC_ERROR($1 = BISON-OPTIONS, $2 = EXIT-STATUS, $3 = INPUT,
792 #                      $4 = [STDOUT],
793 #                      $5 = [NUM-STDERR-LINES],
794 #                      $6 = [CUSTOM-ERROR-MESSAGE])
795 # ----------------------------------------------------------------------
796 # Run 'calc' on INPUT, and expect a 'syntax error' message.
798 # If INPUT starts with a slash, it is used as absolute input file name,
799 # otherwise as contents.
801 # NUM-STDERR-LINES is the number of expected lines on stderr.
802 # If BISON-OPTIONS contains '%debug' but not '%glr', then NUM-STDERR-LINES
803 # is the number of expected lines on stderr.
805 # CUSTOM-ERROR-MESSAGE is the expected error message when parse.error
806 # is 'custom' and locations are enabled.  Other expected formats are
807 # computed from it.
808 m4_define([_AT_CHECK_CALC_ERROR],
809 [m4_bmatch([$3], [^/],
810   [AT_JAVA_IF(
811     [AT_JAVA_PARSER_CHECK([Calc < $3], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])],
812     [AT_PARSER_CHECK([calc $3],        $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])])],
813   [AT_DATA([[input]],
814 [[$3
816   AT_JAVA_IF(
817     [AT_JAVA_PARSER_CHECK([Calc < input], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])],
818     [AT_PARSER_CHECK([calc input],        $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])])
821 # Normalize the observed and expected error messages, depending upon the
822 # options.
823 # 1. Remove the traces from observed.
824 sed '/^Starting/d
825 /^Entering/d
826 /^Stack/d
827 /^Reading/d
828 /^Reducing/d
829 /^Return/d
830 /^Shifting/d
831 /^state/d
832 /^Cleanup:/d
833 /^Error:/d
834 /^Next/d
835 /^Now/d
836 /^Discarding/d
837 / \$[[0-9$]]* = /d
838 /^yydestructor:/d' stderr >at-stderr
839 mv at-stderr stderr
841 # 2. Create the reference error message.
842 AT_DATA([[expout]],
846 # 3. If locations are not used, remove them.
847 AT_YYERROR_SEES_LOC_IF([],
848 [[sed 's/^[-0-9.]*: //' expout >at-expout
849 mv at-expout expout]])
851 # 4. If parse.error is not custom, turn the expected message to
852 # the traditional one.
853 AT_ERROR_CUSTOM_IF([], [
854 AT_PERL_REQUIRE([[-pi -e 'use strict;
855   s{syntax error on token \[(.*?)\] \(expected: (.*)\)}
856   {
857     my $unexp = $][1;
858     my @exps = $][2 =~ /\[(.*?)\]/g;
859     ($][#exps && $][#exps < 4)
860     ? "syntax error, unexpected $unexp, expecting @{[join(\" or \", @exps)]}"
861     : "syntax error, unexpected $unexp";
862   }eg
863 ' expout]])
866 # 5. If parse.error is simple, strip the', unexpected....' part.
867 AT_ERROR_SIMPLE_IF(
868 [[sed 's/syntax error, .*$/syntax error/' expout >at-expout
869 mv at-expout expout]])
871 # 6. Actually check.
872 AT_CHECK([cat stderr], 0, [expout])
876 # AT_CHECK_SPACES([FILES])
877 # ------------------------
878 # Make sure we did not introduce bad spaces.  Checked here because all
879 # the skeletons are (or should be) exercised here.
880 m4_define([AT_CHECK_SPACES],
881 [AT_PERL_CHECK([-ne '
882   chomp;
883   print "$ARGV:$.: {$_}\n"
884     if (# No starting/ending empty lines.
885         (eof || $. == 1) && /^\s*$/
886         # No trailing space.
887         || /\s$/
888         # No tabs.
889         || /\t/
890         )' $1
895 # AT_CHECK_JAVA_GREP(FILE, [LINE], [COUNT=1])
896 # -------------------------------------------
897 # Check that FILE contains exactly COUNT lines matching ^LINE$
898 # with grep.  Unquoted so that COUNT can be a shell expression.
899 m4_define([AT_CHECK_JAVA_GREP],
900 [AT_CHECK_UNQUOTED([grep -c '^$2$' $1], [ignore], [m4_default([$3], [1])
901 ])])
904 # AT_CHECK_CALC([BISON-OPTIONS], [COMPILER-OPTIONS])
905 # --------------------------------------------------
906 # Start a testing chunk which compiles 'calc' grammar with
907 # BISON-OPTIONS, and performs several tests over the parser.
908 m4_define([AT_CHECK_CALC],
909 [m4_ifval([$3], [m4_fatal([$0: expected at most two arguments])])
911 # We use integers to avoid dependencies upon the precision of doubles.
912 AT_SETUP([Calculator $1 $2])
914 AT_BISON_OPTION_PUSHDEFS([$1])
916 AT_DATA_CALC_Y([$1])
917 AT_FULL_COMPILE(AT_JAVA_IF([[Calc]], [[calc]]), AT_DEFINES_IF([[lex], [main]], [[], []]), [$2], [-Wno-deprecated])
919 AT_YACC_IF(
920   [# No direct calls to malloc/free.
921   AT_CHECK([[$EGREP '(malloc|free) *\(' calc.[ch] | $EGREP -v 'INFRINGES ON USER NAME SPACE']],
922            [1])])
924 AT_PUSH_IF([AT_JAVA_IF(
925  [# Verify that this is a push parser.
926   AT_CHECK_JAVA_GREP([[Calc.java]],
927                      [[.*public void push_parse_initialize ().*]])])])
929 AT_CHECK_SPACES([AT_JAVA_IF([Calc], [calc]).AT_LANG_EXT AT_DEFINES_IF([AT_JAVA_IF([Calc], [calc]).AT_LANG_HDR])])
931 # Test the precedences.
932 # The Java traces do not show the clean up sequence at the end,
933 # since it does not support %destructor.
934 _AT_CHECK_CALC([$1],
935 [[1 + 2 * 3 = 7
936 1 + 2 * -3 = -5
938 -1^2 = -1
939 (-1)^2 = 1
941 ---1 = -1
943 1 - 2 - 3 = -4
944 1 - (2 - 3) = 2
946 2^2^3 = 256
947 (2^2)^3 = 64]],
948 [[final: 64 12 0]],
949                [AT_JAVA_IF([1014], [1017])])
951 # Some syntax errors.
952 _AT_CHECK_CALC_ERROR([$1], [1], [1 2],
953                      [[final: 0 0 1]],
954                      [15],
955                      [AT_JAVA_IF([1.3-1.4], [1.3])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] ['\n'])]])
956 _AT_CHECK_CALC_ERROR([$1], [1], [1//2],
957                      [[final: 0 0 1]],
958                      [20],
959                      [AT_JAVA_IF([1.3-1.4], [1.3])[: syntax error on token ['/'] (expected: [number] ['-'] ['('] ['!'])]])
960 _AT_CHECK_CALC_ERROR([$1], [1], [error],
961                      [[final: 0 0 1]],
962                      [5],
963                      [AT_JAVA_IF([1.1-1.2], [1.1])[: syntax error on token [invalid token] (expected: [number] ['-'] ['\n'] ['('] ['!'])]])
964 _AT_CHECK_CALC_ERROR([$1], [1], [1 = 2 = 3],
965                      [[final: 0 0 1]],
966                      [30],
967                      [AT_LAC_IF(
968                        [AT_JAVA_IF([1.7-1.8], [1.7])[: syntax error on token ['='] (expected: ['-'] ['+'] ['*'] ['/'] ['^'] ['\n'])]],
969                        [AT_JAVA_IF([1.7-1.8], [1.7])[: syntax error on token ['='] (expected: ['-'] ['+'] ['*'] ['/'] ['^'])]])])
970 _AT_CHECK_CALC_ERROR([$1], [1],
971                      [
972 +1],
973                      [[final: 0 0 1]],
974                      [20],
975                      [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'] ['('] ['!'])]])
976 # Exercise error messages with EOF: work on an empty file.
977 _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null],
978                      [[final: 0 0 1]],
979                      [4],
980                      [[1.1: syntax error on token ]AT_TOKEN_TRANSLATE_IF([[[end of file]]], [[[end of input]]])[ (expected: [number] ['-'] ['\n'] ['('] ['!'])]])
982 # Exercise the error token: without it, we die at the first error,
983 # hence be sure to
985 # - have several errors which exercise different shift/discardings
986 #   - (): nothing to pop, nothing to discard
987 #   - (1 + 1 + 1 +): a lot to pop, nothing to discard
988 #   - (* * *): nothing to pop, a lot to discard
989 #   - (1 + 2 * *): some to pop and discard
991 # - test the action associated to 'error'
993 # - check the lookahead that triggers an error is not discarded
994 #   when we enter error recovery.  Below, the lookahead causing the
995 #   first error is ")", which is needed to recover from the error and
996 #   produce the "0" that triggers the "0 != 1" error.
998 _AT_CHECK_CALC_ERROR([$1], [0],
999                      [() + (1 + 1 + 1 +) + (* * *) + (1 * 2 * *) = 1],
1000                      [[final: 4444 0 5]],
1001                      [250],
1002 [AT_JAVA_IF([1.2-1.3], [1.2])[: syntax error on token [')'] (expected: [number] ['-'] ['('] ['!'])
1003 ]AT_JAVA_IF([1.18-1.19], [1.18])[: syntax error on token [')'] (expected: [number] ['-'] ['('] ['!'])
1004 ]AT_JAVA_IF([1.23-1.24], [1.23])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1005 ]AT_JAVA_IF([1.41-1.42], [1.41])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1006 ]AT_JAVA_IF([1.1-1.47], [1.1-46])[: calc: error: 4444 != 1]])
1008 # The same, but this time exercising explicitly triggered syntax errors.
1009 # POSIX says the lookahead causing the error should not be discarded.
1010 _AT_CHECK_CALC_ERROR([$1], [0], [(!) + (1 2) = 1],
1011                      [[final: 2222 0 2]],
1012                      [102],
1013 [AT_JAVA_IF([1.10-1.11], [1.10])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] [')'])
1014 ]AT_JAVA_IF([1.1-1.16], [1.1-15])[: calc: error: 2222 != 1]])
1016 _AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (1 2) = 1],
1017                      [[final: 2222 0 3]],
1018                      [113],
1019 [AT_JAVA_IF([1.4-1.5], [1.4])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1020 ]AT_JAVA_IF([1.12-1.13], [1.12])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] [')'])
1021 ]AT_JAVA_IF([1.1-1.18], [1.1-17])[: calc: error: 2222 != 1]])
1023 # Check that yyerrok works properly: second error is not reported,
1024 # third and fourth are.  Parse status is successful.
1025 _AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)],
1026                      [[final: 3333 0 3]],
1027                      [113],
1028 [AT_JAVA_IF([1.2-1.3], [1.2])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1029 ]AT_JAVA_IF([1.10-1.11], [1.10])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1030 ]AT_JAVA_IF([1.16-1.17], [1.16])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])]])
1033 # YYerror.
1034 # --------
1035 # Check that returning YYerror from the scanner properly enters
1036 # error-recovery without issuing a second error message.
1038 _AT_CHECK_CALC_ERROR([$1], [0], [(#) + (#) = 2222],
1039                      [[final: 2222 0 0]],
1040                      [102],
1041 [[1.2: syntax error: invalid character: '#'
1042 1.8: syntax error: invalid character: '#']])
1044 _AT_CHECK_CALC_ERROR([$1], [0], [(1 + #) = 1111],
1045                      [[final: 1111 0 0]],
1046                      [102],
1047 [[1.6: syntax error: invalid character: '#']])
1049 _AT_CHECK_CALC_ERROR([$1], [0], [(# + 1) = 1111],
1050                      [[final: 1111 0 0]],
1051                      [102],
1052 [[1.2: syntax error: invalid character: '#']])
1054 _AT_CHECK_CALC_ERROR([$1], [0], [(1 + # + 1) = 1111],
1055                      [[final: 1111 0 0]],
1056                      [102],
1057 [[1.6: syntax error: invalid character: '#']])
1061 AT_BISON_OPTION_POPDEFS
1063 AT_CLEANUP
1064 ])# AT_CHECK_CALC
1069 # ----------------- #
1070 # LALR Calculator.  #
1071 # ----------------- #
1073 AT_BANNER([[LALR(1) Calculator.]])
1075 # AT_CHECK_CALC_LALR([BISON-OPTIONS])
1076 # -----------------------------------
1077 # Start a testing chunk which compiles 'calc' grammar with
1078 # BISON-OPTIONS, and performs several tests over the parser.
1079 m4_define([AT_CHECK_CALC_LALR],
1080 [AT_CHECK_CALC($@)])
1082 AT_CHECK_CALC_LALR([%define parse.trace])
1084 AT_CHECK_CALC_LALR([%defines])
1085 AT_CHECK_CALC_LALR([%debug %locations])
1086 AT_CHECK_CALC_LALR([%locations %define api.location.type {Span}])
1088 AT_CHECK_CALC_LALR([%name-prefix "calc"])
1089 AT_CHECK_CALC_LALR([%verbose])
1090 AT_CHECK_CALC_LALR([%yacc])
1091 AT_CHECK_CALC_LALR([%define parse.error detailed])
1092 AT_CHECK_CALC_LALR([%define parse.error verbose])
1094 AT_CHECK_CALC_LALR([%define api.pure full %locations])
1095 AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %locations])
1096 AT_CHECK_CALC_LALR([%define parse.error detailed %locations])
1098 AT_CHECK_CALC_LALR([%define parse.error detailed %locations %defines %define api.prefix {calc} %verbose %yacc])
1099 AT_CHECK_CALC_LALR([%define parse.error detailed %locations %defines %name-prefix "calc" %define api.token.prefix {TOK_} %verbose %yacc])
1101 AT_CHECK_CALC_LALR([%debug])
1102 AT_CHECK_CALC_LALR([%define parse.error detailed %debug %locations %defines %name-prefix "calc" %verbose %yacc])
1103 AT_CHECK_CALC_LALR([%define parse.error detailed %debug %locations %defines %define api.prefix {calc} %verbose %yacc])
1105 AT_CHECK_CALC_LALR([%define api.pure full %define parse.error detailed %debug %locations %defines %name-prefix "calc" %verbose %yacc])
1106 AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %define parse.error detailed %debug %locations %defines %define api.prefix {calc} %verbose %yacc])
1108 AT_CHECK_CALC_LALR([%define api.pure %define parse.error detailed %debug %locations %defines %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1110 AT_CHECK_CALC_LALR([%no-lines %define api.pure %define parse.error detailed %debug %locations %defines %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1111 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}])
1114 AT_CHECK_CALC_LALR([%define parse.error custom])
1115 AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc}])
1116 AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc} %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1117 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])
1118 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])
1120 # ---------------- #
1121 # GLR Calculator.  #
1122 # ---------------- #
1124 AT_BANNER([[GLR Calculator.]])
1126 m4_define([AT_CHECK_CALC_GLR],
1127 [AT_CHECK_CALC([%glr-parser] $@)])
1129 AT_CHECK_CALC_GLR()
1131 AT_CHECK_CALC_GLR([%defines])
1132 AT_CHECK_CALC_GLR([%locations])
1133 AT_CHECK_CALC_GLR([%locations %define api.location.type {Span}])
1134 AT_CHECK_CALC_GLR([%name-prefix "calc"])
1135 AT_CHECK_CALC_GLR([%define api.prefix {calc}])
1136 AT_CHECK_CALC_GLR([%verbose])
1137 AT_CHECK_CALC_GLR([%define parse.error verbose])
1139 AT_CHECK_CALC_GLR([%define api.pure %locations])
1140 AT_CHECK_CALC_GLR([%define parse.error verbose %locations])
1142 AT_CHECK_CALC_GLR([%define parse.error custom %locations %defines %name-prefix "calc" %verbose])
1143 AT_CHECK_CALC_GLR([%define parse.error detailed %locations %defines %name-prefix "calc" %verbose])
1144 AT_CHECK_CALC_GLR([%define parse.error verbose %locations %defines %name-prefix "calc" %verbose])
1146 AT_CHECK_CALC_GLR([%debug])
1147 AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose])
1148 AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %define api.prefix {calc} %define api.token.prefix {TOK_} %verbose])
1150 AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose])
1152 AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1153 AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1155 AT_CHECK_CALC_GLR([%no-lines %define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1158 # ---------------------- #
1159 # LALR1 C++ Calculator.  #
1160 # ---------------------- #
1162 AT_BANNER([[LALR(1) C++ Calculator.]])
1164 # First let's try using %skeleton
1165 AT_CHECK_CALC([%skeleton "lalr1.cc" %defines])
1167 m4_define([AT_CHECK_CALC_LALR1_CC],
1168 [AT_CHECK_CALC([%language "C++" $1], [$2])])
1170 AT_CHECK_CALC_LALR1_CC([])
1171 AT_CHECK_CALC_LALR1_CC([%locations])
1172 AT_CHECK_CALC_LALR1_CC([%locations], [$NO_EXCEPTIONS_CXXFLAGS])
1173 AT_CHECK_CALC_LALR1_CC([%locations %define api.location.type {Span}])
1174 AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %name-prefix "calc" %verbose])
1176 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %define api.prefix {calc} %verbose])
1177 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %name-prefix "calc" %verbose])
1179 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %define api.prefix {calc} %verbose])
1180 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %define api.prefix {calc} %define api.token.prefix {TOK_} %verbose])
1182 AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %debug %name-prefix "calc" %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1184 AT_CHECK_CALC_LALR1_CC([%define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1185 AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1187 AT_CHECK_CALC_LALR1_CC([%defines %locations %define api.location.file none])
1188 AT_CHECK_CALC_LALR1_CC([%defines %locations %define api.location.file "my-location.hh"])
1190 AT_CHECK_CALC_LALR1_CC([%no-lines %defines %locations %define api.location.file "my-location.hh"])
1192 AT_CHECK_CALC_LALR1_CC([%locations %define parse.lac full %define parse.error verbose])
1193 AT_CHECK_CALC_LALR1_CC([%locations %define parse.lac full %define parse.error detailed])
1195 AT_CHECK_CALC_LALR1_CC([%define parse.error custom])
1196 AT_CHECK_CALC_LALR1_CC([%define parse.error custom %locations %define api.prefix {calc} %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1197 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])
1199 # -------------------- #
1200 # GLR C++ Calculator.  #
1201 # -------------------- #
1203 AT_BANNER([[GLR C++ Calculator.]])
1205 # Again, we try also using %skeleton.
1206 AT_CHECK_CALC([%skeleton "glr.cc"])
1208 m4_define([AT_CHECK_CALC_GLR_CC],
1209 [AT_CHECK_CALC([%language "C++" %glr-parser] $@)])
1211 AT_CHECK_CALC_GLR_CC([])
1212 AT_CHECK_CALC_GLR_CC([%locations])
1213 AT_CHECK_CALC_GLR_CC([%locations %define api.location.type {Span}])
1214 AT_CHECK_CALC_GLR_CC([%defines %define parse.error verbose %name-prefix "calc" %verbose])
1215 AT_CHECK_CALC_GLR_CC([%define parse.error verbose %define api.prefix {calc} %verbose])
1217 AT_CHECK_CALC_GLR_CC([%debug])
1219 AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %verbose])
1220 AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %define api.token.prefix {TOK_} %verbose])
1222 AT_CHECK_CALC_GLR_CC([%locations %defines %define parse.error verbose %debug %name-prefix "calc" %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1223 AT_CHECK_CALC_GLR_CC([%locations %defines %define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1225 AT_CHECK_CALC_GLR_CC([%no-lines %locations %defines %define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1228 # -------------------- #
1229 # LALR1 D Calculator.  #
1230 # -------------------- #
1232 AT_BANNER([[LALR(1) D Calculator.]])
1234 # First let's try using %skeleton
1235 AT_CHECK_CALC([%skeleton "lalr1.d"])
1237 m4_define([AT_CHECK_CALC_LALR1_D],
1238 [AT_CHECK_CALC([%language "D" $1], [$2])])
1240 AT_CHECK_CALC_LALR1_D([])
1241 AT_CHECK_CALC_LALR1_D([%locations])
1242 #AT_CHECK_CALC_LALR1_D([%locations %define api.location.type {Span}])
1243 AT_CHECK_CALC_LALR1_D([%define parse.error verbose %define api.prefix {calc} %verbose])
1245 AT_CHECK_CALC_LALR1_D([%debug])
1247 AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %verbose])
1248 #AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %define api.token.prefix {TOK_} %verbose])
1250 #AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1251 #AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1254 # ----------------------- #
1255 # LALR1 Java Calculator.  #
1256 # ----------------------- #
1258 AT_BANNER([[LALR(1) Java Calculator.]])
1260 m4_define([AT_CHECK_CALC_LALR1_JAVA],
1261 [AT_CHECK_CALC([%language "Java" $1], [$2])])
1263 AT_CHECK_CALC_LALR1_JAVA
1264 AT_CHECK_CALC_LALR1_JAVA([%define parse.error custom])
1265 AT_CHECK_CALC_LALR1_JAVA([%define parse.error detailed])
1266 AT_CHECK_CALC_LALR1_JAVA([%define parse.error verbose])
1267 AT_CHECK_CALC_LALR1_JAVA([%locations %define parse.error custom])
1268 AT_CHECK_CALC_LALR1_JAVA([%locations %define parse.error detailed])
1269 AT_CHECK_CALC_LALR1_JAVA([%locations %define parse.error verbose])
1270 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error verbose])
1271 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error verbose %locations %lex-param {InputStream is}])
1273 AT_CHECK_CALC_LALR1_JAVA([%define api.push-pull both])
1274 AT_CHECK_CALC_LALR1_JAVA([%define api.push-pull both %define parse.error detailed %locations])
1275 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error custom %locations %lex-param {InputStream is} %define api.push-pull both])
1276 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error verbose %locations %lex-param {InputStream is} %define api.push-pull both])
1279 m4_popdef([AT_TOKEN_TRANSLATE_IF])
1280 m4_popdef([AT_CALC_MAIN])
1281 m4_popdef([AT_CALC_YYLEX])