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 *************************************************************************/
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
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
69 %token
<c_value
> ASSIGN_OP
70 /* '=', '+=', '-=', '*=', '/=', '%=', '^=' */
71 %token
<s_value
> REL_OP
72 /* '==', '<=', '>=', '!=', '<', '>' */
73 %token
<c_value
> INCR_DECR
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
101 %nonassoc UNARY_MINUS
105 program
: /* empty */
110 printf
("%s\n", BC_VERSION
);
116 input_item
: semicolon_list NEWLINE
126 semicolon_list
: /* empty */
129 | semicolon_list
';' statement_or_error
132 statement_list
: /* empty */
135 | statement_list NEWLINE
136 | statement_list NEWLINE statement_or_error
138 | statement_list
';' statement
140 statement_or_error
: statement
151 warn
("comparison in expression");
166 if
(break_label
== 0)
167 yyerror ("Break outside a for/while");
170 sprintf
(genstr
, "J%1d:", break_label
);
176 warn
("Continue statement");
177 if
(continue_label
== 0)
178 yyerror ("Continue outside a for");
181 sprintf
(genstr
, "J%1d:", continue_label
);
191 | Return
'(' return_expression
')'
196 break_label
= next_label
++;
198 '(' opt_expression
';'
201 warn
("Comparison in first for expression");
204 sprintf
(genstr
, "N%1d:", $4);
206 sprintf
(genstr
, "pN%1d:", $4);
211 if
($7 < 0) generate
("1");
213 sprintf
(genstr
, "B%1d:J%1d:", $7, break_label
);
215 $
<i_value
>$
= continue_label
;
216 continue_label
= next_label
++;
217 sprintf
(genstr
, "N%1d:", continue_label
);
223 warn
("Comparison in third for expression");
225 sprintf
(genstr
, "J%1d:N%1d:", $4, $7);
227 sprintf
(genstr
, "pJ%1d:N%1d:", $4, $7);
232 sprintf
(genstr
, "J%1d:N%1d:",
233 continue_label
, break_label
);
236 continue_label
= $
<i_value
>9;
238 | If
'(' expression
')'
241 if_label
= next_label
++;
242 sprintf
(genstr
, "Z%1d:", if_label
);
247 sprintf
(genstr
, "N%1d:", if_label
);
254 sprintf
(genstr
, "N%1d:", $1);
260 break_label
= next_label
++;
261 sprintf
(genstr
, "Z%1d:", break_label
);
266 sprintf
(genstr
, "J%1d:N%1d:", $1, break_label
);
270 |
'{' statement_list
'}'
273 { warn
("print statement"); }
276 print_list
: print_element
277 | print_element
',' print_list
279 print_element
: STRING
288 opt_else
: /* nothing */
291 warn
("else clause in if statement");
293 sprintf
(genstr
, "J%d:N%1d:", $1, if_label
);
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
));
311 statement_list NEWLINE
'}'
317 opt_parameter_list
: /* empty */
321 opt_auto_define_list
: /* empty */
323 | Auto define_list NEWLINE
325 | Auto define_list
';'
329 { $$
= nextarg
(NULL
, lookup
($1,SIMPLE
)); }
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 */
341 argument_list
: expression
343 if
($1 > 1) warn
("comparison in argument");
344 $$
= nextarg
(NULL
,0);
348 sprintf
(genstr
, "K%d:", -lookup
($1,ARRAY
));
350 $$
= nextarg
(NULL
,1);
352 | argument_list
',' expression
354 if
($3 > 1) warn
("comparison in argument");
357 | argument_list
',' NAME
'[' ']'
359 sprintf
(genstr
, "K%d:", -lookup
($3,ARRAY
));
364 opt_expression
: /* empty */
367 warn
("Missing expression in for statement");
371 return_expression
: /* empty */
379 warn
("comparison in return expresion");
382 expression
: named_expression ASSIGN_OP
387 sprintf
(genstr
, "DL%d:", -$1);
389 sprintf
(genstr
, "l%d:", $1);
395 if
($4 > 1) warn
("comparison in assignment");
398 sprintf
(genstr
, "%c", $2);
402 sprintf
(genstr
, "S%d:", -$1);
404 sprintf
(genstr
, "s%d:", $1);
413 sprintf
(genstr
, "DZ%d:p", $2);
418 sprintf
(genstr
, "DZ%d:p1N%d:", $2, $2);
426 sprintf
(genstr
, "B%d:", $2);
432 tmplab
= next_label
++;
433 sprintf
(genstr
, "B%d:0J%d:N%d:1N%d:",
434 $2, tmplab
, $2, tmplab
);
444 | expression REL_OP expression
472 | expression
'+' expression
477 | expression
'-' expression
482 | expression MUL_OP expression
489 | expression
'^' expression
494 |
'-' expression %prec UNARY_MINUS
503 sprintf
(genstr
, "L%d:", -$1);
505 sprintf
(genstr
, "l%d:", $1);
510 int len
= strlen
($1);
512 if
(len
== 1 && *$1 == '0')
514 else if
(len
== 1 && *$1 == '1')
526 | NAME
'(' opt_argument_list
')'
531 sprintf
(genstr
, "C%d,%s:",
538 sprintf
(genstr
, "C%d:", lookup
($1,FUNCT
));
542 | INCR_DECR named_expression
548 sprintf
(genstr
, "DA%d:L%d:", -$2, -$2);
550 sprintf
(genstr
, "DM%d:L%d:", -$2, -$2);
555 sprintf
(genstr
, "i%d:l%d:", $2, $2);
557 sprintf
(genstr
, "d%d:l%d:", $2, $2);
561 | named_expression INCR_DECR
566 sprintf
(genstr
, "DL%d:x", -$1);
569 sprintf
(genstr
, "A%d:", -$1);
571 sprintf
(genstr
, "M%d:", -$1);
575 sprintf
(genstr
, "l%d:", $1);
578 sprintf
(genstr
, "i%d:", $1);
580 sprintf
(genstr
, "d%d:", $1);
584 | Length
'(' expression
')'
585 { generate
("cL"); $$
= 1;}
586 | Sqrt
'(' expression
')'
587 { generate
("cR"); $$
= 1;}
588 | Scale
'(' expression
')'
589 { generate
("cS"); $$
= 1;}
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
);