java: avoid Integer(String), use parseInt
[bison.git] / tests / calc.at
blob94a5fdb049695af33f823f26f957b2b0e47313e5
1 # Simple calculator.                         -*- Autotest -*-
3 # Copyright (C) 2000-2015, 2018-2020 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 <http://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], $@)])
26 # -------------- #
27 # AT_DATA_CALC.  #
28 # -------------- #
31 # _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
32 # -----------------------------------------------
33 # Produce 'calc.y' and, if %header was specified, 'calc-lex.c' or
34 # 'calc-lex.cc'.
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
45 # two later files.
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], $@)])
53 ## ----------- ##
54 ## Calc in C.  ##
55 ## ----------- ##
57 # AT_CALC_MAIN(c).
58 m4_define([AT_CALC_MAIN(c)],
59 [[#include <assert.h>
60 #include <stdlib.h> /* exit */
61 #include <string.h> /* strcmp */
62 #include <unistd.h>
64 ]AT_CXX_IF([[
65 namespace
67   /* A C++ ]AT_NAME_PREFIX[parse that simulates the C signature.  */
68   int
69   ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([semantic_value *result, int *count, int *nerrs]))[
70   {
71     ]AT_NAME_PREFIX[::parser parser]AT_PARAM_IF([ (result, count, nerrs)])[;
72   #if ]AT_API_PREFIX[DEBUG
73     parser.set_debug_level (1);
74   #endif
75     return parser.parse ();
76   }
78 ]])[
80 /* Value of the last computation.  */
81 semantic_value global_result = 0;
82 /* Total number of computations.  */
83 int global_count = 0;
84 /* Total number of errors.  */
85 int global_nerrs = 0;
87 static FILE *
88 open_file (const char *file)
90   FILE *res = (file && *file && strcmp (file, "-")) ? fopen (file, "r") : stdin;
91   if (!res)
92     {
93       perror (file);
94       exit (3);
95     }
96   return res;
99 /* A C main function.  */
101 main (int argc, const char **argv)
102 {]AT_PARAM_IF([[
103   semantic_value result = 0;
104   int count = 0;
105   int nerrs = 0;]])[
106   int status = 0;
108   /* This used to be alarm (10), but that isn't enough time for a July
109      1995 vintage DEC Alphastation 200 4/100 system, according to
110      Nelson H. F. Beebe.  100 seconds was enough for regular users,
111      but the Hydra build farm, which is heavily loaded needs more.  */
113   alarm (200);
115 ]AT_CXX_IF([], [AT_DEBUG_IF([  ]AT_NAME_PREFIX[debug = 1;])])[
117   {
118     int i;
119     for (i = 1; i < argc; ++i)
120       {
121 ]AT_MULTISTART_IF([[
122         if (!strcmp (argv[i], "--exp") && i+1 < argc)
123           {
124             input = open_file (argv[i+1]);
125             ignore_eol = 1;
126             ]AT_NAME_PREFIX[parse_exp_t res = ]AT_NAME_PREFIX[parse_exp ();
127             printf ("exp => %d (status: %d, errors: %d)\n",
128                     res.yystatus == 0 ? res.yyvalue : 0, res.yystatus, res.yynerrs);
129             status = res.yystatus;
130             ++i;
131           }
132         else if (!strcmp (argv[i], "--num") && i+1 < argc)
133           {
134             input = open_file (argv[i+1]);
135             ignore_eol = 1;
136             ]AT_NAME_PREFIX[parse_NUM_t res = ]AT_NAME_PREFIX[parse_NUM ();
137             printf ("NUM => %d (status: %d, errors: %d)\n",
138                     res.yystatus == 0 ? res.yyvalue : 0, res.yystatus, res.yynerrs);
139             status = res.yystatus;
140             ++i;
141           }
142         else]])[
143           {
144             input = open_file (argv[i]);
145             status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count, &nerrs]])[);
146           }
147         if (input != stdin && fclose (input))
148           perror ("fclose");
149       }
150   }
151 ]AT_PARAM_IF([[
152   assert (global_result == result); (void) result;
153   assert (global_count  == count);  (void) count;
154   assert (global_nerrs  == nerrs);  (void) nerrs;
155   printf ("final: %d %d %d\n", global_result, global_count, global_nerrs);]])[
156   return status;
161 # AT_CALC_YYLEX(c).
162 m4_define([AT_CALC_YYLEX(c)],
163 [[#include <ctype.h>
165 ]AT_YYLEX_DECLARE_EXTERN[
167 ]AT_LOCATION_IF([
168 static AT_YYLTYPE last_yylloc;
170 static int
171 get_char (]AT_YYLEX_FORMALS[)
173   int res = getc (input);
174   ]AT_USE_LEX_ARGS[;
175 ]AT_LOCATION_IF([
176   last_yylloc = AT_LOC;
177   if (res == '\n')
178     {
179       AT_LOC_LAST_LINE++;
180       AT_LOC_LAST_COLUMN = 1;
181     }
182   else
183     AT_LOC_LAST_COLUMN++;
185   return res;
188 static void
189 unget_char (]AT_YYLEX_PRE_FORMALS[ int c)
191   ]AT_USE_LEX_ARGS[;
192 ]AT_LOCATION_IF([
193   /* Wrong when C == '\n'. */
194   AT_LOC = last_yylloc;
196   ungetc (c, input);
199 static int
200 read_integer (]AT_YYLEX_FORMALS[)
202   int c = get_char (]AT_YYLEX_ARGS[);
203   int res = 0;
205   ]AT_USE_LEX_ARGS[;
206   while (isdigit (c))
207     {
208       res = 10 * res + (c - '0');
209       c = get_char (]AT_YYLEX_ARGS[);
210     }
212   unget_char (]AT_YYLEX_PRE_ARGS[ c);
214   return res;
218 /*---------------------------------------------------------------.
219 | Lexical analyzer returns an integer on the stack and the token |
220 | NUM, or the ASCII character read if not a number.  Skips all   |
221 | blanks and tabs, returns 0 for EOF.                            |
222 `---------------------------------------------------------------*/
224 ]AT_YYLEX_PROTOTYPE[
226   int c;
227   /* Skip white spaces.  */
228   do
229     {
230 ]AT_LOCATION_IF([
231       AT_LOC_FIRST_COLUMN = AT_LOC_LAST_COLUMN;
232       AT_LOC_FIRST_LINE   = AT_LOC_LAST_LINE;
234     }
235   while ((c = get_char (]AT_YYLEX_ARGS[)) == ' '
236          || c == '\t'
237          || (ignore_eol && c == '\n'));
239   /* Process numbers.   */
240   if (isdigit (c))
241     {
242       unget_char (]AT_YYLEX_PRE_ARGS[ c);
243       ]AT_VAL[.]AT_VALUE_UNION_IF([NUM], [ival])[ = read_integer (]AT_YYLEX_ARGS[);
244       return ]AT_CXX_IF([AT_NAMESPACE::parser::token::])[]AT_TOKEN_PREFIX[NUM;
245     }
247   /* Return end-of-file.  */
248   if (c == EOF)
249     return ]AT_CXX_IF([AT_NAMESPACE::parser::token::])[]AT_TOKEN_PREFIX[CALC_EOF;
251   /* An explicit error raised by the scanner. */
252   if (c == '#')
253     {]AT_LOCATION_IF([
254       fprintf (stderr, "%d.%d: ",
255                AT_LOC_FIRST_LINE, AT_LOC_FIRST_COLUMN);])[
256       fputs ("syntax error: invalid character: '#'\n", stderr);
257       return ]AT_CXX_IF([AT_NAMESPACE::parser::token::])[]AT_TOKEN_PREFIX[]AT_API_PREFIX[error;
258     }
260   /* Return single chars. */
261   return c;
266 m4_define([_AT_DATA_CALC_Y(c)],
267 [AT_DATA_GRAMMAR([calc.y],
268 [[/* Infix notation calculator--calc */
269 ]$4[
270 %code requires
272 ]AT_LOCATION_TYPE_SPAN_IF([[
273   typedef struct
274   {
275     int l;
276     int c;
277   } Point;
279   typedef struct
280   {
281     Point first;
282     Point last;
283   } Span;
285 # define YYLLOC_DEFAULT(Current, Rhs, N)                                \
286   do                                                                    \
287     if (N)                                                              \
288       {                                                                 \
289         (Current).first = YYRHSLOC (Rhs, 1).first;                      \
290         (Current).last  = YYRHSLOC (Rhs, N).last;                       \
291       }                                                                 \
292     else                                                                \
293       {                                                                 \
294         (Current).first = (Current).last = YYRHSLOC (Rhs, 0).last;      \
295       }                                                                 \
296   while (0)
298 ]AT_C_IF(
299 [[#include <stdio.h>
300 void location_print (FILE *o, Span s);
301 #define LOCATION_PRINT location_print
302 ]])[
304 ]])[
305   /* Exercise pre-prologue dependency to %union.  */
306   typedef int semantic_value;
309 ]AT_VALUE_UNION_IF([],
310 [[/* Exercise %union. */
311 %union
313   semantic_value ival;
314 };]])[
315 %printer { ]AT_CXX_IF([[yyo << $$]],
316                       [[fprintf (yyo, "%d", $$)]])[; } <]AT_VALUE_UNION_IF([int], [ival])[>;
318 %code provides
320   #include <stdio.h>
321   /* The input.  */
322   extern FILE *input;
323   /* Whether \n is a blank.  */
324   extern int ignore_eol;
325   extern semantic_value global_result;
326   extern int global_count;
327   extern int global_nerrs;
330 %code
332   #include <assert.h>
333   #include <string.h>
334   #define USE(Var)
336   FILE *input;
337   int ignore_eol = 0;
338   static int power (int base, int exponent);
340   ]AT_YYERROR_DECLARE[
341   ]AT_YYLEX_DECLARE_EXTERN[
343   ]AT_TOKEN_TRANSLATE_IF([[
344 #define N_
345     static
346     const char *
347     _ (const char *cp)
348     {
349       if (strcmp (cp, "end of input") == 0)
350         return "end of file";
351       else if (strcmp (cp, "number") == 0)
352         return "nombre";
353       else
354         return cp;
355     }
356   ]])[
359 ]AT_LOCATION_TYPE_SPAN_IF([[
360 %initial-action
362   @$.first.l = @$.first.c = 1;
363   @$.last = @$.first;
364 }]])[
366 /* Bison Declarations */
367 %token CALC_EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of input")], ["end of input"])[
368 %token <]AT_VALUE_UNION_IF([int], [ival])[> NUM   "number"
369 %type  <]AT_VALUE_UNION_IF([int], [ival])[> exp
371 %nonassoc '='   /* comparison          */
372 %left '-' '+'
373 %left '*' '/'
374 %precedence NEG /* negation--unary minus */
375 %right '^'      /* exponentiation        */
377 /* Grammar follows */
379 input:
380   line
381 | input line         { ]AT_PARAM_IF([++*count; ++global_count;])[ }
384 line:
385   '\n'
386 | exp '\n'           { ]AT_PARAM_IF([*result = global_result = $1;], [USE ($1);])[ }
389 exp:
390   NUM
391 | exp '=' exp
392   {
393     if ($1 != $3)]AT_LANG_CASE(
394       [c], [[
395       {
396         char buf[1024];
397         snprintf (buf, sizeof buf, "error: %d != %d", $1, $3);]AT_YYERROR_ARG_LOC_IF([[
398         yyerror (&@$, ]AT_PARAM_IF([result, count, nerrs, ])[buf);]], [[
399         {
400           YYLTYPE old_yylloc = yylloc;
401           yylloc = @$;
402           yyerror (]AT_PARAM_IF([result, count, nerrs, ])[buf);
403           yylloc = old_yylloc;
404         }
405         ]])[
406       }]],
407       [c++], [[
408       {
409         char buf[1024];
410         snprintf (buf, sizeof buf, "error: %d != %d", $1, $3);
411         ]AT_GLR_IF([[yyparser.]])[error (]AT_LOCATION_IF([[@$, ]])[buf);
412       }]])[
413     $$ = $1;
414   }
415 | exp '+' exp        { $$ = $1 + $3; }
416 | exp '-' exp        { $$ = $1 - $3; }
417 | exp '*' exp        { $$ = $1 * $3; }
418 | exp '/' exp
419   {
420     if ($3 == 0)]AT_LANG_CASE(
421       [c], [[
422       {]AT_YYERROR_ARG_LOC_IF([[
423         yyerror (&@3, ]AT_PARAM_IF([result, count, nerrs, ])["error: null divisor");]], [[
424         {
425           YYLTYPE old_yylloc = yylloc;
426           yylloc = @3;
427           yyerror (]AT_PARAM_IF([result, count, nerrs, ])["error: null divisor");
428           yylloc = old_yylloc;
429         }
430         ]])[
431       }]],
432       [c++], [[
433       {
434         ]AT_GLR_IF([[yyparser.]])[error (]AT_LOCATION_IF([[@3, ]])["error: null divisor");
435       }]])[
436     else
437       $$ = $1 / $3;
438   }
439 | '-' exp  %prec NEG { $$ = -$2; }
440 | exp '^' exp        { $$ = power ($1, $3); }
441 | '(' exp ')'        { $$ = $2; }
442 | '(' error ')'      { $$ = 1111; yyerrok; }
443 | '!'                { $$ = 0; YYERROR; }
444 | '-' error          { $$ = 0; YYERROR; }
449 power (int base, int exponent)
451   int res = 1;
452   assert (0 <= exponent);
453   for (/* Niente */; exponent; --exponent)
454     res *= base;
455   return res;
458 ]AT_LOCATION_TYPE_SPAN_IF([AT_CXX_IF([[
459 #include <iostream>
460 namespace
462   std::ostream&
463   operator<< (std::ostream& o, const Span& s)
464   {
465     o << s.first.l << '.' << s.first.c;
466     if (s.first.l != s.last.l)
467       o << '-' << s.last.l << '.' << s.last.c - 1;
468     else if (s.first.c != s.last.c - 1)
469       o << '-' << s.last.c - 1;
470     return o;
471   }
473 ]], [[
474 void
475 location_print (FILE *o, Span s)
477   fprintf (o, "%d.%d", s.first.l, s.first.c);
478   if (s.first.l != s.last.l)
479     fprintf (o, "-%d.%d", s.last.l, s.last.c - 1);
480   else if (s.first.c != s.last.c - 1)
481     fprintf (o, "-%d", s.last.c - 1);
483 ]])])[
484 ]AT_YYERROR_DEFINE[
485 ]AT_HEADER_IF([],
486 [AT_CALC_YYLEX
487 AT_CALC_MAIN])])
489 AT_HEADER_IF([AT_DATA_SOURCE([[calc-lex.]AT_LANG_EXT],
490 [[#include "calc.]AT_LANG_HDR["
492 ]AT_CALC_YYLEX])
493 AT_DATA_SOURCE([[calc-main.]AT_LANG_EXT],
494 [[#include "calc.]AT_LANG_HDR["
496 ]AT_CALC_MAIN])
498 ])# _AT_DATA_CALC_Y(c)
502 ## ------------- ##
503 ## Calc in C++.  ##
504 ## ------------- ##
506 m4_copy([AT_CALC_MAIN(c)], [AT_CALC_MAIN(c++)])
507 m4_copy([AT_CALC_YYLEX(c)], [AT_CALC_YYLEX(c++)])
508 m4_copy([_AT_DATA_CALC_Y(c)], [_AT_DATA_CALC_Y(c++)])
511 ## ----------- ##
512 ## Calc in D.  ##
513 ## ----------- ##
515 # AT_CALC_MAIN(d).
516 m4_define([AT_CALC_MAIN(d)],
517 [[int main (string[] args)
518 {]AT_PARAM_IF([[
519   semantic_value result = 0;
520   int count = 0;]])[
522   File input = args.length == 2 ? File (args[1], "r") : stdin;
523   auto l = calcLexer (input);
524   auto p = new YYParser (l);]AT_DEBUG_IF([[
525   p.setDebugLevel (1);]])[
526   return !p.parse ();
530 m4_define([AT_CALC_YYLEX(d)],
531 [[import std.range.primitives;
532 import std.stdio;
534 auto calcLexer(R)(R range)
535   if (isInputRange!R && is (ElementType!R : dchar))
537   return new CalcLexer!R(range);
540 auto calcLexer (File f)
542   import std.algorithm : map, joiner;
543   import std.utf : byDchar;
545   return f.byChunk(1024)        // avoid making a syscall roundtrip per char
546           .map!(chunk => cast(char[]) chunk) // because byChunk returns ubyte[]
547           .joiner               // combine chunks into a single virtual range of char
548           .calcLexer;           // forward to other overload
551 class CalcLexer(R) : Lexer
552   if (isInputRange!R && is (ElementType!R : dchar))
554   R input;
556   this(R r) {
557     input = r;
558   }
560   ]AT_YYERROR_DEFINE[
562   YYSemanticType semanticVal_;]AT_LOCATION_IF([[
563   YYLocation location = new YYLocation;
565   public final @property YYPosition startPos()
566   {
567     return location.begin;
568   }
570   public final @property YYPosition endPos()
571   {
572     return location.end;
573   }
574 ]])[
575   public final @property YYSemanticType semanticVal()
576   {
577     return semanticVal_;
578   }
580   int parseInt ()
581   {
582     auto res = 0;
583     import std.uni : isNumber;
584     while (input.front.isNumber)
585       {
586         res = res * 10 + (input.front - '0');]AT_LOCATION_IF([[
587         location.end.column += 1;]])[
588         input.popFront;
589       }
590     return res;
591   }
593   TokenKind yylex ()
594   {]AT_LOCATION_IF([[
595     location.begin = location.end;]])[
597     import std.uni : isWhite, isNumber;
599     // Skip initial spaces
600     while (!input.empty && input.front != '\n' && isWhite (input.front))
601       {
602         input.popFront;]AT_LOCATION_IF([[
603         location.begin.column += 1;
604         location.end.column += 1;]])[
605       }
607     // EOF.
608     if (input.empty)
609       return TokenKind.]AT_TOKEN_PREFIX[EOF;
611     // Numbers.
612     if (input.front.isNumber)
613       {
614         semanticVal_.ival = parseInt;
615         return TokenKind.]AT_TOKEN_PREFIX[NUM;
616       }
618     // Individual characters
619     auto c = input.front;]AT_LOCATION_IF([[
620     if (c == '\n')
621       {
622         location.end.line += 1;
623         location.end.column = 1;
624       }
625     else
626       location.end.column += 1;]])[
627     input.popFront;
629     // An explicit error raised by the scanner. */
630     if (c == '#')
631       {
632         stderr.writeln (]AT_LOCATION_IF([location, ": ", ])["syntax error: invalid character: '#'");
633         return TokenKind.]AT_TOKEN_PREFIX[YYerror;
634       }
636     switch (c)
637     {
638       case '+':  return TokenKind.]AT_TOKEN_PREFIX[PLUS;
639       case '-':  return TokenKind.]AT_TOKEN_PREFIX[MINUS;
640       case '*':  return TokenKind.]AT_TOKEN_PREFIX[STAR;
641       case '/':  return TokenKind.]AT_TOKEN_PREFIX[SLASH;
642       case '(':  return TokenKind.]AT_TOKEN_PREFIX[LPAR;
643       case ')':  return TokenKind.]AT_TOKEN_PREFIX[RPAR;
644       case '\n': return TokenKind.]AT_TOKEN_PREFIX[EOL;
645       case '=':  return TokenKind.]AT_TOKEN_PREFIX[EQUAL;
646       case '^':  return TokenKind.]AT_TOKEN_PREFIX[POW;
647       case '!':  return TokenKind.]AT_TOKEN_PREFIX[NOT;
648       default:   return TokenKind.]AT_TOKEN_PREFIX[YYUNDEF;
649     }
650   }
654 m4_define([_AT_DATA_CALC_Y(d)],
655 [AT_DATA_GRAMMAR([calc.y],
656 [[/* Infix notation calculator--calc */
657 ]$4[
658 %code imports {
659   alias semantic_value = int;
661 /* Exercise %union. */
662 %union
664   semantic_value ival;
666 %printer { fprintf (yyo, "%d", $$); } <ival>;
668 /* Bison Declarations */
669 %token EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of input")], ["end of input"])[
670 %token <ival> NUM   "number"
671 %type  <ival> exp
673 %token PLUS   "+"
674        MINUS  "-"
675        STAR   "*"
676        SLASH  "/"
677        LPAR   "("
678        RPAR   ")"
679        EQUAL  "="
680        POW    "^"
681        NOT    "!"
682        EOL    "\n"
684 %nonassoc "="   /* comparison          */
685 %left "-" "+"
686 %left "*" "/"
687 %precedence NEG /* negation--unary minus */
688 %right "^"      /* exponentiation        */
690 /* Grammar follows */
692 input:
693   line
694 | input line         { ]AT_PARAM_IF([++*count; ++global_count;])[ }
697 line:
698   EOL
699 | exp EOL            { ]AT_PARAM_IF([*result = global_result = $1;])[ }
702 exp:
703   NUM
704 | exp "=" exp
705   {
706     if ($1 != $3)
707       yyerror (]AT_LOCATION_IF([[@$, ]])[format ("error: %d != %d", $1, $3));
708     $$ = $1;
709   }
710 | exp "+" exp        { $$ = $1 + $3; }
711 | exp "-" exp        { $$ = $1 - $3; }
712 | exp "*" exp        { $$ = $1 * $3; }
713 | exp "/" exp
714   {
715     if ($3 == 0)
716       yyerror (]AT_LOCATION_IF([[@3, ]])["error: null divisor");
717     else
718       $$ = $1 / $3;
719   }
720 | "-" exp  %prec NEG { $$ = -$2; }
721 | exp "^" exp        { $$ = power ($1, $3); }
722 | "(" exp ")"        { $$ = $2; }
723 | "(" error ")"      { $$ = 1111; }
724 | "!"                { $$ = 0; return YYERROR; }
725 | "-" error          { $$ = 0; return YYERROR; }
730 power (int base, int exponent)
732   int res = 1;
733   assert (0 <= exponent);
734   for (/* Niente */; exponent; --exponent)
735     res *= base;
736   return res;
739 ]AT_YYERROR_DEFINE[
740 ]AT_CALC_YYLEX
741 AT_CALC_MAIN])
742 ])# _AT_DATA_CALC_Y(d)
746 ## -------------- ##
747 ## Calc in Java.  ##
748 ## -------------- ##
750 m4_define([AT_CALC_MAIN(java)],
751 [[public static void main (String[] args) throws IOException
752   {]AT_LEXPARAM_IF([[
753     Calc p = new Calc (System.in);]], [[
754     CalcLexer l = new CalcLexer (System.in);
755     Calc p = new Calc (l);]])AT_DEBUG_IF([[
756     p.setDebugLevel (1);]])[
757     boolean success = p.parse ();
758     if (!success)
759       System.exit (1);
760   }
763 m4_define([AT_CALC_YYLEX(java)],
764 [AT_LEXPARAM_IF([[%code lexer {]],
765                 [[%code epilogue { class CalcLexer implements Calc.Lexer {]])[
766   StreamTokenizer st;]AT_LOCATION_IF([[
767   PositionReader reader;]])[
769   public ]AT_LEXPARAM_IF([[YYLexer]], [[CalcLexer]])[ (InputStream is)
770   {]AT_LOCATION_IF([[
771     reader = new PositionReader (new InputStreamReader (is));
772     st = new StreamTokenizer (reader);]], [[
773     st = new StreamTokenizer (new InputStreamReader (is));]])[
774     st.resetSyntax ();
775     st.eolIsSignificant (true);
776     st.wordChars ('0', '9');
777   }
779 ]AT_LOCATION_IF([[
780   Position start = new Position (1, 0);
781   Position end = new Position (1, 0);
783   public Position getStartPos () {
784     return new Position (start);
785   }
787   public Position getEndPos () {
788     return new Position (end);
789   }
791 ]])[
792   ]AT_YYERROR_DEFINE[
794   Integer yylval;
796   public Object getLVal () {
797     return yylval;
798   }
800   public int yylex() throws IOException {;]AT_LOCATION_IF([[
801     start.set(reader.getPosition());]])[
802     int tkind = st.nextToken();]AT_LOCATION_IF([[
803     end.set(reader.getPosition());]])[
804     switch (tkind)
805       {
806       case StreamTokenizer.TT_EOF:
807         return CALC_EOF;
808       case StreamTokenizer.TT_EOL:;]AT_LOCATION_IF([[
809         end.line += 1;
810         end.column = 0;]])[
811         return (int) '\n';
812       case StreamTokenizer.TT_WORD:
813         yylval = Integer.parseInt(st.sval);]AT_LOCATION_IF([[
814         end.set(reader.getPreviousPosition());]])[
815         return NUM;
816       case ' ': case '\t':
817         return yylex();
818       case '#':
819         System.err.println(]AT_LOCATION_IF([[start + ": " + ]])["syntax error: invalid character: '#'");
820         return YYerror;
821       default:
822         return tkind;
823       }
824   }
825 ]AT_LEXPARAM_IF([], [[}]])[
829 m4_define([_AT_DATA_CALC_Y(java)],
830 [AT_DATA_GRAMMAR([Calc.y],
831 [[/* Infix notation calculator--calc */
832 %define api.prefix {Calc}
833 %define api.parser.class {Calc}
834 %define public
836 ]$4[
838 %code imports {]AT_LOCATION_IF([[
839   import java.io.BufferedReader;]])[
840   import java.io.IOException;
841   import java.io.InputStream;
842   import java.io.InputStreamReader;
843   import java.io.Reader;
844   import java.io.StreamTokenizer;
847 %code {
848   ]AT_CALC_MAIN[
850   ]AT_TOKEN_TRANSLATE_IF([[
851     static String i18n(String s)
852     {
853       if (s.equals ("end of input"))
854         return "end of file";
855       else if (s.equals ("number"))
856         return "nombre";
857       else
858         return s;
859     }
860   ]])[
863 /* Bison Declarations */
864 %token CALC_EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of input")], ["end of input"])[
865 %token <Integer> NUM "number"
866 %type  <Integer> exp
868 %nonassoc '='       /* comparison            */
869 %left '-' '+'
870 %left '*' '/'
871 %precedence NEG     /* negation--unary minus */
872 %right '^'          /* exponentiation        */
874 /* Grammar follows */
876 input:
877   line
878 | input line
881 line:
882   '\n'
883 | exp '\n'
886 exp:
887   NUM
888 | exp '=' exp
889   {
890     if ($1.intValue () != $3.intValue ())
891       yyerror (]AT_LOCATION_IF([[@$, ]])["error: " + $1 + " != " + $3);
892   }
893 | exp '+' exp        { $$ = $1 + $3; }
894 | exp '-' exp        { $$ = $1 - $3; }
895 | exp '*' exp        { $$ = $1 * $3; }
896 | exp '/' exp
897   {
898     if ($3.intValue () == 0)
899       yyerror (]AT_LOCATION_IF([[@3, ]])["error: null divisor");
900     else
901       $$ = $1 / $3;
902   }
903 | '-' exp  %prec NEG { $$ = -$2; }
904 | exp '^' exp        { $$ = (int) Math.pow ($1, $3); }
905 | '(' exp ')'        { $$ = $2; }
906 | '(' error ')'      { $$ = 1111; }
907 | '!'                { $$ = 0; return YYERROR; }
908 | '-' error          { $$ = 0; return YYERROR; }
910 ]AT_CALC_YYLEX[
911 ]AT_LOCATION_IF([[
913 ]AT_JAVA_POSITION_DEFINE])[
915 ])# _AT_DATA_JAVA_CALC_Y
920 ## ------------------ ##
921 ## Calculator tests.  ##
922 ## ------------------ ##
925 # AT_DATA_CALC_Y([BISON-OPTIONS])
926 # -------------------------------
927 # Produce 'calc.y' and, if %header was specified, 'calc-lex.c' or
928 # 'calc-lex.cc'.
929 m4_define([AT_DATA_CALC_Y],
930 [_AT_DATA_CALC_Y($[1], $[2], $[3], [$1])
934 # _AT_CHECK_CALC(CALC-OPTIONS, INPUT, [STDOUT], [NUM-STDERR-LINES])
935 # -----------------------------------------------------------------
936 # Run 'calc' on INPUT and expect no STDOUT nor STDERR.
938 # If BISON-OPTIONS contains '%debug' but not '%glr-parser', then
939 # NUM-STDERR-LINES is the number of expected lines on stderr.
940 # Currently this is ignored, though, since the output format is fluctuating.
942 # We don't count GLR's traces yet, since its traces are somewhat
943 # different from LALR's.  Likewise for D.
945 # The push traces are the same, except for "Return for a new token", don't
946 # count them.
947 m4_define([_AT_CHECK_CALC],
948 [AT_DATA([[input]],
951 AT_JAVA_IF(
952   [AT_JAVA_PARSER_CHECK([Calc $1 < input], 0, [m4_ifvaln(m4_quote($3), [$3])], [stderr])],
953   [AT_PARSER_CHECK([calc $1 input],        0, [m4_ifvaln(m4_quote($3), [$3])], [stderr])])
954 AT_LANG_MATCH([c\|c++\|java],
955   [AT_GLR_IF([],
956     [AT_CHECK([grep -c -v -E 'Return for a new token:|LAC:' stderr],
957               [ignore],
958               [m4_n([AT_DEBUG_IF([$4], [0])])])])])
962 # _AT_CHECK_CALC_ERROR($1 = BISON-OPTIONS, $2 = EXIT-STATUS, $3 = INPUT,
963 #                      $4 = [STDOUT],
964 #                      $5 = [NUM-STDERR-LINES],
965 #                      $6 = [CUSTOM-ERROR-MESSAGE])
966 #                      $7 = [CALC-OPTIONS])
967 # ----------------------------------------------------------------------
968 # Run 'calc' on INPUT, and expect a 'syntax error' message.
970 # If INPUT starts with a slash, it is used as absolute input file name,
971 # otherwise as contents.
973 # NUM-STDERR-LINES is the number of expected lines on stderr.
974 # If BISON-OPTIONS contains '%debug' but not '%glr', then NUM-STDERR-LINES
975 # is the number of expected lines on stderr.
977 # CUSTOM-ERROR-MESSAGE is the expected error message when parse.error
978 # is 'custom' and locations are enabled.  Other expected formats are
979 # computed from it.
980 m4_define([_AT_CHECK_CALC_ERROR],
981 [m4_bmatch([$3], [^/],
982   [AT_JAVA_IF(
983     [AT_JAVA_PARSER_CHECK([Calc $7 < $3], $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])],
984     [AT_PARSER_CHECK([calc $7 $3],        $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])])],
985   [AT_DATA([[input]],
986 [[$3
988   AT_JAVA_IF(
989     [AT_JAVA_PARSER_CHECK([Calc $7 < input], $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])],
990     [AT_PARSER_CHECK([calc $7 input],        $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])])
993 # Normalize the observed and expected error messages, depending upon the
994 # options.
995 # 1. Remove the traces from observed.
996 sed '
997 / \$[[0-9$]]* = /d
998 /^Cleanup:/d
999 /^Discarding/d
1000 /^Entering/d
1001 /^Error:/d
1002 /^LAC:/d
1003 /^Next/d
1004 /^Now/d
1005 /^Reading/d
1006 /^Reducing/d
1007 /^Return/d
1008 /^Shifting/d
1009 /^Stack/d
1010 /^Starting/d
1011 /^state/d
1012 /^yydestructor:/d
1013 ' stderr >at-stderr
1014 mv at-stderr stderr
1016 # 2. Create the reference error message.
1017 AT_DATA([[expout]],
1021 # 3. If locations are not used, remove them.
1022 AT_YYERROR_SEES_LOC_IF([],
1023 [[sed 's/^[-0-9.]*: //' expout >at-expout
1024 mv at-expout expout]])
1026 # 4. If parse.error is not custom, turn the expected message to
1027 # the traditional one.
1028 AT_ERROR_CUSTOM_IF([], [
1029 AT_PERL_REQUIRE([[-pi -e 'use strict;
1030   s{syntax error on token \[(.*?)\] \(expected: (.*)\)}
1031   {
1032     my $unexp = $][1;
1033     my @exps = $][2 =~ /\[(.*?)\]/g;]AT_D_IF([[
1034     # In the case of D, there are no single quotes around the symbols.
1035     $unexp =~ s/'"'(.)'"'/$][1/g;
1036     s/'"'(.)'"'/$][1/g for @exps;]])[
1037     ($][#exps && $][#exps < 4)
1038     ? "syntax error, unexpected $unexp, expecting @{[join(\" or \", @exps)]}"
1039     : "syntax error, unexpected $unexp";
1040   }eg
1041 ' expout]])
1044 # 5. If parse.error is simple, strip the', unexpected....' part.
1045 AT_ERROR_SIMPLE_IF(
1046 [[sed 's/syntax error, .*$/syntax error/' expout >at-expout
1047 mv at-expout expout]])
1049 # 6. Actually check.
1050 AT_CHECK([cat stderr], 0, [expout])
1054 # AT_CHECK_SPACES([FILES])
1055 # ------------------------
1056 # Make sure we did not introduce bad spaces.  Checked here because all
1057 # the skeletons are (or should be) exercised here.
1058 m4_define([AT_CHECK_SPACES],
1059 [AT_PERL_CHECK([-ne '
1060   chomp;
1061   print "$ARGV:$.: {$_}\n"
1062     if (# No starting/ending empty lines.
1063         (eof || $. == 1) && /^\s*$/
1064         # No trailing space.
1065         || /\s$/
1066         # No tabs.
1067         || /\t/
1068         )' $1
1073 # AT_CHECK_JAVA_GREP(FILE, [LINE], [COUNT=1])
1074 # -------------------------------------------
1075 # Check that FILE contains exactly COUNT lines matching ^LINE$
1076 # with grep.  Unquoted so that COUNT can be a shell expression.
1077 m4_define([AT_CHECK_JAVA_GREP],
1078 [AT_CHECK_UNQUOTED([grep -c '^$2$' $1], [ignore], [m4_default([$3], [1])
1079 ])])
1082 # AT_CHECK_CALC([BISON-OPTIONS], [COMPILER-OPTIONS])
1083 # --------------------------------------------------
1084 # Start a testing chunk which compiles 'calc' grammar with
1085 # BISON-OPTIONS, and performs several tests over the parser.
1086 m4_define([AT_CHECK_CALC],
1087 [m4_ifval([$3], [m4_fatal([$0: expected at most two arguments])])
1089 # We use integers to avoid dependencies upon the precision of doubles.
1090 AT_SETUP([Calculator $1 $2])
1092 AT_BISON_OPTION_PUSHDEFS([$1])
1094 AT_DATA_CALC_Y([$1])
1095 AT_FULL_COMPILE(AT_JAVA_IF([[Calc]], [[calc]]), AT_HEADER_IF([[lex], [main]], [[], []]), [$2], [-Wno-deprecated])
1097 AT_YACC_IF(
1098   [# No direct calls to malloc/free.
1099   AT_CHECK([[$EGREP '(malloc|free) *\(' calc.[ch] | $EGREP -v 'INFRINGES ON USER NAME SPACE']],
1100            [1])])
1102 AT_PUSH_IF([AT_JAVA_IF(
1103  [# Verify that this is a push parser.
1104   AT_CHECK_JAVA_GREP([[Calc.java]],
1105                      [[.*public void push_parse_initialize ().*]])])])
1107 AT_CHECK_SPACES([AT_JAVA_IF([Calc], [calc]).AT_LANG_EXT AT_HEADER_IF([AT_JAVA_IF([Calc], [calc]).AT_LANG_HDR])])
1109 # Test the precedences.
1110 # The Java traces do not show the clean up sequence at the end,
1111 # since it does not support %destructor.
1112 _AT_CHECK_CALC([],
1113 [[1 + 2 * 3 = 7
1114 1 + 2 * -3 = -5
1116 -1^2 = -1
1117 (-1)^2 = 1
1119 ---1 = -1
1121 1 - 2 - 3 = -4
1122 1 - (2 - 3) = 2
1124 2^2^3 = 256
1125 (2^2)^3 = 64]],
1126 [AT_PARAM_IF([final: 64 12 0])],
1127                [AT_JAVA_IF([1014], [1017])])
1129 # Some syntax errors.
1130 _AT_CHECK_CALC_ERROR([$1], [1], [1 2],
1131                      [AT_PARAM_IF([final: 0 0 1])],
1132                      [15],
1133                      [AT_JAVA_IF([1.3-1.4], [1.3])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] ['\n'])]])
1134 _AT_CHECK_CALC_ERROR([$1], [1], [1//2],
1135                      [AT_PARAM_IF([final: 0 0 1])],
1136                      [20],
1137                      [AT_JAVA_IF([1.3-1.4], [1.3])[: syntax error on token ['/'] (expected: [number] ['-'] ['('] ['!'])]])
1138 _AT_CHECK_CALC_ERROR([$1], [1], [error],
1139                      [AT_PARAM_IF([final: 0 0 1])],
1140                      [5],
1141                      [AT_JAVA_IF([1.1-1.2], [1.1])[: syntax error on token [invalid token] (expected: [number] ['-'] ['\n'] ['('] ['!'])]])
1142 _AT_CHECK_CALC_ERROR([$1], [1], [1 = 2 = 3],
1143                      [AT_PARAM_IF([final: 0 0 1])],
1144                      [30],
1145                      [AT_LAC_IF(
1146                        [AT_JAVA_IF([1.7-1.8], [1.7])[: syntax error on token ['='] (expected: ['-'] ['+'] ['*'] ['/'] ['^'] ['\n'])]],
1147                        [AT_JAVA_IF([1.7-1.8], [1.7])[: syntax error on token ['='] (expected: ['-'] ['+'] ['*'] ['/'] ['^'])]])])
1148 _AT_CHECK_CALC_ERROR([$1], [1],
1149                      [
1150 +1],
1151                      [AT_PARAM_IF([final: 0 0 1])],
1152                      [20],
1153                      [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'] ['('] ['!'])]])
1154 # Exercise error messages with EOF: work on an empty file.
1155 _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null],
1156                      [AT_PARAM_IF([final: 0 0 1])],
1157                      [4],
1158                      [[1.1: syntax error on token ]AT_TOKEN_TRANSLATE_IF([[[end of file]]], [[[end of input]]])[ (expected: [number] ['-'] ['\n'] ['('] ['!'])]])
1160 # Exercise the error token: without it, we die at the first error,
1161 # hence be sure to
1163 # - have several errors which exercise different shift/discardings
1164 #   - (): nothing to pop, nothing to discard
1165 #   - (1 + 1 + 1 +): a lot to pop, nothing to discard
1166 #   - (* * *): nothing to pop, a lot to discard
1167 #   - (1 + 2 * *): some to pop and discard
1169 # - test the action associated to 'error'
1171 # - check the lookahead that triggers an error is not discarded
1172 #   when we enter error recovery.  Below, the lookahead causing the
1173 #   first error is ")", which is needed to recover from the error and
1174 #   produce the "0" that triggers the "0 != 1" error.
1176 _AT_CHECK_CALC_ERROR([$1], [0],
1177                      [() + (1 + 1 + 1 +) + (* * *) + (1 * 2 * *) = 1],
1178                      [AT_PARAM_IF([final: 4444 0 5])],
1179                      [250],
1180 [AT_JAVA_IF([1.2-1.3], [1.2])[: syntax error on token [')'] (expected: [number] ['-'] ['('] ['!'])
1181 ]AT_JAVA_IF([1.18-1.19], [1.18])[: syntax error on token [')'] (expected: [number] ['-'] ['('] ['!'])
1182 ]AT_JAVA_IF([1.23-1.24], [1.23])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1183 ]AT_JAVA_IF([1.41-1.42], [1.41])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1184 ]AT_JAVA_IF([1.1-1.47], [1.1-46])[: error: 4444 != 1]])
1186 # The same, but this time exercising explicitly triggered syntax errors.
1187 # POSIX says the lookahead causing the error should not be discarded.
1188 _AT_CHECK_CALC_ERROR([$1], [0], [(!) + (1 2) = 1],
1189                      [AT_PARAM_IF([final: 2222 0 2])],
1190                      [102],
1191 [AT_JAVA_IF([1.10-1.11], [1.10])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] [')'])
1192 ]AT_JAVA_IF([1.1-1.16], [1.1-15])[: error: 2222 != 1]])
1194 _AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (1 2) = 1],
1195                      [AT_PARAM_IF([final: 2222 0 3])],
1196                      [113],
1197 [AT_JAVA_IF([1.4-1.5], [1.4])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1198 ]AT_JAVA_IF([1.12-1.13], [1.12])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] [')'])
1199 ]AT_JAVA_IF([1.1-1.18], [1.1-17])[: error: 2222 != 1]])
1201 # Check that yyerrok works properly: second error is not reported,
1202 # third and fourth are.  Parse status is successful.
1203 _AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)],
1204                      [AT_PARAM_IF([final: 3333 0 3])],
1205                      [113],
1206 [AT_JAVA_IF([1.2-1.3], [1.2])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1207 ]AT_JAVA_IF([1.10-1.11], [1.10])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
1208 ]AT_JAVA_IF([1.16-1.17], [1.16])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])]])
1211 # YYerror.
1212 # --------
1213 # Check that returning YYerror from the scanner properly enters
1214 # error-recovery without issuing a second error message.
1216 _AT_CHECK_CALC_ERROR([$1], [0], [(#) + (#) = 2222],
1217                      [AT_PARAM_IF([final: 2222 0 0])],
1218                      [102],
1219 [[1.2: syntax error: invalid character: '#'
1220 1.8: syntax error: invalid character: '#']])
1222 _AT_CHECK_CALC_ERROR([$1], [0], [(1 + #) = 1111],
1223                      [AT_PARAM_IF([final: 1111 0 0])],
1224                      [102],
1225 [[1.6: syntax error: invalid character: '#']])
1227 _AT_CHECK_CALC_ERROR([$1], [0], [(# + 1) = 1111],
1228                      [AT_PARAM_IF([final: 1111 0 0])],
1229                      [102],
1230 [[1.2: syntax error: invalid character: '#']])
1232 _AT_CHECK_CALC_ERROR([$1], [0], [(1 + # + 1) = 1111],
1233                      [AT_PARAM_IF([final: 1111 0 0])],
1234                      [102],
1235 [[1.6: syntax error: invalid character: '#']])
1237 _AT_CHECK_CALC_ERROR([$1], [0], [(1 + 1) / (1 - 1)],
1238                      [AT_PARAM_IF([final: 2 0 1])],
1239                      [102],
1240 [AT_JAVA_IF([1.11-1.18], [1.11-17])[: error: null divisor]])
1242 # Multiple start symbols.
1243 AT_MULTISTART_IF([
1244 _AT_CHECK_CALC([--num], [[123]],
1245                [[NUM => 123 (status: 0, errors: 0)]],
1246                [AT_JAVA_IF([1014], [1017])])
1247 _AT_CHECK_CALC_ERROR([$1], [1], [1 + 2 * 3],
1248                      [NUM => 0 (status: 1, errors: 1)],
1249                      [102],
1250                      [[1.3: syntax error, unexpected '+', expecting end of file]],
1251                      [--num])
1253 _AT_CHECK_CALC([--exp], [[1 + 2 * 3]],
1254                [[exp => 7 (status: 0, errors: 0)]],
1255                [AT_JAVA_IF([1014], [1017])])
1259 AT_BISON_OPTION_POPDEFS
1261 AT_CLEANUP
1262 ])# AT_CHECK_CALC
1267 # ----------------- #
1268 # LALR Calculator.  #
1269 # ----------------- #
1271 AT_BANNER([[LALR(1) Calculator.]])
1273 # AT_CHECK_CALC_LALR([BISON-OPTIONS])
1274 # -----------------------------------
1275 # Start a testing chunk which compiles 'calc' grammar with
1276 # BISON-OPTIONS, and performs several tests over the parser.
1277 m4_define([AT_CHECK_CALC_LALR],
1278 [AT_CHECK_CALC($@)])
1280 AT_CHECK_CALC_LALR([%define parse.trace])
1282 AT_CHECK_CALC_LALR([%header])
1283 AT_CHECK_CALC_LALR([%debug %locations])
1284 AT_CHECK_CALC_LALR([%locations %define api.location.type {Span}])
1286 AT_CHECK_CALC_LALR([%name-prefix "calc"])
1287 AT_CHECK_CALC_LALR([%verbose])
1288 AT_CHECK_CALC_LALR([%yacc])
1289 AT_CHECK_CALC_LALR([%define parse.error detailed])
1290 AT_CHECK_CALC_LALR([%define parse.error verbose])
1292 AT_CHECK_CALC_LALR([%define api.pure full %locations])
1293 AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %locations])
1294 AT_CHECK_CALC_LALR([%define parse.error detailed %locations])
1296 AT_CHECK_CALC_LALR([%define parse.error detailed %locations %header %define api.prefix {calc} %verbose %yacc])
1297 AT_CHECK_CALC_LALR([%define parse.error detailed %locations %header %name-prefix "calc" %define api.token.prefix {TOK_} %verbose %yacc])
1299 AT_CHECK_CALC_LALR([%debug])
1300 AT_CHECK_CALC_LALR([%define parse.error detailed %debug %locations %header %name-prefix "calc" %verbose %yacc])
1301 AT_CHECK_CALC_LALR([%define parse.error detailed %debug %locations %header %define api.prefix {calc} %verbose %yacc])
1303 AT_CHECK_CALC_LALR([%define api.pure full %define parse.error detailed %debug %locations %header %name-prefix "calc" %verbose %yacc])
1304 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])
1306 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}])
1308 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}])
1309 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}])
1310 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}])
1312 # parse.error custom.
1313 AT_CHECK_CALC_LALR([%define parse.error custom])
1314 AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc}])
1315 AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc} %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1316 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])
1317 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])
1319 # multistart.
1320 AT_CHECK_CALC_LALR([%start input exp NUM %define api.value.type union])
1321 AT_CHECK_CALC_LALR([%start input exp NUM %define api.value.type union %locations %define parse.error detailed])
1324 # ---------------- #
1325 # GLR Calculator.  #
1326 # ---------------- #
1328 AT_BANNER([[GLR Calculator.]])
1330 m4_define([AT_CHECK_CALC_GLR],
1331 [AT_CHECK_CALC([%glr-parser] $@)])
1333 AT_CHECK_CALC_GLR()
1335 AT_CHECK_CALC_GLR([%header])
1336 AT_CHECK_CALC_GLR([%locations])
1337 AT_CHECK_CALC_GLR([%locations %define api.location.type {Span}])
1338 AT_CHECK_CALC_GLR([%name-prefix "calc"])
1339 AT_CHECK_CALC_GLR([%define api.prefix {calc}])
1340 AT_CHECK_CALC_GLR([%verbose])
1341 AT_CHECK_CALC_GLR([%define parse.error verbose])
1343 AT_CHECK_CALC_GLR([%define api.pure %locations])
1344 AT_CHECK_CALC_GLR([%define parse.error verbose %locations])
1346 AT_CHECK_CALC_GLR([%define parse.error custom %locations %header %name-prefix "calc" %verbose])
1347 AT_CHECK_CALC_GLR([%define parse.error detailed %locations %header %name-prefix "calc" %verbose])
1348 AT_CHECK_CALC_GLR([%define parse.error verbose %locations %header %name-prefix "calc" %verbose])
1350 AT_CHECK_CALC_GLR([%debug])
1351 AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %header %name-prefix "calc" %verbose])
1352 AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %header %define api.prefix {calc} %define api.token.prefix {TOK_} %verbose])
1354 AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %header %name-prefix "calc" %verbose])
1356 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}])
1357 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}])
1359 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}])
1362 # ---------------------- #
1363 # LALR1 C++ Calculator.  #
1364 # ---------------------- #
1366 AT_BANNER([[LALR(1) C++ Calculator.]])
1368 # First let's try using %skeleton
1369 AT_CHECK_CALC([%skeleton "lalr1.cc" %header])
1371 m4_define([AT_CHECK_CALC_LALR1_CC],
1372 [AT_CHECK_CALC([%language "C++" $1], [$2])])
1374 AT_CHECK_CALC_LALR1_CC([])
1375 AT_CHECK_CALC_LALR1_CC([%locations])
1376 AT_CHECK_CALC_LALR1_CC([%locations], [$NO_EXCEPTIONS_CXXFLAGS])
1377 AT_CHECK_CALC_LALR1_CC([%locations %define api.location.type {Span}])
1378 AT_CHECK_CALC_LALR1_CC([%header %locations %define parse.error verbose %name-prefix "calc" %verbose])
1380 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %define api.prefix {calc} %verbose])
1381 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %name-prefix "calc" %verbose])
1383 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %define api.prefix {calc} %verbose])
1384 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %define api.prefix {calc} %define api.token.prefix {TOK_} %verbose])
1386 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}])
1388 AT_CHECK_CALC_LALR1_CC([%define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1389 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}])
1391 AT_CHECK_CALC_LALR1_CC([%header %locations %define api.location.file none])
1392 AT_CHECK_CALC_LALR1_CC([%header %locations %define api.location.file "my-location.hh"])
1394 AT_CHECK_CALC_LALR1_CC([%no-lines %header %locations %define api.location.file "my-location.hh"])
1396 AT_CHECK_CALC_LALR1_CC([%locations %define parse.lac full %define parse.error verbose])
1397 AT_CHECK_CALC_LALR1_CC([%locations %define parse.lac full %define parse.error detailed])
1398 AT_CHECK_CALC_LALR1_CC([%locations %define parse.lac full %define parse.error detailed %define parse.trace])
1400 AT_CHECK_CALC_LALR1_CC([%define parse.error custom])
1401 AT_CHECK_CALC_LALR1_CC([%define parse.error custom %locations %define api.prefix {calc} %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1402 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])
1404 # -------------------- #
1405 # GLR C++ Calculator.  #
1406 # -------------------- #
1408 AT_BANNER([[GLR C++ Calculator.]])
1410 # Again, we try also using %skeleton.
1411 AT_CHECK_CALC([%skeleton "glr.cc"])
1412 AT_CHECK_CALC([%skeleton "glr2.cc"])
1414 m4_define([AT_CHECK_CALC_GLR_CC],
1415 [AT_CHECK_CALC([%language "C++" %glr-parser] $@) # glr.cc
1416 AT_CHECK_CALC([%skeleton "glr2.cc"] $@)
1419 AT_CHECK_CALC_GLR_CC([])
1420 AT_CHECK_CALC_GLR_CC([%locations])
1421 AT_CHECK_CALC_GLR_CC([%locations %define api.location.type {Span}])
1422 AT_CHECK_CALC_GLR_CC([%header %define parse.error verbose %name-prefix "calc" %verbose])
1423 AT_CHECK_CALC_GLR_CC([%define parse.error verbose %define api.prefix {calc} %verbose])
1425 AT_CHECK_CALC_GLR_CC([%debug])
1427 AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %verbose])
1428 AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %define api.token.prefix {TOK_} %verbose])
1430 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}])
1431 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}])
1433 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}])
1436 # -------------------- #
1437 # LALR1 D Calculator.  #
1438 # -------------------- #
1440 AT_BANNER([[LALR(1) D Calculator.]])
1442 # First let's try using %skeleton
1443 AT_CHECK_CALC([%skeleton "lalr1.d"])
1445 m4_define([AT_CHECK_CALC_LALR1_D],
1446 [AT_CHECK_CALC([%language "D" $1], [$2])])
1448 AT_CHECK_CALC_LALR1_D([])
1449 AT_CHECK_CALC_LALR1_D([%locations])
1450 #AT_CHECK_CALC_LALR1_D([%locations %define api.location.type {Span}])
1451 AT_CHECK_CALC_LALR1_D([%define parse.error verbose %define api.prefix {calc} %verbose])
1453 AT_CHECK_CALC_LALR1_D([%debug])
1455 AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %verbose])
1456 AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %define api.token.prefix {TOK_} %verbose])
1457 AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %define api.symbol.prefix {SYMB_} %verbose])
1458 AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %define api.symbol.prefix {SYMB_} %define api.token.prefix {TOK_} %verbose])
1460 #AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
1461 #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}])
1464 # ----------------------- #
1465 # LALR1 Java Calculator.  #
1466 # ----------------------- #
1468 AT_BANNER([[LALR(1) Java Calculator.]])
1470 m4_define([AT_CHECK_CALC_LALR1_JAVA],
1471 [AT_CHECK_CALC([%language "Java" $1], [$2])])
1473 AT_CHECK_CALC_LALR1_JAVA
1474 AT_CHECK_CALC_LALR1_JAVA([%define parse.error custom])
1475 AT_CHECK_CALC_LALR1_JAVA([%define parse.error detailed])
1476 AT_CHECK_CALC_LALR1_JAVA([%define parse.error verbose])
1477 AT_CHECK_CALC_LALR1_JAVA([%locations %define parse.error custom])
1478 AT_CHECK_CALC_LALR1_JAVA([%locations %define parse.error detailed])
1479 AT_CHECK_CALC_LALR1_JAVA([%locations %define parse.error verbose])
1480 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error verbose])
1481 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error verbose %locations %lex-param {InputStream is}])
1483 AT_CHECK_CALC_LALR1_JAVA([%define api.push-pull both])
1484 AT_CHECK_CALC_LALR1_JAVA([%define api.push-pull both %define parse.error detailed %locations])
1485 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error custom %locations %lex-param {InputStream is} %define api.push-pull both])
1486 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error verbose %locations %lex-param {InputStream is} %define api.push-pull both])
1488 # parse.lac.
1489 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error custom %locations %define parse.lac full])
1490 AT_CHECK_CALC_LALR1_JAVA([%define parse.trace %define parse.error custom %locations %define api.push-pull both %define parse.lac full])
1493 m4_popdef([AT_CALC_MAIN])
1494 m4_popdef([AT_CALC_YYLEX])