Typo's.
[minix3.git] / commands / bc / bc.y
blobe67e1017449601911e216e12b22ade1a43a92ac4
1 %{
2 /* bc.y: The grammar for a POSIX compatable bc processor with some
3 extensions to the language. */
5 /* This file is part of bc written for MINIX.
6 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License , or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 You may contact the author by:
23 e-mail: phil@cs.wwu.edu
24 us-mail: Philip A. Nelson
25 Computer Science Department, 9062
26 Western Washington University
27 Bellingham, WA 98226-9062
29 *************************************************************************/
31 #include "bcdefs.h"
32 #include "global.h"
33 #include "proto.h"
36 %start program
38 %union {
39 char *s_value;
40 char c_value;
41 int i_value;
42 arg_list *a_value;
45 /* Extensions over POSIX bc.
46 a) NAME was LETTER. This grammer allows longer names.
47 Single letter names will still work.
48 b) Relational_expression allowed only one comparison.
49 This grammar has added boolean expressions with
50 && (and) || (or) and ! (not) and allowed all of them in
51 full expressions.
52 c) Added an else to the if.
53 d) Call by variable array parameters
54 e) read() procedure that reads a number under program control from stdin.
55 f) halt statement that halts the the program under program control. It
56 is an executed statement.
57 g) continue statement for for loops.
58 h) optional expressions in the for loop.
59 i) print statement to print multiple numbers per line.
60 j) warranty statement to print an extended warranty notice.
61 j) limits statement to print the processor's limits.
64 %token <i_value> NEWLINE AND OR NOT
65 %token <s_value> STRING NAME NUMBER
66 /* '-', '+' are tokens themselves */
67 %token <c_value> MUL_OP
68 /* '*', '/', '%' */
69 %token <c_value> ASSIGN_OP
70 /* '=', '+=', '-=', '*=', '/=', '%=', '^=' */
71 %token <s_value> REL_OP
72 /* '==', '<=', '>=', '!=', '<', '>' */
73 %token <c_value> INCR_DECR
74 /* '++', '--' */
75 %token <i_value> Define Break Quit Length
76 /* 'define', 'break', 'quit', 'length' */
77 %token <i_value> Return For If While Sqrt Else
78 /* 'return', 'for', 'if', 'while', 'sqrt', 'else' */
79 %token <i_value> Scale Ibase Obase Auto Read
80 /* 'scale', 'ibase', 'obase', 'auto', 'read' */
81 %token <i_value> Warranty, Halt, Last, Continue, Print, Limits
82 /* 'warranty', 'halt', 'last', 'continue', 'print', 'limits' */
84 /* Types of all other things. */
85 %type <i_value> expression return_expression named_expression opt_expression
86 %type <c_value> '+' '-'
87 %type <a_value> opt_parameter_list opt_auto_define_list define_list
88 %type <a_value> opt_argument_list argument_list
89 %type <i_value> program input_item semicolon_list statement_list
90 %type <i_value> statement function statement_or_error
92 /* precedence */
93 %left OR
94 %left AND
95 %nonassoc NOT
96 %left REL_OP
97 %right ASSIGN_OP
98 %left '+' '-'
99 %left MUL_OP
100 %right '^'
101 %nonassoc UNARY_MINUS
102 %nonassoc INCR_DECR
105 program : /* empty */
107 $$ = 0;
108 if (interactive)
110 printf ("%s\n", BC_VERSION);
111 welcome ();
114 | program input_item
116 input_item : semicolon_list NEWLINE
117 { run_code (); }
118 | function
119 { run_code (); }
120 | error NEWLINE
122 yyerrok;
123 init_gen ();
126 semicolon_list : /* empty */
127 { $$ = 0; }
128 | statement_or_error
129 | semicolon_list ';' statement_or_error
130 | semicolon_list ';'
132 statement_list : /* empty */
133 { $$ = 0; }
134 | statement_or_error
135 | statement_list NEWLINE
136 | statement_list NEWLINE statement_or_error
137 | statement_list ';'
138 | statement_list ';' statement
140 statement_or_error : statement
141 | error statement
142 { $$ = $2; }
144 statement : Warranty
145 { warranty (""); }
146 | Limits
147 { limits (); }
148 | expression
150 if ($1 & 2)
151 warn ("comparison in expression");
152 if ($1 & 1)
153 generate ("W");
154 else
155 generate ("p");
157 | STRING
159 $$ = 0;
160 generate ("w");
161 generate ($1);
162 free ($1);
164 | Break
166 if (break_label == 0)
167 yyerror ("Break outside a for/while");
168 else
170 sprintf (genstr, "J%1d:", break_label);
171 generate (genstr);
174 | Continue
176 warn ("Continue statement");
177 if (continue_label == 0)
178 yyerror ("Continue outside a for");
179 else
181 sprintf (genstr, "J%1d:", continue_label);
182 generate (genstr);
185 | Quit
186 { exit (0); }
187 | Halt
188 { generate ("h"); }
189 | Return
190 { generate ("0R"); }
191 | Return '(' return_expression ')'
192 { generate ("R"); }
193 | For
195 $1 = break_label;
196 break_label = next_label++;
198 '(' opt_expression ';'
200 if ($4 > 1)
201 warn ("Comparison in first for expression");
202 $4 = next_label++;
203 if ($4 < 0)
204 sprintf (genstr, "N%1d:", $4);
205 else
206 sprintf (genstr, "pN%1d:", $4);
207 generate (genstr);
209 opt_expression ';'
211 if ($7 < 0) generate ("1");
212 $7 = next_label++;
213 sprintf (genstr, "B%1d:J%1d:", $7, break_label);
214 generate (genstr);
215 $<i_value>$ = continue_label;
216 continue_label = next_label++;
217 sprintf (genstr, "N%1d:", continue_label);
218 generate (genstr);
220 opt_expression ')'
222 if ($10 > 1)
223 warn ("Comparison in third for expression");
224 if ($10 < 0)
225 sprintf (genstr, "J%1d:N%1d:", $4, $7);
226 else
227 sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
228 generate (genstr);
230 statement
232 sprintf (genstr, "J%1d:N%1d:",
233 continue_label, break_label);
234 generate (genstr);
235 break_label = $1;
236 continue_label = $<i_value>9;
238 | If '(' expression ')'
240 $3 = if_label;
241 if_label = next_label++;
242 sprintf (genstr, "Z%1d:", if_label);
243 generate (genstr);
245 statement opt_else
247 sprintf (genstr, "N%1d:", if_label);
248 generate (genstr);
249 if_label = $3;
251 | While
253 $1 = next_label++;
254 sprintf (genstr, "N%1d:", $1);
255 generate (genstr);
257 '(' expression
259 $4 = break_label;
260 break_label = next_label++;
261 sprintf (genstr, "Z%1d:", break_label);
262 generate (genstr);
264 ')' statement
266 sprintf (genstr, "J%1d:N%1d:", $1, break_label);
267 generate (genstr);
268 break_label = $4;
270 | '{' statement_list '}'
271 { $$ = 0; }
272 | Print
273 { warn ("print statement"); }
274 print_list
276 print_list : print_element
277 | print_element ',' print_list
279 print_element : STRING
281 generate ("O");
282 generate ($1);
283 free ($1);
285 | expression
286 { generate ("P"); }
288 opt_else : /* nothing */
289 | Else
291 warn ("else clause in if statement");
292 $1 = next_label++;
293 sprintf (genstr, "J%d:N%1d:", $1, if_label);
294 generate (genstr);
295 if_label = $1;
297 statement
298 function : Define NAME '(' opt_parameter_list ')' '{'
299 NEWLINE opt_auto_define_list
301 /* Check auto list against parameter list? */
302 check_params ($4,$8);
303 sprintf (genstr, "F%d,%s.%s[", lookup($2,FUNCT),
304 arg_str ($4,TRUE), arg_str ($8,TRUE));
305 generate (genstr);
306 free_args ($4);
307 free_args ($8);
308 $1 = next_label;
309 next_label = 0;
311 statement_list NEWLINE '}'
313 generate ("0R]");
314 next_label = $1;
317 opt_parameter_list : /* empty */
318 { $$ = NULL; }
319 | define_list
321 opt_auto_define_list : /* empty */
322 { $$ = NULL; }
323 | Auto define_list NEWLINE
324 { $$ = $2; }
325 | Auto define_list ';'
326 { $$ = $2; }
328 define_list : NAME
329 { $$ = nextarg (NULL, lookup ($1,SIMPLE)); }
330 | NAME '[' ']'
331 { $$ = nextarg (NULL, lookup ($1,ARRAY)); }
332 | define_list ',' NAME
333 { $$ = nextarg ($1, lookup ($3,SIMPLE)); }
334 | define_list ',' NAME '[' ']'
335 { $$ = nextarg ($1, lookup ($3,ARRAY)); }
337 opt_argument_list : /* empty */
338 { $$ = NULL; }
339 | argument_list
341 argument_list : expression
343 if ($1 > 1) warn ("comparison in argument");
344 $$ = nextarg (NULL,0);
346 | NAME '[' ']'
348 sprintf (genstr, "K%d:", -lookup ($1,ARRAY));
349 generate (genstr);
350 $$ = nextarg (NULL,1);
352 | argument_list ',' expression
354 if ($3 > 1) warn ("comparison in argument");
355 $$ = nextarg ($1,0);
357 | argument_list ',' NAME '[' ']'
359 sprintf (genstr, "K%d:", -lookup ($3,ARRAY));
360 generate (genstr);
361 $$ = nextarg ($1,1);
364 opt_expression : /* empty */
366 $$ = -1;
367 warn ("Missing expression in for statement");
369 | expression
371 return_expression : /* empty */
373 $$ = 0;
374 generate ("0");
376 | expression
378 if ($1 > 1)
379 warn ("comparison in return expresion");
382 expression : named_expression ASSIGN_OP
384 if ($2 != '=')
386 if ($1 < 0)
387 sprintf (genstr, "DL%d:", -$1);
388 else
389 sprintf (genstr, "l%d:", $1);
390 generate (genstr);
393 expression
395 if ($4 > 1) warn("comparison in assignment");
396 if ($2 != '=')
398 sprintf (genstr, "%c", $2);
399 generate (genstr);
401 if ($1 < 0)
402 sprintf (genstr, "S%d:", -$1);
403 else
404 sprintf (genstr, "s%d:", $1);
405 generate (genstr);
406 $$ = 0;
409 | expression AND
411 warn("&& operator");
412 $2 = next_label++;
413 sprintf (genstr, "DZ%d:p", $2);
414 generate (genstr);
416 expression
418 sprintf (genstr, "DZ%d:p1N%d:", $2, $2);
419 generate (genstr);
420 $$ = $1 | $4;
422 | expression OR
424 warn("|| operator");
425 $2 = next_label++;
426 sprintf (genstr, "B%d:", $2);
427 generate (genstr);
429 expression
431 int tmplab;
432 tmplab = next_label++;
433 sprintf (genstr, "B%d:0J%d:N%d:1N%d:",
434 $2, tmplab, $2, tmplab);
435 generate (genstr);
436 $$ = $1 | $4;
438 | NOT expression
440 $$ = $2;
441 warn("! operator");
442 generate ("!");
444 | expression REL_OP expression
446 $$ = 3;
447 switch (*($2))
449 case '=':
450 generate ("=");
451 break;
453 case '!':
454 generate ("#");
455 break;
457 case '<':
458 if ($2[1] == '=')
459 generate ("{");
460 else
461 generate ("<");
462 break;
464 case '>':
465 if ($2[1] == '=')
466 generate ("}");
467 else
468 generate (">");
469 break;
472 | expression '+' expression
474 generate ("+");
475 $$ = $1 | $3;
477 | expression '-' expression
479 generate ("-");
480 $$ = $1 | $3;
482 | expression MUL_OP expression
484 genstr[0] = $2;
485 genstr[1] = 0;
486 generate (genstr);
487 $$ = $1 | $3;
489 | expression '^' expression
491 generate ("^");
492 $$ = $1 | $3;
494 | '-' expression %prec UNARY_MINUS
496 generate ("n");
497 $$ = $2;
499 | named_expression
501 $$ = 1;
502 if ($1 < 0)
503 sprintf (genstr, "L%d:", -$1);
504 else
505 sprintf (genstr, "l%d:", $1);
506 generate (genstr);
508 | NUMBER
510 int len = strlen($1);
511 $$ = 1;
512 if (len == 1 && *$1 == '0')
513 generate ("0");
514 else if (len == 1 && *$1 == '1')
515 generate ("1");
516 else
518 generate ("K");
519 generate ($1);
520 generate (":");
522 free ($1);
524 | '(' expression ')'
525 { $$ = $2 | 1; }
526 | NAME '(' opt_argument_list ')'
528 $$ = 1;
529 if ($3 != NULL)
531 sprintf (genstr, "C%d,%s:",
532 lookup ($1,FUNCT),
533 arg_str ($3,FALSE));
534 free_args ($3);
536 else
538 sprintf (genstr, "C%d:", lookup ($1,FUNCT));
540 generate (genstr);
542 | INCR_DECR named_expression
544 $$ = 1;
545 if ($2 < 0)
547 if ($1 == '+')
548 sprintf (genstr, "DA%d:L%d:", -$2, -$2);
549 else
550 sprintf (genstr, "DM%d:L%d:", -$2, -$2);
552 else
554 if ($1 == '+')
555 sprintf (genstr, "i%d:l%d:", $2, $2);
556 else
557 sprintf (genstr, "d%d:l%d:", $2, $2);
559 generate (genstr);
561 | named_expression INCR_DECR
563 $$ = 1;
564 if ($1 < 0)
566 sprintf (genstr, "DL%d:x", -$1);
567 generate (genstr);
568 if ($2 == '+')
569 sprintf (genstr, "A%d:", -$1);
570 else
571 sprintf (genstr, "M%d:", -$1);
573 else
575 sprintf (genstr, "l%d:", $1);
576 generate (genstr);
577 if ($2 == '+')
578 sprintf (genstr, "i%d:", $1);
579 else
580 sprintf (genstr, "d%d:", $1);
582 generate (genstr);
584 | Length '(' expression ')'
585 { generate ("cL"); $$ = 1;}
586 | Sqrt '(' expression ')'
587 { generate ("cR"); $$ = 1;}
588 | Scale '(' expression ')'
589 { generate ("cS"); $$ = 1;}
590 | Read '(' ')'
592 warn ("read function");
593 generate ("cI"); $$ = 1;
596 named_expression : NAME
597 { $$ = lookup($1,SIMPLE); }
598 | NAME '[' expression ']'
600 if ($3 > 1) warn("comparison in subscript");
601 $$ = lookup($1,ARRAY);
603 | Ibase
604 { $$ = 0; }
605 | Obase
606 { $$ = 1; }
607 | Scale
608 { $$ = 2; }
609 | Last
610 { $$ = 3; }