source: trunk/minix/commands/bc/sbc.y@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 10.6 KB
Line 
1, %{
2/* sbc.y: A POSIX bc processor written for minix with no extensions. */
3
4/* This file is part of bc written for MINIX.
5 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
6
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.
11
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.
16
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.
20
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
27
28*************************************************************************/
29
30#include "bcdefs.h"
31#include "global.h" /* To get the global variables. */
32#include "proto.h"
33%}
34
35%start program
36
37%union {
38 char *s_value;
39 char c_value;
40 int i_value;
41 arg_list *a_value;
42 }
43
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' */
63
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
70
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
79
80%%
81program : /* empty */
82 {
83 $$ = 0;
84 std_only = TRUE;
85 if (interactive)
86 {
87 printf ("s%s\n", BC_VERSION);
88 welcome();
89 }
90 }
91 | program input_item
92 ;
93input_item : semicolon_list NEWLINE
94 { run_code(); }
95 | function
96 { run_code(); }
97 | error NEWLINE
98 {
99 yyerrok;
100 init_gen() ;
101 }
102 ;
103semicolon_list : /* empty */
104 { $$ = 0; }
105 | statement_or_error
106 | semicolon_list ';' statement_or_error
107 | semicolon_list ';'
108 ;
109statement_list : /* empty */
110 { $$ = 0; }
111 | statement
112 | statement_list NEWLINE
113 | statement_list NEWLINE statement
114 | statement_list ';'
115 | statement_list ';' statement
116 ;
117statement_or_error : statement
118 | error statement
119 { $$ = $2; }
120 ;
121statement : Warranty
122 { warranty("s"); }
123 | expression
124 {
125 if ($1 & 1)
126 generate ("W");
127 else
128 generate ("p");
129 }
130 | STRING
131 {
132 $$ = 0;
133 generate ("w");
134 generate ($1);
135 free ($1);
136 }
137 | Break
138 {
139 if (break_label == 0)
140 yyerror ("Break outside a for/while");
141 else
142 {
143 sprintf (genstr, "J%1d:", break_label);
144 generate (genstr);
145 }
146 }
147 | Quit
148 { exit(0); }
149 | Return
150 { generate ("0R"); }
151 | Return '(' return_expression ')'
152 { generate ("R"); }
153 | For
154 {
155 $1 = break_label;
156 break_label = next_label++;
157 }
158 '(' expression ';'
159 {
160 $4 = next_label++;
161 sprintf (genstr, "pN%1d:", $4);
162 generate (genstr);
163 }
164 relational_expression ';'
165 {
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);
172 }
173 expression ')'
174 {
175 sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
176 generate (genstr);
177 }
178 statement
179 {
180 sprintf (genstr, "J%1d:N%1d:", $<i_value>9,
181 break_label);
182 generate (genstr);
183 break_label = $1;
184 }
185 | If '(' relational_expression ')'
186 {
187 $3 = next_label++;
188 sprintf (genstr, "Z%1d:", $3);
189 generate (genstr);
190 }
191 statement
192 {
193 sprintf (genstr, "N%1d:", $3);
194 generate (genstr);
195 }
196 | While
197 {
198 $1 = next_label++;
199 sprintf (genstr, "N%1d:", $1);
200 generate (genstr);
201 }
202 '(' relational_expression
203 {
204 $4 = break_label;
205 break_label = next_label++;
206 sprintf (genstr, "Z%1d:", break_label);
207 generate (genstr);
208 }
209 ')' statement
210 {
211 sprintf (genstr, "J%1d:N%1d:", $1, break_label);
212 generate (genstr);
213 break_label = $4;
214 }
215 | '{' statement_list '}'
216 { $$ = 0; }
217 ;
218function : Define NAME '(' opt_parameter_list ')' '{'
219 NEWLINE opt_auto_define_list
220 {
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;
229 }
230 statement_list NEWLINE '}'
231 {
232 generate ("0R]");
233 next_label = $1;
234 }
235 ;
236opt_parameter_list : /* empty */
237 { $$ = NULL; }
238 | parameter_list
239 ;
240parameter_list : NAME
241 { $$ = nextarg (NULL, lookup($1,SIMPLE)); }
242 | define_list ',' NAME
243 { $$ = nextarg ($1, lookup($3,SIMPLE)); }
244 ;
245opt_auto_define_list : /* empty */
246 { $$ = NULL; }
247 | Auto define_list NEWLINE
248 { $$ = $2; }
249 | Auto define_list ';'
250 { $$ = $2; }
251 ;
252define_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)); }
260 ;
261opt_argument_list : /* empty */
262 { $$ = NULL; }
263 | argument_list
264 ;
265argument_list : expression
266 { $$ = nextarg (NULL,0); }
267 | argument_list ',' expression
268 { $$ = nextarg ($1,0); }
269 ;
270relational_expression : expression
271 { $$ = 0; }
272 | expression REL_OP expression
273 {
274 $$ = 0;
275 switch (*($2))
276 {
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;
295 }
296 }
297 ;
298return_expression : /* empty */
299 {
300 $$ = 0;
301 generate ("0");
302 }
303 | expression
304 ;
305expression : named_expression ASSIGN_OP
306 {
307 if ($2 != '=')
308 {
309 if ($1 < 0)
310 sprintf (genstr, "DL%d:", -$1);
311 else
312 sprintf (genstr, "l%d:", $1);
313 generate (genstr);
314 }
315 }
316 expression
317 {
318 $$ = 0;
319 if ($2 != '=')
320 {
321 sprintf (genstr, "%c", $2);
322 generate (genstr);
323 }
324 if ($1 < 0)
325 sprintf (genstr, "S%d:", -$1);
326 else
327 sprintf (genstr, "s%d:", $1);
328 generate (genstr);
329 }
330 | expression '+' expression
331 { generate ("+"); }
332 | expression '-' expression
333 { generate ("-"); }
334 | expression MUL_OP expression
335 {
336 genstr[0] = $2;
337 genstr[1] = 0;
338 generate (genstr);
339 }
340 | expression '^' expression
341 { generate ("^"); }
342 | '-' expression %prec UNARY_MINUS
343 { generate ("n"); $$ = 1;}
344 | named_expression
345 {
346 $$ = 1;
347 if ($1 < 0)
348 sprintf (genstr, "L%d:", -$1);
349 else
350 sprintf (genstr, "l%d:", $1);
351 generate (genstr);
352 }
353 | NUMBER
354 {
355 int len = strlen($1);
356 $$ = 1;
357 if (len == 1 && *$1 == '0')
358 generate ("0");
359 else
360 {
361 if (len == 1 && *$1 == '1')
362 generate ("1");
363 else
364 {
365 generate ("K");
366 generate ($1);
367 generate (":");
368 }
369 free ($1);
370 }
371 }
372 | '(' expression ')'
373 { $$ = 1; }
374 | NAME '(' opt_argument_list ')'
375 {
376 $$ = 1;
377 if ($3 != NULL)
378 {
379 sprintf (genstr, "C%d,%s:", lookup($1,FUNCT),
380 arg_str ($3,FALSE));
381 free_args ($3);
382 }
383 else
384 sprintf (genstr, "C%d:", lookup($1,FUNCT));
385 generate (genstr);
386 }
387 | INCR_DECR named_expression
388 {
389 $$ = 1;
390 if ($2 < 0)
391 {
392 if ($1 == '+')
393 sprintf (genstr, "DA%d:L%d:", -$2, -$2);
394 else
395 sprintf (genstr, "DM%d:L%d:", -$2, -$2);
396 }
397 else
398 {
399 if ($1 == '+')
400 sprintf (genstr, "i%d:l%d:", $2, $2);
401 else
402 sprintf (genstr, "d%d:l%d:", $2, $2);
403 }
404 generate (genstr);
405 }
406 | named_expression INCR_DECR
407 {
408 $$ = 1;
409 if ($1 < 0)
410 {
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);
417 }
418 else
419 {
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);
426 }
427 generate (genstr);
428 }
429 | Length '(' expression ')'
430 { generate ("cL"); $$ = 1;}
431 | Sqrt '(' expression ')'
432 { generate ("cR"); $$ = 1;}
433 | Scale '(' expression ')'
434 { generate ("cS"); $$ = 1;}
435 ;
436named_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; }
446 ;
447
448%%
Note: See TracBrowser for help on using the repository browser.