warnings: pacify ‘gcc -Wchar-subscripts’ in yacc.c
[bison.git] / tests / calc.at
blob4d15b73202e2f0cc70821588a13e137b6477218b
1 # Simple calculator.                         -*- Autotest -*-
3 # Copyright (C) 2000-2015, 2018-2019 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 ## ---------------------------------------------------- ##
22 # -------------- #
23 # AT_CALC_MAIN.  #
24 # -------------- #
26 m4_pushdef([AT_CALC_MAIN],   [AT_LANG_DISPATCH([$0], $@)])
28 m4_define([AT_CALC_MAIN(c)],
29 [[#include <assert.h>
30 #include <unistd.h>
32 ]AT_CXX_IF([[
33 namespace
35   /* A C++ ]AT_NAME_PREFIX[parse that simulates the C signature.  */
36   int
37   ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([semantic_value *result, int *count]))[
38   {
39     ]AT_NAME_PREFIX[::parser parser]AT_PARAM_IF([ (result, count)])[;
40   #if ]AT_API_PREFIX[DEBUG
41     parser.set_debug_level (1);
42   #endif
43     return parser.parse ();
44   }
46 ]])[
48 semantic_value global_result = 0;
49 int global_count = 0;
51 /* A C main function.  */
52 int
53 main (int argc, const char **argv)
55   semantic_value result = 0;
56   int count = 0;
57   int status;
59   /* This used to be alarm (10), but that isn't enough time for a July
60      1995 vintage DEC Alphastation 200 4/100 system, according to
61      Nelson H. F. Beebe.  100 seconds was enough for regular users,
62      but the Hydra build farm, which is heavily loaded needs more.  */
64   alarm (200);
66   if (argc == 2)
67     input = fopen (argv[1], "r");
68   else
69     input = stdin;
71   if (!input)
72     {
73       perror (argv[1]);
74       return 3;
75     }
77 ]AT_CXX_IF([], [AT_DEBUG_IF([  ]AT_NAME_PREFIX[debug = 1;])])[
78   status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count]])[);
79   if (fclose (input))
80     perror ("fclose");
81   assert (global_result == result); (void) result;
82   assert (global_count == count);   (void) count;
83   return status;
85 ]])
87 m4_copy([AT_CALC_MAIN(c)], [AT_CALC_MAIN(c++)])
89 m4_define([AT_CALC_MAIN(d)],
90 [[int main (string[] args)
92   semantic_value result = 0;
93   int count = 0;
95   File input = args.length == 2 ? File (args[1], "r") : stdin;
96   auto l = calcLexer (input);
97   auto p = new YYParser (l);
98   return !p.parse ();
104 # --------------- #
105 # AT_CALC_YYLEX.  #
106 # --------------- #
108 m4_pushdef([AT_CALC_YYLEX],   [AT_LANG_DISPATCH([$0], $@)])
111 m4_define([AT_CALC_YYLEX(c)],
112 [[#include <ctype.h>
114 ]AT_YYLEX_DECLARE_EXTERN[
116 ]AT_LOCATION_IF([
117 static AT_YYLTYPE last_yylloc;
119 static int
120 get_char (]AT_YYLEX_FORMALS[)
122   int res = getc (input);
123   ]AT_USE_LEX_ARGS[;
124 ]AT_LOCATION_IF([
125   last_yylloc = AT_LOC;
126   if (res == '\n')
127     {
128       AT_LOC_LAST_LINE++;
129       AT_LOC_LAST_COLUMN = 1;
130     }
131   else
132     AT_LOC_LAST_COLUMN++;
134   return res;
137 static void
138 unget_char (]AT_YYLEX_PRE_FORMALS[ int c)
140   ]AT_USE_LEX_ARGS[;
141 ]AT_LOCATION_IF([
142   /* Wrong when C == '\n'. */
143   AT_LOC = last_yylloc;
145   ungetc (c, input);
148 static int
149 read_integer (]AT_YYLEX_FORMALS[)
151   int c = get_char (]AT_YYLEX_ARGS[);
152   int res = 0;
154   ]AT_USE_LEX_ARGS[;
155   while (isdigit (c))
156     {
157       res = 10 * res + (c - '0');
158       c = get_char (]AT_YYLEX_ARGS[);
159     }
161   unget_char (]AT_YYLEX_PRE_ARGS[ c);
163   return res;
167 /*---------------------------------------------------------------.
168 | Lexical analyzer returns an integer on the stack and the token |
169 | NUM, or the ASCII character read if not a number.  Skips all   |
170 | blanks and tabs, returns 0 for EOF.                            |
171 `---------------------------------------------------------------*/
173 ]AT_YYLEX_PROTOTYPE[
175   int c;
176   /* Skip white spaces.  */
177   do
178     {
179 ]AT_LOCATION_IF(
180 [     AT_LOC_FIRST_COLUMN = AT_LOC_LAST_COLUMN;
181       AT_LOC_FIRST_LINE   = AT_LOC_LAST_LINE;
183     }
184   while ((c = get_char (]AT_YYLEX_ARGS[)) == ' ' || c == '\t');
186   /* Process numbers.   */
187   if (isdigit (c))
188     {
189       unget_char (]AT_YYLEX_PRE_ARGS[ c);
190       ]AT_VAL[.ival = read_integer (]AT_YYLEX_ARGS[);
191       return ]AT_TOKEN_PREFIX[NUM;
192     }
194   /* Return end-of-file.  */
195   if (c == EOF)
196     return ]AT_TOKEN_PREFIX[CALC_EOF;
198   /* Return single chars. */
199   return c;
203 m4_copy([AT_CALC_YYLEX(c)], [AT_CALC_YYLEX(c++)])
205 m4_define([AT_CALC_YYLEX(d)],
206 [[import std.range.primitives;
207 import std.stdio;
209 auto calcLexer(R)(R range)
210   if (isInputRange!R && is (ElementType!R : dchar))
212   return new CalcLexer!R(range);
215 auto calcLexer (File f)
217   import std.algorithm : map, joiner;
218   import std.utf : byDchar;
220   return f.byChunk(1024)        // avoid making a syscall roundtrip per char
221           .map!(chunk => cast(char[]) chunk) // because byChunk returns ubyte[]
222           .joiner               // combine chunks into a single virtual range of char
223           .calcLexer;           // forward to other overload
226 class CalcLexer(R) : Lexer
227   if (isInputRange!R && is (ElementType!R : dchar))
229   R input;
231   this(R r) {
232     input = r;
233   }
235   ]AT_YYERROR_DEFINE[
237   YYSemanticType semanticVal_;]AT_LOCATION_IF([[
238   YYLocation location = new YYLocation;
240   public final @property YYPosition startPos()
241   {
242     return location.begin;
243   }
245   public final @property YYPosition endPos()
246   {
247     return location.end;
248   }
249 ]])[
250   public final @property YYSemanticType semanticVal()
251   {
252     return semanticVal_;
253   }
255   int parseInt ()
256   {
257     auto res = 0;
258     import std.uni : isNumber;
259     while (input.front.isNumber)
260       {
261         res = res * 10 + (input.front - '0');]AT_LOCATION_IF([[
262         location.end.column += 1;]])[
263         input.popFront;
264       }
265     return res;
266   }
268   int yylex ()
269   {]AT_LOCATION_IF([[
270     location.begin = location.end;]])[
272     import std.uni : isWhite, isNumber;
274     // Skip initial spaces
275     while (!input.empty && input.front != '\n' && isWhite (input.front))
276       {
277         input.popFront;]AT_LOCATION_IF([[
278         location.begin.column += 1;
279         location.end.column += 1;]])[
280       }
282     // Handle EOF.
283     if (input.empty)
284       return YYTokenType.EOF;
286     // Numbers.
287     if (input.front.isNumber)
288       {
289         semanticVal_.ival = parseInt;
290         return YYTokenType.NUM;
291       }
293     // Individual characters
294     auto c = input.front;]AT_LOCATION_IF([[
295     if (c == '\n')
296       {
297         location.end.line += 1;
298         location.end.column = 1;
299       }
300     else
301       location.end.column += 1;]])[
302     input.popFront;
303     return c;
304   }
309 # -------------- #
310 # AT_DATA_CALC.  #
311 # -------------- #
314 # _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
315 # -----------------------------------------------
316 # Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
317 # 'calc-lex.cc'.
319 # Don't call this macro directly, because it contains some occurrences
320 # of '$1' etc. which will be interpreted by m4.  So you should call it
321 # with $1, $2, and $3 as arguments, which is what AT_DATA_CALC_Y does.
323 # When %defines is not passed, generate a single self-contained file.
324 # Otherwise, generate three: calc.y with the parser, calc-lex.c with
325 # the scanner, and calc-main.c with "main()".  This is in order to
326 # stress the use of the generated parser header.  To avoid code
327 # duplication, AT_CALC_YYLEX and AT_CALC_MAIN contain the body of these
328 # two later files.
329 m4_define([_AT_DATA_CALC_Y],
330 [m4_if([$1$2$3], $[1]$[2]$[3], [],
331        [m4_fatal([$0: Invalid arguments: $@])])dnl
333 AT_DATA_GRAMMAR([calc.y],
334 [[/* Infix notation calculator--calc */
335 ]$4[
336 ]AT_CXX_IF([%define global_tokens_and_yystype])[
337 ]AT_D_IF([[
338 %code imports {
339   alias semantic_value = int;
341 ]], [[
342 %code requires
344 ]AT_LOCATION_TYPE_SPAN_IF([[
345   typedef struct
346   {
347     int l;
348     int c;
349   } Point;
351   typedef struct
352   {
353     Point first;
354     Point last;
355   } Span;
357 # define YYLLOC_DEFAULT(Current, Rhs, N)                                \
358   do                                                                    \
359     if (N)                                                              \
360       {                                                                 \
361         (Current).first = YYRHSLOC (Rhs, 1).first;                      \
362         (Current).last  = YYRHSLOC (Rhs, N).last;                       \
363       }                                                                 \
364     else                                                                \
365       {                                                                 \
366         (Current).first = (Current).last = YYRHSLOC (Rhs, 0).last;      \
367       }                                                                 \
368   while (0)
370 ]AT_C_IF(
371 [[#include <stdio.h>
372 void location_print (FILE *o, Span s);
373 #define LOCATION_PRINT location_print
374 ]])[
376 ]])[
377   /* Exercise pre-prologue dependency to %union.  */
378   typedef int semantic_value;
380 ]])[
382 /* Exercise %union. */
383 %union
385   semantic_value ival;
387 %printer { ]AT_CXX_IF([[yyo << $$]],
388                       [[fprintf (yyo, "%d", $$)]])[; } <ival>;
390 ]AT_D_IF([], [[
391 %code provides
393   #include <stdio.h>
394   /* The input.  */
395   extern FILE *input;
396   extern semantic_value global_result;
397   extern int global_count;
400 %code
402   #include <assert.h>
403   #include <string.h>
404   #define USE(Var)
406   FILE *input;
407   static int power (int base, int exponent);
409   ]AT_YYERROR_DECLARE[
410   ]AT_YYLEX_DECLARE_EXTERN[
412 ]])[
414 ]AT_LOCATION_TYPE_SPAN_IF([[
415 %initial-action
417   @$.first.l = @$.first.c = 1;
418   @$.last = @$.first;
419 }]])[
421 /* Bison Declarations */
422 %token CALC_EOF 0 "end of input"
423 %token <ival> NUM "number"
424 %type  <ival> exp
426 %nonassoc '='   /* comparison          */
427 %left '-' '+'
428 %left '*' '/'
429 %precedence NEG /* negation--unary minus */
430 %right '^'      /* exponentiation        */
432 /* Grammar follows */
434 input:
435   line
436 | input line         { ]AT_PARAM_IF([++*count; ++global_count;])[ }
439 line:
440   '\n'
441 | exp '\n'           { ]AT_PARAM_IF([*result = global_result = $1;], [AT_D_IF([], [USE ($1);])])[ }
444 exp:
445   NUM
446 | exp '=' exp
447   {
448     if ($1 != $3)]AT_D_IF([
449       stderr.writefln ("calc: error: %d != %d", $1, $3);], [
450       fprintf (stderr, "calc: error: %d != %d\n", $1, $3);], [
451       ])[
452     $$ = $1;
453   }
454 | exp '+' exp        { $$ = $1 + $3;        }
455 | exp '-' exp        { $$ = $1 - $3;        }
456 | exp '*' exp        { $$ = $1 * $3;        }
457 | exp '/' exp        { $$ = $1 / $3;        }
458 | '-' exp  %prec NEG { $$ = -$2;            }
459 | exp '^' exp        { $$ = power ($1, $3); }
460 | '(' exp ')'        { $$ = $2;             }
461 | '(' error ')'      { $$ = 1111; ]AT_D_IF([], [yyerrok;])[  }
462 | '!'                { $$ = 0; ]AT_D_IF([return YYERROR], [YYERROR])[;     }
463 | '-' error          { $$ = 0; ]AT_D_IF([return YYERROR], [YYERROR])[;     }
468 power (int base, int exponent)
470   int res = 1;
471   assert (0 <= exponent);
472   for (/* Niente */; exponent; --exponent)
473     res *= base;
474   return res;
477 ]AT_LOCATION_TYPE_SPAN_IF([AT_CXX_IF([[
478 #include <iostream>
479 namespace
481   std::ostream&
482   operator<< (std::ostream& o, const Span& s)
483   {
484     o << s.first.l << '.' << s.first.c;
485     if (s.first.l != s.last.l)
486       o << '-' << s.last.l << '.' << s.last.c - 1;
487     else if (s.first.c != s.last.c - 1)
488       o << '-' << s.last.c - 1;
489     return o;
490   }
492 ]], [[
493 void
494 location_print (FILE *o, Span s)
496   fprintf (o, "%d.%d", s.first.l, s.first.c);
497   if (s.first.l != s.last.l)
498     fprintf (o, "-%d.%d", s.last.l, s.last.c - 1);
499   else if (s.first.c != s.last.c - 1)
500     fprintf (o, "-%d", s.last.c - 1);
502 ]])])[
503 ]AT_YYERROR_DEFINE[
504 ]AT_DEFINES_IF([],
505 [AT_CALC_YYLEX
506 AT_CALC_MAIN])])
508 AT_DEFINES_IF([AT_DATA_SOURCE([[calc-lex.]AT_LANG_EXT],
509 [[#include "calc.]AT_LANG_HDR["
511 ]AT_CALC_YYLEX])
512 AT_DATA_SOURCE([[calc-main.]AT_LANG_EXT],
513 [[#include "calc.]AT_LANG_HDR["
515 ]AT_CALC_MAIN])
517 ])# _AT_DATA_CALC_Y
520 # AT_DATA_CALC_Y([BISON-OPTIONS])
521 # -------------------------------
522 # Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
523 # 'calc-lex.cc'.
524 m4_define([AT_DATA_CALC_Y],
525 [_AT_DATA_CALC_Y($[1], $[2], $[3], [$1])
530 # _AT_CHECK_CALC(BISON-OPTIONS, INPUT, [NUM-STDERR-LINES])
531 # --------------------------------------------------------
532 # Run 'calc' on INPUT and expect no STDOUT nor STDERR.
534 # If BISON-OPTIONS contains '%debug' but not '%glr-parser', then
535 # NUM-STDERR-LINES is the number of expected lines on stderr.
536 # Currently this is ignored, though, since the output format is fluctuating.
538 # We don't count GLR's traces yet, since its traces are somewhat
539 # different from LALR's.
540 m4_define([_AT_CHECK_CALC],
541 [AT_DATA([[input]],
542 [[$2
544 AT_PARSER_CHECK([calc input], 0, [], [stderr])
548 # _AT_CHECK_CALC_ERROR(BISON-OPTIONS, EXIT-STATUS, INPUT,
549 #                      [NUM-STDERR-LINES],
550 #                      [VERBOSE-AND-LOCATED-ERROR-MESSAGE])
551 # ---------------------------------------------------------
552 # Run 'calc' on INPUT, and expect a 'syntax error' message.
554 # If INPUT starts with a slash, it is used as absolute input file name,
555 # otherwise as contents.
557 # NUM-STDERR-LINES is the number of expected lines on stderr.
558 # Currently this is ignored, though, since the output format is fluctuating.
560 # If BISON-OPTIONS contains '%location', then make sure the ERROR-LOCATION
561 # is correctly output on stderr.
563 # If BISON-OPTIONS contains '%define parse.error verbose', then make sure the
564 # IF-YYERROR-VERBOSE message is properly output after 'syntax error, '
565 # on STDERR.
567 # If BISON-OPTIONS contains '%debug' but not '%glr', then NUM-STDERR-LINES
568 # is the number of expected lines on stderr.
569 m4_define([_AT_CHECK_CALC_ERROR],
570 [m4_bmatch([$3], [^/],
571            [AT_PARSER_CHECK([calc $3], $2, [], [stderr])],
572            [AT_DATA([[input]],
573 [[$3
575 AT_PARSER_CHECK([calc input], $2, [], [stderr])])
577 # Normalize the observed and expected error messages, depending upon the
578 # options.
579 # 1. Remove the traces from observed.
580 sed '/^Starting/d
581 /^Entering/d
582 /^Stack/d
583 /^Reading/d
584 /^Reducing/d
585 /^Return/d
586 /^Shifting/d
587 /^state/d
588 /^Cleanup:/d
589 /^Error:/d
590 /^Next/d
591 /^Now/d
592 /^Discarding/d
593 / \$[[0-9$]]* = /d
594 /^yydestructor:/d' stderr >at-stderr
595 mv at-stderr stderr
597 # 2. Create the reference error message.
598 AT_DATA([[expout]],
602 # 3. If locations are not used, remove them.
603 AT_YYERROR_SEES_LOC_IF([],
604 [[sed 's/^[-0-9.]*: //' expout >at-expout
605 mv at-expout expout]])
607 # 4. If error-verbose is not used, strip the', unexpected....' part.
608 m4_bmatch([$1], [%define parse.error verbose], [],
609 [[sed 's/syntax error, .*$/syntax error/' expout >at-expout
610 mv at-expout expout]])
612 # 5. Check
613 AT_CHECK([cat stderr], 0, [expout])
617 # AT_CHECK_SPACES([FILES])
618 # ------------------------
619 # Make sure we did not introduce bad spaces.  Checked here because all
620 # the skeletons are (or should be) exercized here.
621 m4_define([AT_CHECK_SPACES],
622 [AT_PERL_CHECK([-ne '
623   chomp;
624   print "$ARGV:$.: {$_}\n"
625     if (# No starting/ending empty lines.
626         (eof || $. == 1) && /^\s*$/
627         # No trailing space.
628         || /\s$/
629         # No tabs.
630         || /\t/
631         )' $1
636 # AT_CHECK_CALC([BISON-OPTIONS], [COMPILER-OPTIONS])
637 # --------------------------------------------------
638 # Start a testing chunk which compiles 'calc' grammar with
639 # BISON-OPTIONS, and performs several tests over the parser.
640 m4_define([AT_CHECK_CALC],
641 [m4_ifval([$3], [m4_fatal([$0: expected at most two arguments])])
643 # We use integers to avoid dependencies upon the precision of doubles.
644 AT_SETUP([Calculator $1 $2])
646 AT_BISON_OPTION_PUSHDEFS([$1])
648 AT_DATA_CALC_Y([$1])
649 AT_FULL_COMPILE([calc], AT_DEFINES_IF([[lex], [main]], [[], []]), [$2], [-Wno-deprecated])
650 AT_CHECK_SPACES([calc.AT_LANG_EXT AT_DEFINES_IF([calc.AT_LANG_HDR])])
652 # Test the precedences.
653 _AT_CHECK_CALC([$1],
654 [1 + 2 * 3 = 7
655 1 + 2 * -3 = -5
657 -1^2 = -1
658 (-1)^2 = 1
660 ---1 = -1
662 1 - 2 - 3 = -4
663 1 - (2 - 3) = 2
665 2^2^3 = 256
666 (2^2)^3 = 64],
667                [842])
669 # Some syntax errors.
670 _AT_CHECK_CALC_ERROR([$1], [1], [1 2], [15],
671                      [1.3: syntax error, unexpected number])
672 _AT_CHECK_CALC_ERROR([$1], [1], [1//2], [20],
673                      [1.3: syntax error, unexpected '/', expecting number or '-' or '(' or '!'])
674 _AT_CHECK_CALC_ERROR([$1], [1], [error], [5],
675                      [1.1: syntax error, unexpected $undefined])
676 _AT_CHECK_CALC_ERROR([$1], [1], [1 = 2 = 3], [30],
677                      [1.7: syntax error, unexpected '='])
678 _AT_CHECK_CALC_ERROR([$1], [1],
679                      [
680 +1],
681                      [20],
682                      [2.1: syntax error, unexpected '+'])
683 # Exercise error messages with EOF: work on an empty file.
684 _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null], [4],
685                      [1.1: syntax error, unexpected end of input])
687 # Exercise the error token: without it, we die at the first error,
688 # hence be sure to
690 # - have several errors which exercise different shift/discardings
691 #   - (): nothing to pop, nothing to discard
692 #   - (1 + 1 + 1 +): a lot to pop, nothing to discard
693 #   - (* * *): nothing to pop, a lot to discard
694 #   - (1 + 2 * *): some to pop and discard
696 # - test the action associated to 'error'
698 # - check the lookahead that triggers an error is not discarded
699 #   when we enter error recovery.  Below, the lookahead causing the
700 #   first error is ")", which is needed to recover from the error and
701 #   produce the "0" that triggers the "0 != 1" error.
703 _AT_CHECK_CALC_ERROR([$1], [0],
704                      [() + (1 + 1 + 1 +) + (* * *) + (1 * 2 * *) = 1],
705                      [250],
706 [1.2: syntax error, unexpected ')', expecting number or '-' or '(' or '!'
707 1.18: syntax error, unexpected ')', expecting number or '-' or '(' or '!'
708 1.23: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
709 1.41: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
710 calc: error: 4444 != 1])
712 # The same, but this time exercising explicitly triggered syntax errors.
713 # POSIX says the lookahead causing the error should not be discarded.
714 _AT_CHECK_CALC_ERROR([$1], [0], [(!) + (1 2) = 1], [102],
715 [1.10: syntax error, unexpected number
716 calc: error: 2222 != 1])
717 _AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (1 2) = 1], [113],
718 [1.4: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
719 1.12: syntax error, unexpected number
720 calc: error: 2222 != 1])
722 # Check that yyerrok works properly: second error is not reported,
723 # third and fourth are.  Parse status is succesful.
724 _AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)], [113],
725 [1.2: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
726 1.10: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
727 1.16: syntax error, unexpected '*', expecting number or '-' or '(' or '!'])
729 AT_BISON_OPTION_POPDEFS
731 AT_CLEANUP
732 ])# AT_CHECK_CALC
737 # ------------------------ #
738 # Simple LALR Calculator.  #
739 # ------------------------ #
741 AT_BANNER([[Simple LALR(1) Calculator.]])
743 # AT_CHECK_CALC_LALR([BISON-OPTIONS])
744 # -----------------------------------
745 # Start a testing chunk which compiles 'calc' grammar with
746 # BISON-OPTIONS, and performs several tests over the parser.
747 m4_define([AT_CHECK_CALC_LALR],
748 [AT_CHECK_CALC($@)])
750 AT_CHECK_CALC_LALR()
752 AT_CHECK_CALC_LALR([%defines])
753 AT_CHECK_CALC_LALR([%locations])
754 AT_CHECK_CALC_LALR([%locations %define api.location.type {Span}])
756 AT_CHECK_CALC_LALR([%name-prefix "calc"])
757 AT_CHECK_CALC_LALR([%verbose])
758 AT_CHECK_CALC_LALR([%yacc])
759 AT_CHECK_CALC_LALR([%define parse.error verbose])
761 AT_CHECK_CALC_LALR([%define api.pure full %locations])
762 AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %locations])
763 AT_CHECK_CALC_LALR([%define parse.error verbose %locations])
765 AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %define api.prefix {calc} %verbose %yacc])
766 AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %name-prefix "calc" %define api.token.prefix {TOK_} %verbose %yacc])
768 AT_CHECK_CALC_LALR([%debug])
769 AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
770 AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %define api.prefix {calc} %verbose %yacc])
772 AT_CHECK_CALC_LALR([%define api.pure full %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
773 AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure full %define parse.error verbose %debug %locations %defines %define api.prefix {calc} %verbose %yacc])
775 AT_CHECK_CALC_LALR([%define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
777 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} %parse-param {int *count}])
779 # ----------------------- #
780 # Simple GLR Calculator.  #
781 # ----------------------- #
783 AT_BANNER([[Simple GLR Calculator.]])
785 # AT_CHECK_CALC_GLR([BISON-OPTIONS])
786 # ----------------------------------
787 # Start a testing chunk which compiles 'calc' grammar with
788 # BISON-OPTIONS and %glr-parser, and performs several tests over the parser.
789 m4_define([AT_CHECK_CALC_GLR],
790 [AT_CHECK_CALC([%glr-parser] $@)])
793 AT_CHECK_CALC_GLR()
795 AT_CHECK_CALC_GLR([%defines])
796 AT_CHECK_CALC_GLR([%locations])
797 AT_CHECK_CALC_GLR([%locations %define api.location.type {Span}])
798 AT_CHECK_CALC_GLR([%name-prefix "calc"])
799 AT_CHECK_CALC_GLR([%define api.prefix {calc}])
800 AT_CHECK_CALC_GLR([%verbose])
801 AT_CHECK_CALC_GLR([%yacc])
802 AT_CHECK_CALC_GLR([%define parse.error verbose])
804 AT_CHECK_CALC_GLR([%define api.pure %locations])
805 AT_CHECK_CALC_GLR([%define parse.error verbose %locations])
807 AT_CHECK_CALC_GLR([%define parse.error verbose %locations %defines %name-prefix "calc" %verbose %yacc])
809 AT_CHECK_CALC_GLR([%debug])
810 AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
811 AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %define api.prefix {calc} %define api.token.prefix {TOK_} %verbose %yacc])
813 AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
815 AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
816 AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
818 AT_CHECK_CALC_GLR([%no-lines %define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
821 # ----------------------------- #
822 # Simple LALR1 C++ Calculator.  #
823 # ----------------------------- #
825 AT_BANNER([[Simple LALR(1) C++ Calculator.]])
827 # First let's try using %skeleton
828 AT_CHECK_CALC([%skeleton "lalr1.cc" %defines])
830 # AT_CHECK_CALC_LALR1_CC([BISON-OPTIONS])
831 # ---------------------------------------
832 # Start a testing chunk which compiles 'calc' grammar with
833 # the C++ skeleton, and performs several tests over the parser.
834 m4_define([AT_CHECK_CALC_LALR1_CC],
835 [AT_CHECK_CALC([%language "C++" $1], [$2])])
837 AT_CHECK_CALC_LALR1_CC([])
838 AT_CHECK_CALC_LALR1_CC([%locations])
839 AT_CHECK_CALC_LALR1_CC([%locations], [$NO_EXCEPTIONS_CXXFLAGS])
840 AT_CHECK_CALC_LALR1_CC([%locations %define api.location.type {Span}])
841 AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %name-prefix "calc" %verbose %yacc])
843 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %define api.prefix {calc} %verbose %yacc])
844 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
846 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %yacc])
847 AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %define api.prefix {calc} %define api.token.prefix {TOK_} %verbose %yacc])
849 AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
851 AT_CHECK_CALC_LALR1_CC([%define parse.error verbose %debug %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
852 AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
854 AT_CHECK_CALC_LALR1_CC([%defines %locations %define api.location.file none])
855 AT_CHECK_CALC_LALR1_CC([%defines %locations %define api.location.file "my-location.hh"])
857 AT_CHECK_CALC_LALR1_CC([%no-lines %defines %locations %define api.location.file "my-location.hh"])
860 # --------------------------- #
861 # Simple GLR C++ Calculator.  #
862 # --------------------------- #
864 AT_BANNER([[Simple GLR C++ Calculator.]])
866 # Again, we try also using %skeleton.
867 AT_CHECK_CALC([%skeleton "glr.cc"])
869 # AT_CHECK_CALC_GLR_CC([BISON-OPTIONS])
870 # -------------------------------------
871 # Start a testing chunk which compiles 'calc' grammar with
872 # the GLR C++ skeleton, and performs several tests over the parser.
873 m4_define([AT_CHECK_CALC_GLR_CC],
874 [AT_CHECK_CALC([%language "C++" %glr-parser] $@)])
876 AT_CHECK_CALC_GLR_CC([])
877 AT_CHECK_CALC_GLR_CC([%locations])
878 AT_CHECK_CALC_GLR_CC([%locations %define api.location.type {Span}])
879 AT_CHECK_CALC_GLR_CC([%defines %define parse.error verbose %name-prefix "calc" %verbose %yacc])
880 AT_CHECK_CALC_GLR_CC([%define parse.error verbose %define api.prefix {calc} %verbose %yacc])
882 AT_CHECK_CALC_GLR_CC([%debug])
884 AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
885 AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %define api.token.prefix {TOK_} %verbose %yacc])
887 AT_CHECK_CALC_GLR_CC([%locations %defines %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
888 AT_CHECK_CALC_GLR_CC([%locations %defines %define parse.error verbose %debug %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
890 AT_CHECK_CALC_GLR_CC([%no-lines %locations %defines %define parse.error verbose %debug %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
893 # --------------------------- #
894 # Simple LALR1 D Calculator.  #
895 # --------------------------- #
897 AT_BANNER([[Simple LALR(1) D Calculator.]])
899 # First let's try using %skeleton
900 AT_CHECK_CALC([%skeleton "lalr1.d"])
902 # AT_CHECK_CALC_LALR1_D([BISON-OPTIONS])
903 # ---------------------------------------
904 # Start a testing chunk which compiles 'calc' grammar with
905 # the C++ skeleton, and performs several tests over the parser.
906 m4_define([AT_CHECK_CALC_LALR1_D],
907 [AT_CHECK_CALC([%language "D" $1], [$2])])
909 AT_CHECK_CALC_LALR1_D([])
910 AT_CHECK_CALC_LALR1_D([%locations])
911 #AT_CHECK_CALC_LALR1_D([%locations %define api.location.type {Span}])
912 AT_CHECK_CALC_LALR1_D([%define parse.error verbose %define api.prefix {calc} %verbose])
914 AT_CHECK_CALC_LALR1_D([%debug])
916 AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %verbose])
917 #AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %define api.token.prefix {TOK_} %verbose])
919 #AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %verbose %parse-param {semantic_value *result} %parse-param {int *count}])
920 #AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result} %parse-param {int *count}])
922 m4_popdef([AT_CALC_MAIN])
923 m4_popdef([AT_CALC_YYLEX])