]> git.saurik.com Git - bison.git/blame - tests/calc.at
* src/closure.c (print_firsts): Display of the symbol tags.
[bison.git] / tests / calc.at
CommitLineData
342b8b6e
AD
1# Checking the output filenames. -*- Autotest -*-
2# Copyright 2000, 2001 Free Software Foundation, Inc.
bfb07874 3
342b8b6e
AD
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 2, or (at your option)
7# any later version.
bfb07874 8
342b8b6e
AD
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
bfb07874 13
342b8b6e
AD
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17# 02111-1307, USA.
bfb07874 18
342b8b6e 19AT_BANNER([[Simple Calculator.]])
bfb07874
AD
20
21## ---------------------------------------------------- ##
22## Compile the grammar described in the documentation. ##
23## ---------------------------------------------------- ##
24
25
26# ------------------------- #
27# Helping Autotest macros. #
28# ------------------------- #
29
30
31# _AT_DATA_CALC_Y($1, $2, $3, [CPP-DIRECTIVES])
32# ---------------------------------------------
33# Produce `calc.y'. Don't call this macro directly, because it contains
34# some occurrences of `$1' etc. which will be interpreted by m4. So
35# you should call it with $1, $2, and $3 as arguments, which is what
36# AT_DATA_CALC_Y does.
342b8b6e
AD
37m4_define([_AT_DATA_CALC_Y],
38[m4_if([$1$2$3], $[1]$[2]$[3], [],
39 [m4_fatal([$0: Invalid arguments: $@])])dnl
bfb07874
AD
40AT_DATA([calc.y],
41[[/* Infix notation calculator--calc */
42
43%{
2ce10144 44#include <config.h>
342b8b6e
AD
45/* We don't need a perfect malloc for these tests. */
46#undef malloc
bfb07874 47#include <stdio.h>
2ce10144
AD
48
49#if STDC_HEADERS
50# include <stdlib.h>
51# include <string.h>
52#else
53char *strcat(char *dest, const char *src);
54#endif
bfb07874 55#include <ctype.h>
bfb07874
AD
56
57static int power (int base, int exponent);
58static void yyerror (const char *s);
59static int yylex (void);
2ce10144
AD
60static int yygetc (void);
61static void yyungetc (int c);
62
bfb07874 63extern void perror (const char *s);
0dd1580a
RA
64
65/* Exercise pre-prologue dependency to %union. */
66typedef int value_t;
67
bfb07874
AD
68%}
69
2b7ed18a
RA
70/* Exercise M4 quoting: '@:>@@:>@', 0. */
71
213e640e
AD
72/* Also exercise %union. */
73%union
74{
0dd1580a 75 value_t ival; /* A comment to exercise an old bug. */
213e640e
AD
76};
77
0dd1580a
RA
78/* Exercise post-prologue dependency to %union. */
79%{
80static void id (YYSTYPE *lval);
2b7ed18a
RA
81
82/* Exercise quotes in declarations. */
83char quote[] = "@:>@@:>@,";
0dd1580a
RA
84%}
85
6b7e85b9 86/* Bison Declarations */
b7c49edf 87%token CALC_EOF 0 "end of file"
213e640e
AD
88%token <ival> NUM "number"
89%type <ival> exp
bfb07874 90
2b7ed18a
RA
91/* Exercise quotes in strings. */
92%token "fake @>:@@>:@,"
93
bfb07874
AD
94%nonassoc '=' /* comparison */
95%left '-' '+'
96%left '*' '/'
97%left NEG /* negation--unary minus */
98%right '^' /* exponentiation */
99
147e184c
MA
100]$4[
101
bfb07874
AD
102/* Grammar follows */
103%%
104input:
b7c49edf 105 line
bfb07874
AD
106| input line
107;
108
109line:
110 '\n'
2b7ed18a
RA
111| exp '\n'
112 {
113 /* Exercise quotes in braces. */
114 char tmp[] = "@>:@@:>@,";
115 }
bfb07874
AD
116;
117
2b7ed18a 118/* Exercise M4 quoting: '@:>@@:>@', 1. */
bfb07874
AD
119exp:
120 NUM { $$ = $1; }
121| exp '=' exp
122 {
123 if ($1 != $3)
51dec47b 124 fprintf (stderr, "calc: error: %d != %d\n", $1, $3);
bfb07874
AD
125 $$ = $1 == $3;
126 }
127| exp '+' exp { $$ = $1 + $3; }
128| exp '-' exp { $$ = $1 - $3; }
129| exp '*' exp { $$ = $1 * $3; }
130| exp '/' exp { $$ = $1 / $3; }
131| '-' exp %prec NEG { $$ = -$2; }
132| exp '^' exp { $$ = power ($1, $3); }
133| '(' exp ')' { $$ = $2; }
51dec47b 134| '(' error ')' { $$ = 0; }
bfb07874
AD
135;
136%%
137/* The input. */
138FILE *yyin;
139
2b7ed18a 140/* Exercise M4 quoting: '@:>@@:>@', 2. */
bfb07874
AD
141static void
142yyerror (const char *s)
143{
19c50364 144#if YYLSP_NEEDED
51dec47b 145 fprintf (stderr, "%d.%d-%d.%d: ",
bfb07874
AD
146 yylloc.first_line, yylloc.first_column,
147 yylloc.last_line, yylloc.last_column);
148#endif
149 fprintf (stderr, "%s\n", s);
150}
151
b7c49edf
AD
152
153#if YYLSP_NEEDED
154static YYLTYPE last_yylloc;
155#endif
bfb07874 156static int
2ce10144 157yygetc (void)
bfb07874
AD
158{
159 int res = getc (yyin);
19c50364 160#if YYLSP_NEEDED
b7c49edf 161 last_yylloc = yylloc;
bfb07874
AD
162 if (res == '\n')
163 {
164 yylloc.last_line++;
51dec47b 165 yylloc.last_column = 1;
bfb07874
AD
166 }
167 else
168 yylloc.last_column++;
169#endif
170 return res;
171}
172
173
174static void
175yyungetc (int c)
176{
19c50364 177#if YYLSP_NEEDED
bfb07874 178 /* Wrong when C == `\n'. */
b7c49edf 179 yylloc = last_yylloc;
bfb07874
AD
180#endif
181 ungetc (c, yyin);
182}
183
184static int
185read_signed_integer (void)
186{
187 int c = yygetc ();
188 int sign = 1;
189 int n = 0;
190
191 if (c == '-')
192 {
193 c = yygetc ();
194 sign = -1;
195 }
196
197 while (isdigit (c))
198 {
199 n = 10 * n + (c - '0');
200 c = yygetc ();
201 }
202
203 yyungetc (c);
204
205 return sign * n;
206}
207
208
209
210/*---------------------------------------------------------------.
211| Lexical analyzer returns an integer on the stack and the token |
212| NUM, or the ASCII character read if not a number. Skips all |
213| blanks and tabs, returns 0 for EOF. |
214`---------------------------------------------------------------*/
215
216static int
217yylex (void)
218{
219 int c;
220
19c50364 221#if YYLSP_NEEDED
bfb07874
AD
222 yylloc.first_column = yylloc.last_column;
223 yylloc.first_line = yylloc.last_line;
224#endif
225
226 /* Skip white space. */
227 while ((c = yygetc ()) == ' ' || c == '\t')
228 {
19c50364 229#if YYLSP_NEEDED
bfb07874
AD
230 yylloc.first_column = yylloc.last_column;
231 yylloc.first_line = yylloc.last_line;
232#endif
233 }
234
235 /* process numbers */
236 if (c == '.' || isdigit (c))
237 {
238 yyungetc (c);
213e640e 239 yylval.ival = read_signed_integer ();
bfb07874
AD
240 return NUM;
241 }
242
243 /* Return end-of-file. */
244 if (c == EOF)
6b7e85b9 245 return CALC_EOF;
bfb07874
AD
246
247 /* Return single chars. */
248 return c;
249}
250
251static int
252power (int base, int exponent)
253{
254 int res = 1;
255 if (exponent < 0)
256 exit (1);
257 for (/* Niente */; exponent; --exponent)
258 res *= base;
259 return res;
260}
261
0dd1580a
RA
262void
263id (YYSTYPE* lval)
264{
265}
266
bfb07874 267int
342b8b6e 268main (int argc, const char **argv)
bfb07874 269{
342b8b6e
AD
270 yyin = NULL;
271
272 if (argc == 2)
bfb07874
AD
273 yyin = fopen (argv[1], "r");
274 else
275 yyin = stdin;
276
342b8b6e 277 if (!yyin)
bfb07874
AD
278 {
279 perror (argv[1]);
280 exit (1);
281 }
282
283#if YYDEBUG
284 yydebug = 1;
285#endif
19c50364 286#if YYLSP_NEEDED
51dec47b 287 yylloc.last_column = 1;
bfb07874
AD
288 yylloc.last_line = 1;
289#endif
290 yyparse ();
291 return 0;
292}
293]])
294])# _AT_DATA_CALC_Y
295
296
297# AT_DATA_CALC_Y([BISON-OPTIONS])
298# -------------------------------
299# Produce `calc.y'.
342b8b6e 300m4_define([AT_DATA_CALC_Y],
bfb07874 301[_AT_DATA_CALC_Y($[1], $[2], $[3],
f987e9d2 302 [m4_bmatch([$1], [--yyerror-verbose],
147e184c 303 [[%error-verbose]])])])
bfb07874
AD
304
305
306
342b8b6e
AD
307# _AT_CHECK_CALC(BISON-OPTIONS, INPUT, [NUM-STDERR-LINES = 0])
308# ------------------------------------------------------------
bfb07874 309# Run `calc' on INPUT and expect no STDOUT nor STDERR.
342b8b6e
AD
310#
311# If BISON-OPTIONS contains `--debug', then NUM-STDERR-LINES is the number
312# of expected lines on stderr.
313m4_define([_AT_CHECK_CALC],
314[AT_DATA([[input]],
315[[$2
316]])
30d2f3d5 317AT_CHECK([./calc input], 0, [], [stderr])dnl
342b8b6e 318AT_CHECK([wc -l <stderr | sed 's/[[^0-9]]//g'], 0,
3c1a79b3
AD
319 [m4_bmatch([$1], [--debug],
320 [$3], [0])
342b8b6e
AD
321])
322])
323
324
325# _AT_CHECK_CALC_ERROR(BISON-OPTIONS, INPUT, [NUM-DEBUG-LINES],
bfb07874
AD
326# [ERROR-LOCATION], [IF-YYERROR-VERBOSE])
327# ------------------------------------------------------------
342b8b6e
AD
328# Run `calc' on INPUT, and expect a `parse error' message.
329#
b7c49edf
AD
330# If INPUT starts with a slash, it is used as absolute input file name,
331# otherwise as contents.
332#
342b8b6e
AD
333# If BISON-OPTIONS contains `--location', then make sure the ERROR-LOCATION
334# is correctly output on stderr.
335#
336# If BISON-OPTIONS contains `--yyerror-verbose', then make sure the
337# IF-YYERROR-VERBOSE message is properly output after `parse error, '
338# on STDERR.
339#
340# If BISON-OPTIONS contains `--debug', then NUM-STDERR-LINES is the number
341# of expected lines on stderr.
342m4_define([_AT_CHECK_CALC_ERROR],
b7c49edf 343[m4_bmatch([$2], [^/],
30d2f3d5 344 [AT_CHECK([./calc $2], 0, [], [stderr])],
b7c49edf 345 [AT_DATA([[input]],
342b8b6e
AD
346[[$2
347]])
30d2f3d5 348AT_CHECK([./calc input], 0, [], [stderr])])
342b8b6e 349
51dec47b
AD
350m4_bmatch([$1], [--debug],
351[AT_CHECK([wc -l <stderr | sed 's/[[^0-9]]//g'], 0, [$3
352])])
342b8b6e 353
51dec47b
AD
354# Normalize the observed and expected error messages, depending upon the
355# options.
356# 1. Remove the traces from observed.
357egrep -v '^((Start|Enter|Read|Reduc|Shift)ing|state|Error:|Next|Discarding) ' stderr >at-stderr
342b8b6e 358mv at-stderr stderr
51dec47b
AD
359# 2. Create the reference error message.
360AT_DATA([[expout]],
361[$4
342b8b6e 362])
51dec47b
AD
363# 3. If locations are not used, remove them.
364m4_bmatch([$1], [--location], [],
365[[sed 's/^[-0-9.]*: //' expout >at-expout
366mv at-expout expout]])
367# 4. If error-verbose is not used, strip the`, unexpected....' part.
368m4_bmatch([$1], [--yyerror-verbose], [],
369[[sed 's/parse error, .*$/parse error/' expout >at-expout
370mv at-expout expout]])
371# 5. Check
372AT_CHECK([cat stderr], 0, [expout])
342b8b6e 373])
bfb07874
AD
374
375
376# AT_CHECK_CALC([BISON-OPTIONS], [PARSER-EXPECTED-STDERR])
377# --------------------------------------------------------
378# Start a testing chunk which compiles `calc' grammar with
379# BISON-OPTIONS, and performs several tests over the parser.
342b8b6e 380m4_define([AT_CHECK_CALC],
bfb07874
AD
381[# We use integers to avoid dependencies upon the precision of doubles.
382AT_SETUP([Calculator $1])
383
384AT_DATA_CALC_Y([$1])
385
386# Specify the output files to avoid problems on different file systems.
3c1a79b3 387AT_CHECK([bison calc.y -o calc.c m4_bpatsubst([$1], [--yyerror-verbose])],
bfb07874 388 [0], [], [])
3c1a79b3 389
d803322e 390AT_CHECK([$CC $CFLAGS $CPPFLAGS calc.c -o calc], 0, [], [ignore])
bfb07874
AD
391
392# Test the priorities.
393_AT_CHECK_CALC([$1],
394[1 + 2 * 3 = 7
3951 + 2 * -3 = -5
396
397-1^2 = -1
398(-1)^2 = 1
399
400---1 = -1
401
4021 - 2 - 3 = -4
4031 - (2 - 3) = 2
404
4052^2^3 = 256
3db472b9 406(2^2)^3 = 64], [486])
bfb07874
AD
407
408# Some parse errors.
b7c49edf 409_AT_CHECK_CALC_ERROR([$1], [0 0], [10],
51dec47b 410 [1.3-1.4: parse error, unexpected "number"])
b7c49edf 411_AT_CHECK_CALC_ERROR([$1], [1//2], [13],
51dec47b 412 [1.3-1.4: parse error, unexpected '/', expecting "number" or '-' or '('])
b7c49edf 413_AT_CHECK_CALC_ERROR([$1], [error], [4],
51dec47b 414 [1.1-1.2: parse error, unexpected $undefined., expecting "number" or '-' or '\n' or '('])
b7c49edf 415_AT_CHECK_CALC_ERROR([$1], [1 = 2 = 3], [19],
51dec47b 416 [1.7-1.8: parse error, unexpected '='])
bfb07874
AD
417_AT_CHECK_CALC_ERROR([$1],
418 [
419+1],
b7c49edf 420 [13],
51dec47b 421 [2.1-2.2: parse error, unexpected '+'])
b7c49edf
AD
422# Exercise error messages with EOF: work on an empty file.
423_AT_CHECK_CALC_ERROR([$1],
424 [/dev/null],
425 [4],
51dec47b
AD
426 [1.1-1.2: parse error, unexpected "end of file", expecting "number" or '-' or '\n' or '('])
427
428# Exercise the error token: without it, we die at the first error,
429# hence be sure i. to have several errors, ii. to test the action
430# associated to `error'.
431_AT_CHECK_CALC_ERROR([$1],
432 [(1 ++ 2) + (0 0) = 1],
433 [76],
434[1.5-1.6: parse error, unexpected '+', expecting "number" or '-' or '('
4351.15-1.16: parse error, unexpected "number"
436calc: error: 0 != 1])
437
438# Add a studid example demonstrating that Bison can further improve the
439# error message. FIXME: Fix this ridiculous message.
440_AT_CHECK_CALC_ERROR([$1],
441 [()],
442 [21],
443[1.2-1.3: parse error, unexpected ')', expecting error or "number" or '-' or '('])
bfb07874 444
d803322e 445AT_CLEANUP
bfb07874
AD
446])# AT_CHECK_CALC
447
448
449
450
451# ------------------ #
452# Test the parsers. #
453# ------------------ #
454
455AT_CHECK_CALC()
bfb07874
AD
456
457AT_CHECK_CALC([--defines])
458AT_CHECK_CALC([--locations])
459AT_CHECK_CALC([--name-prefix=calc])
460AT_CHECK_CALC([--verbose])
461AT_CHECK_CALC([--yacc])
462AT_CHECK_CALC([--yyerror-verbose])
463
464AT_CHECK_CALC([--locations --yyerror-verbose])
465
466AT_CHECK_CALC([--defines --locations --name-prefix=calc --verbose --yacc --yyerror-verbose])
467
468AT_CHECK_CALC([--debug])
469AT_CHECK_CALC([--debug --defines --locations --name-prefix=calc --verbose --yacc --yyerror-verbose])