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 ## ---------------------------------------------------- ##
26 m4_pushdef([AT_CALC_MAIN], [AT_LANG_DISPATCH([$0], $@)])
28 m4_define([AT_CALC_MAIN(c)],
35 /* A C++ ]AT_NAME_PREFIX[parse that simulates the C signature. */
37 ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([semantic_value *result, int *count]))[
39 ]AT_NAME_PREFIX[::parser parser]AT_PARAM_IF([ (result, count)])[;
40 #if ]AT_API_PREFIX[DEBUG
41 parser.set_debug_level (1);
43 return parser.parse ();
48 semantic_value global_result = 0;
51 /* A C main function. */
53 main (int argc, const char **argv)
55 semantic_value result = 0;
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. */
67 input = fopen (argv[1], "r");
77 ]AT_CXX_IF([], [AT_DEBUG_IF([ ]AT_NAME_PREFIX[debug = 1;])])[
78 status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count]])[);
81 assert (global_result == result); (void) result;
82 assert (global_count == count); (void) count;
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;
95 File input = args.length == 2 ? File (args[1], "r") : stdin;
96 auto l = calcLexer (input);
97 auto p = new YYParser (l);
108 m4_pushdef([AT_CALC_YYLEX], [AT_LANG_DISPATCH([$0], $@)])
111 m4_define([AT_CALC_YYLEX(c)],
114 ]AT_YYLEX_DECLARE_EXTERN[
117 static AT_YYLTYPE last_yylloc;
120 get_char (]AT_YYLEX_FORMALS[)
122 int res = getc (input);
125 last_yylloc = AT_LOC;
129 AT_LOC_LAST_COLUMN = 1;
132 AT_LOC_LAST_COLUMN++;
138 unget_char (]AT_YYLEX_PRE_FORMALS[ int c)
142 /* Wrong when C == '\n'. */
143 AT_LOC = last_yylloc;
149 read_integer (]AT_YYLEX_FORMALS[)
151 int c = get_char (]AT_YYLEX_ARGS[);
157 res = 10 * res + (c - '0');
158 c = get_char (]AT_YYLEX_ARGS[);
161 unget_char (]AT_YYLEX_PRE_ARGS[ c);
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 `---------------------------------------------------------------*/
176 /* Skip white spaces. */
180 [ AT_LOC_FIRST_COLUMN = AT_LOC_LAST_COLUMN;
181 AT_LOC_FIRST_LINE = AT_LOC_LAST_LINE;
184 while ((c = get_char (]AT_YYLEX_ARGS[)) == ' ' || c == '\t');
186 /* Process numbers. */
189 unget_char (]AT_YYLEX_PRE_ARGS[ c);
190 ]AT_VAL[.ival = read_integer (]AT_YYLEX_ARGS[);
191 return ]AT_TOKEN_PREFIX[NUM;
194 /* Return end-of-file. */
196 return ]AT_TOKEN_PREFIX[CALC_EOF;
198 /* Return single chars. */
203 m4_copy([AT_CALC_YYLEX(c)], [AT_CALC_YYLEX(c++)])
205 m4_define([AT_CALC_YYLEX(d)],
206 [[import std.range.primitives;
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))
237 YYSemanticType semanticVal_;]AT_LOCATION_IF([[
238 YYLocation location = new YYLocation;
240 public final @property YYPosition startPos()
242 return location.begin;
245 public final @property YYPosition endPos()
250 public final @property YYSemanticType semanticVal()
258 import std.uni : isNumber;
259 while (input.front.isNumber)
261 res = res * 10 + (input.front - '0');]AT_LOCATION_IF([[
262 location.end.column += 1;]])[
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))
277 input.popFront;]AT_LOCATION_IF([[
278 location.begin.column += 1;
279 location.end.column += 1;]])[
284 return YYTokenType.EOF;
287 if (input.front.isNumber)
289 semanticVal_.ival = parseInt;
290 return YYTokenType.NUM;
293 // Individual characters
294 auto c = input.front;]AT_LOCATION_IF([[
297 location.end.line += 1;
298 location.end.column = 1;
301 location.end.column += 1;]])[
314 # _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
315 # -----------------------------------------------
316 # Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
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
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 */
336 ]AT_CXX_IF([%define global_tokens_and_yystype])[
339 alias semantic_value = int;
344 ]AT_LOCATION_TYPE_SPAN_IF([[
357 # define YYLLOC_DEFAULT(Current, Rhs, N) \
361 (Current).first = YYRHSLOC (Rhs, 1).first; \
362 (Current).last = YYRHSLOC (Rhs, N).last; \
366 (Current).first = (Current).last = YYRHSLOC (Rhs, 0).last; \
372 void location_print (FILE *o, Span s);
373 #define LOCATION_PRINT location_print
377 /* Exercise pre-prologue dependency to %union. */
378 typedef int semantic_value;
382 /* Exercise %union. */
387 %printer { ]AT_CXX_IF([[yyo << $$]],
388 [[fprintf (yyo, "%d", $$)]])[; } <ival>;
396 extern semantic_value global_result;
397 extern int global_count;
407 static int power (int base, int exponent);
410 ]AT_YYLEX_DECLARE_EXTERN[
414 ]AT_LOCATION_TYPE_SPAN_IF([[
417 @$.first.l = @$.first.c = 1;
421 /* Bison Declarations */
422 %token CALC_EOF 0 "end of input"
423 %token <ival> NUM "number"
426 %nonassoc '=' /* comparison */
429 %precedence NEG /* negation--unary minus */
430 %right '^' /* exponentiation */
432 /* Grammar follows */
436 | input line { ]AT_PARAM_IF([++*count; ++global_count;])[ }
441 | exp '\n' { ]AT_PARAM_IF([*result = global_result = $1;], [AT_D_IF([], [USE ($1);])])[ }
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);], [
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)
471 assert (0 <= exponent);
472 for (/* Niente */; exponent; --exponent)
477 ]AT_LOCATION_TYPE_SPAN_IF([AT_CXX_IF([[
482 operator<< (std::ostream& o, const Span& s)
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;
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);
508 AT_DEFINES_IF([AT_DATA_SOURCE([[calc-lex.]AT_LANG_EXT],
509 [[#include "calc.]AT_LANG_HDR["
512 AT_DATA_SOURCE([[calc-main.]AT_LANG_EXT],
513 [[#include "calc.]AT_LANG_HDR["
520 # AT_DATA_CALC_Y([BISON-OPTIONS])
521 # -------------------------------
522 # Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
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],
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, '
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])],
575 AT_PARSER_CHECK([calc input], $2, [], [stderr])])
577 # Normalize the observed and expected error messages, depending upon the
579 # 1. Remove the traces from observed.
594 /^yydestructor:/d' stderr >at-stderr
597 # 2. Create the reference error message.
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]])
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 '
624 print "$ARGV:$.: {$_}\n"
625 if (# No starting/ending empty lines.
626 (eof || $. == 1) && /^\s*$/
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])
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.
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],
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,
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],
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
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],
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] $@)])
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])