Merge from vendor branch LIBSTDC++:
[dragonfly.git] / contrib / bc / bc / sbc.y
1 %{
2 /* sbc.y: A POSIX bc processor written for minix with no extensions.  */
3  
4 /*  This file is part of GNU bc.
5     Copyright (C) 1991, 1992, 1993, 1994, 1997 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, Inc.
20       59 Temple Place, Suite 330
21       Boston, MA 02111 USA
22
23     You may contact the author by:
24        e-mail:  philnelson@acm.org
25       us-mail:  Philip A. Nelson
26                 Computer Science Department, 9062
27                 Western Washington University
28                 Bellingham, WA 98226-9062
29        
30 *************************************************************************/
31
32 #include "bcdefs.h"
33 #include "global.h"     /* To get the global variables. */
34 #include "proto.h"
35 %}
36
37 %start program
38
39 %union {
40         char *s_value;
41         char  c_value;
42         int   i_value;
43         arg_list *a_value;
44        }
45
46 %token <i_value> ENDOFLINE AND OR NOT
47 %token <s_value> STRING NAME NUMBER
48 /*     '-', '+' are tokens themselves           */
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 '*' '/' '%'
76 %right '^'
77 %nonassoc UNARY_MINUS
78 %nonassoc INCR_DECR
79
80 %%
81 program                 : /* 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                         ;
93 input_item              : semicolon_list ENDOFLINE
94                             { run_code(); }
95                         | function
96                             { run_code(); }
97                         | error ENDOFLINE
98                             {
99                               yyerrok; 
100                               init_gen() ;
101                             }
102                         ;
103 semicolon_list          : /* empty */
104                             { $$ = 0; }
105                         | statement_or_error
106                         | semicolon_list ';' statement_or_error
107                         | semicolon_list ';'
108                         ;
109 statement_list          : /* empty */
110                             { $$ = 0; }
111                         | statement
112                         | statement_list ENDOFLINE
113                         | statement_list ENDOFLINE statement
114                         | statement_list ';'
115                         | statement_list ';' statement
116                         ;
117 statement_or_error      : statement
118                         | error statement
119                             { $$ = $2; }
120                         ;
121 statement               : 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                         ;
218 function                : Define NAME '(' opt_parameter_list ')' '{'
219                           ENDOFLINE opt_auto_define_list 
220                             {
221                               check_params ($4,$8);
222                               sprintf (genstr, "F%d,%s.%s[", lookup($2,FUNCT),
223                                        arg_str ($4), arg_str ($8));
224                               generate (genstr);
225                               free_args ($4);
226                               free_args ($8);
227                               $1 = next_label;
228                               next_label = 0;
229                             }
230                           statement_list ENDOFLINE '}'
231                             {
232                               generate ("0R]");
233                               next_label = $1;
234                             }
235                         ;
236 opt_parameter_list      : /* empty */ 
237                             { $$ = NULL; }
238                         | parameter_list
239                         ;
240 parameter_list          : NAME
241                             { $$ = nextarg (NULL, lookup($1,SIMPLE), FALSE); }
242                         | define_list ',' NAME
243                             { $$ = nextarg ($1, lookup($3,SIMPLE), FALSE); }
244                         ;
245 opt_auto_define_list    : /* empty */ 
246                             { $$ = NULL; }
247                         | Auto define_list ENDOFLINE
248                             { $$ = $2; } 
249                         | Auto define_list ';'
250                             { $$ = $2; } 
251                         ;
252 define_list             : NAME
253                             { $$ = nextarg (NULL, lookup($1,SIMPLE), FALSE); }
254                         | NAME '[' ']'
255                             { $$ = nextarg (NULL, lookup($1,ARRAY), FALSE); }
256                         | define_list ',' NAME
257                             { $$ = nextarg ($1, lookup($3,SIMPLE), FALSE); }
258                         | define_list ',' NAME '[' ']'
259                             { $$ = nextarg ($1, lookup($3,ARRAY), FALSE); }
260                         ;
261 opt_argument_list       : /* empty */
262                             { $$ = NULL; }
263                         | argument_list
264                         ;
265 argument_list           : expression
266                             { $$ = nextarg (NULL,0, FALSE); }
267                         | argument_list ',' expression
268                             { $$ = nextarg ($1,0, FALSE); }
269                         ;
270 relational_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                         ;
298 return_expression       : /* empty */
299                             {
300                               $$ = 0;
301                               generate ("0");
302                             }
303                         | expression
304                         ;
305 expression              : 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 '*' expression
335                             { generate ("*"); }
336                         | expression '/' expression
337                             { generate ("/"); }
338                         | expression '%' expression
339                             { generate ("%"); }
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));
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                         ;
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; }
446                         ;
447
448 %%