Typo reported by Al Woodhull.
[minix3.git] / commands / bc / sbc.y
blob81594106361aebfc69c60bc7c1ecadcf40942557
1 , %{
2 /* sbc.y: A POSIX bc processor written for minix with no extensions. */
4 /* This file is part of bc written for MINIX.
5 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License , or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21 You may contact the author by:
22 e-mail: phil@cs.wwu.edu
23 us-mail: Philip A. Nelson
24 Computer Science Department, 9062
25 Western Washington University
26 Bellingham, WA 98226-9062
28 *************************************************************************/
30 #include "bcdefs.h"
31 #include "global.h" /* To get the global variables. */
32 #include "proto.h"
35 %start program
37 %union {
38 char *s_value;
39 char c_value;
40 int i_value;
41 arg_list *a_value;
44 %token <i_value> NEWLINE AND OR NOT
45 %token <s_value> STRING NAME NUMBER
46 /* '-', '+' are tokens themselves */
47 %token <c_value> MUL_OP
48 /* '*', '/', '%' */
49 %token <c_value> ASSIGN_OP
50 /* '=', '+=', '-=', '*=', '/=', '%=', '^=' */
51 %token <s_value> REL_OP
52 /* '==', '<=', '>=', '!=', '<', '>' */
53 %token <c_value> INCR_DECR
54 /* '++', '--' */
55 %token <i_value> Define Break Quit Length
56 /* 'define', 'break', 'quit', 'length' */
57 %token <i_value> Return For If While Sqrt Else
58 /* 'return', 'for', 'if', 'while', 'sqrt', 'else' */
59 %token <i_value> Scale Ibase Obase Auto Read
60 /* 'scale', 'ibase', 'obase', 'auto', 'read' */
61 %token <i_value> Warranty, Halt, Last, Continue, Print, Limits
62 /* 'warranty', 'halt', 'last', 'continue', 'print', 'limits' */
64 /* The types of all other non-terminals. */
65 %type <i_value> expression named_expression return_expression
66 %type <a_value> opt_parameter_list parameter_list opt_auto_define_list
67 %type <a_value> define_list opt_argument_list argument_list
68 %type <i_value> program input_item semicolon_list statement_list
69 %type <i_value> statement_or_error statement function relational_expression
71 /* precedence */
72 %nonassoc REL_OP
73 %right ASSIGN_OP
74 %left '+' '-'
75 %left MUL_OP
76 %right '^'
77 %nonassoc UNARY_MINUS
78 %nonassoc INCR_DECR
81 program : /* empty */
83 $$ = 0;
84 std_only = TRUE;
85 if (interactive)
87 printf ("s%s\n", BC_VERSION);
88 welcome();
91 | program input_item
93 input_item : semicolon_list NEWLINE
94 { run_code(); }
95 | function
96 { run_code(); }
97 | error NEWLINE
99 yyerrok;
100 init_gen() ;
103 semicolon_list : /* empty */
104 { $$ = 0; }
105 | statement_or_error
106 | semicolon_list ';' statement_or_error
107 | semicolon_list ';'
109 statement_list : /* empty */
110 { $$ = 0; }
111 | statement
112 | statement_list NEWLINE
113 | statement_list NEWLINE statement
114 | statement_list ';'
115 | statement_list ';' statement
117 statement_or_error : statement
118 | error statement
119 { $$ = $2; }
121 statement : Warranty
122 { warranty("s"); }
123 | expression
125 if ($1 & 1)
126 generate ("W");
127 else
128 generate ("p");
130 | STRING
132 $$ = 0;
133 generate ("w");
134 generate ($1);
135 free ($1);
137 | Break
139 if (break_label == 0)
140 yyerror ("Break outside a for/while");
141 else
143 sprintf (genstr, "J%1d:", break_label);
144 generate (genstr);
147 | Quit
148 { exit(0); }
149 | Return
150 { generate ("0R"); }
151 | Return '(' return_expression ')'
152 { generate ("R"); }
153 | For
155 $1 = break_label;
156 break_label = next_label++;
158 '(' expression ';'
160 $4 = next_label++;
161 sprintf (genstr, "pN%1d:", $4);
162 generate (genstr);
164 relational_expression ';'
166 $7 = next_label++;
167 sprintf (genstr, "B%1d:J%1d:", $7, break_label);
168 generate (genstr);
169 $<i_value>$ = next_label++;
170 sprintf (genstr, "N%1d:", $<i_value>$);
171 generate (genstr);
173 expression ')'
175 sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
176 generate (genstr);
178 statement
180 sprintf (genstr, "J%1d:N%1d:", $<i_value>9,
181 break_label);
182 generate (genstr);
183 break_label = $1;
185 | If '(' relational_expression ')'
187 $3 = next_label++;
188 sprintf (genstr, "Z%1d:", $3);
189 generate (genstr);
191 statement
193 sprintf (genstr, "N%1d:", $3);
194 generate (genstr);
196 | While
198 $1 = next_label++;
199 sprintf (genstr, "N%1d:", $1);
200 generate (genstr);
202 '(' relational_expression
204 $4 = break_label;
205 break_label = next_label++;
206 sprintf (genstr, "Z%1d:", break_label);
207 generate (genstr);
209 ')' statement
211 sprintf (genstr, "J%1d:N%1d:", $1, break_label);
212 generate (genstr);
213 break_label = $4;
215 | '{' statement_list '}'
216 { $$ = 0; }
218 function : Define NAME '(' opt_parameter_list ')' '{'
219 NEWLINE opt_auto_define_list
221 check_params ($4,$8);
222 sprintf (genstr, "F%d,%s.%s[", lookup($2,FUNCT),
223 arg_str ($4,TRUE), arg_str ($8,TRUE));
224 generate (genstr);
225 free_args ($4);
226 free_args ($8);
227 $1 = next_label;
228 next_label = 0;
230 statement_list NEWLINE '}'
232 generate ("0R]");
233 next_label = $1;
236 opt_parameter_list : /* empty */
237 { $$ = NULL; }
238 | parameter_list
240 parameter_list : NAME
241 { $$ = nextarg (NULL, lookup($1,SIMPLE)); }
242 | define_list ',' NAME
243 { $$ = nextarg ($1, lookup($3,SIMPLE)); }
245 opt_auto_define_list : /* empty */
246 { $$ = NULL; }
247 | Auto define_list NEWLINE
248 { $$ = $2; }
249 | Auto define_list ';'
250 { $$ = $2; }
252 define_list : NAME
253 { $$ = nextarg (NULL, lookup($1,SIMPLE)); }
254 | NAME '[' ']'
255 { $$ = nextarg (NULL, lookup($1,ARRAY)); }
256 | define_list ',' NAME
257 { $$ = nextarg ($1, lookup($3,SIMPLE)); }
258 | define_list ',' NAME '[' ']'
259 { $$ = nextarg ($1, lookup($3,ARRAY)); }
261 opt_argument_list : /* empty */
262 { $$ = NULL; }
263 | argument_list
265 argument_list : expression
266 { $$ = nextarg (NULL,0); }
267 | argument_list ',' expression
268 { $$ = nextarg ($1,0); }
270 relational_expression : expression
271 { $$ = 0; }
272 | expression REL_OP expression
274 $$ = 0;
275 switch (*($2))
277 case '=':
278 generate ("=");
279 break;
280 case '!':
281 generate ("#");
282 break;
283 case '<':
284 if ($2[1] == '=')
285 generate ("{");
286 else
287 generate ("<");
288 break;
289 case '>':
290 if ($2[1] == '=')
291 generate ("}");
292 else
293 generate (">");
294 break;
298 return_expression : /* empty */
300 $$ = 0;
301 generate ("0");
303 | expression
305 expression : named_expression ASSIGN_OP
307 if ($2 != '=')
309 if ($1 < 0)
310 sprintf (genstr, "DL%d:", -$1);
311 else
312 sprintf (genstr, "l%d:", $1);
313 generate (genstr);
316 expression
318 $$ = 0;
319 if ($2 != '=')
321 sprintf (genstr, "%c", $2);
322 generate (genstr);
324 if ($1 < 0)
325 sprintf (genstr, "S%d:", -$1);
326 else
327 sprintf (genstr, "s%d:", $1);
328 generate (genstr);
330 | expression '+' expression
331 { generate ("+"); }
332 | expression '-' expression
333 { generate ("-"); }
334 | expression MUL_OP expression
336 genstr[0] = $2;
337 genstr[1] = 0;
338 generate (genstr);
340 | expression '^' expression
341 { generate ("^"); }
342 | '-' expression %prec UNARY_MINUS
343 { generate ("n"); $$ = 1;}
344 | named_expression
346 $$ = 1;
347 if ($1 < 0)
348 sprintf (genstr, "L%d:", -$1);
349 else
350 sprintf (genstr, "l%d:", $1);
351 generate (genstr);
353 | NUMBER
355 int len = strlen($1);
356 $$ = 1;
357 if (len == 1 && *$1 == '0')
358 generate ("0");
359 else
361 if (len == 1 && *$1 == '1')
362 generate ("1");
363 else
365 generate ("K");
366 generate ($1);
367 generate (":");
369 free ($1);
372 | '(' expression ')'
373 { $$ = 1; }
374 | NAME '(' opt_argument_list ')'
376 $$ = 1;
377 if ($3 != NULL)
379 sprintf (genstr, "C%d,%s:", lookup($1,FUNCT),
380 arg_str ($3,FALSE));
381 free_args ($3);
383 else
384 sprintf (genstr, "C%d:", lookup($1,FUNCT));
385 generate (genstr);
387 | INCR_DECR named_expression
389 $$ = 1;
390 if ($2 < 0)
392 if ($1 == '+')
393 sprintf (genstr, "DA%d:L%d:", -$2, -$2);
394 else
395 sprintf (genstr, "DM%d:L%d:", -$2, -$2);
397 else
399 if ($1 == '+')
400 sprintf (genstr, "i%d:l%d:", $2, $2);
401 else
402 sprintf (genstr, "d%d:l%d:", $2, $2);
404 generate (genstr);
406 | named_expression INCR_DECR
408 $$ = 1;
409 if ($1 < 0)
411 sprintf (genstr, "DL%d:x", -$1);
412 generate (genstr);
413 if ($2 == '+')
414 sprintf (genstr, "A%d:", -$1);
415 else
416 sprintf (genstr, "M%d:", -$1);
418 else
420 sprintf (genstr, "l%d:", $1);
421 generate (genstr);
422 if ($2 == '+')
423 sprintf (genstr, "i%d:", $1);
424 else
425 sprintf (genstr, "d%d:", $1);
427 generate (genstr);
429 | Length '(' expression ')'
430 { generate ("cL"); $$ = 1;}
431 | Sqrt '(' expression ')'
432 { generate ("cR"); $$ = 1;}
433 | Scale '(' expression ')'
434 { generate ("cS"); $$ = 1;}
436 named_expression : NAME
437 { $$ = lookup($1,SIMPLE); }
438 | NAME '[' expression ']'
439 { $$ = lookup($1,ARRAY); }
440 | Ibase
441 { $$ = 0; }
442 | Obase
443 { $$ = 1; }
444 | Scale
445 { $$ = 2; }