]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bc/bc/sbc.y
This commit was generated by cvs2svn to compensate for changes in r50397,
[FreeBSD/FreeBSD.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, 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> ASSIGN_OP
48 /*     '=', '+=',  '-=', '*=', '/=', '%=', '^=' */
49 %token <s_value> REL_OP
50 /*     '==', '<=', '>=', '!=', '<', '>'         */
51 %token <c_value> INCR_DECR
52 /*     '++', '--'                               */
53 %token <i_value> Define    Break    Quit    Length
54 /*     'define', 'break', 'quit', 'length'      */
55 %token <i_value> Return    For    If    While    Sqrt  Else
56 /*     'return', 'for', 'if', 'while', 'sqrt',  'else'  */
57 %token <i_value> Scale    Ibase    Obase    Auto  Read
58 /*     'scale', 'ibase', 'obase', 'auto', 'read'        */
59 %token <i_value> Warranty, Halt, Last, Continue, Print, Limits
60 /*     'warranty', 'halt', 'last', 'continue', 'print', 'limits'  */
61
62 /* The types of all other non-terminals. */
63 %type <i_value> expression named_expression return_expression
64 %type <a_value> opt_parameter_list parameter_list opt_auto_define_list
65 %type <a_value> define_list opt_argument_list argument_list
66 %type <i_value> program input_item semicolon_list statement_list
67 %type <i_value> statement_or_error statement function relational_expression 
68
69 /* precedence */
70 %nonassoc REL_OP
71 %right ASSIGN_OP
72 %left '+' '-'
73 %left '*' '/' '%'
74 %right '^'
75 %nonassoc UNARY_MINUS
76 %nonassoc INCR_DECR
77
78 %%
79 program                 : /* empty */
80                             {
81                               $$ = 0;
82                               std_only = TRUE;
83                               if (interactive)
84                                 {
85                                   printf ("s%s\n", BC_VERSION);
86                                   welcome();
87                                 }
88                             }
89                         | program input_item
90                         ;
91 input_item              : semicolon_list NEWLINE
92                             { run_code(); }
93                         | function
94                             { run_code(); }
95                         | error NEWLINE
96                             {
97                               yyerrok; 
98                               init_gen() ;
99                             }
100                         ;
101 semicolon_list          : /* empty */
102                             { $$ = 0; }
103                         | statement_or_error
104                         | semicolon_list ';' statement_or_error
105                         | semicolon_list ';'
106                         ;
107 statement_list          : /* empty */
108                             { $$ = 0; }
109                         | statement
110                         | statement_list NEWLINE
111                         | statement_list NEWLINE statement
112                         | statement_list ';'
113                         | statement_list ';' statement
114                         ;
115 statement_or_error      : statement
116                         | error statement
117                             { $$ = $2; }
118                         ;
119 statement               : Warranty
120                             { warranty("s"); }
121                         | expression
122                             {
123                               if ($1 & 1)
124                                 generate ("W");
125                               else
126                                 generate ("p");
127                             }
128                         | STRING
129                             {
130                               $$ = 0;
131                               generate ("w");
132                               generate ($1);
133                               free ($1);
134                             }
135                         | Break
136                             {
137                               if (break_label == 0)
138                                 yyerror ("Break outside a for/while");
139                               else
140                                 {
141                                   sprintf (genstr, "J%1d:", break_label);
142                                   generate (genstr);
143                                 }
144                             }
145                         | Quit
146                             { exit(0); }
147                         | Return
148                             { generate ("0R"); }
149                         | Return '(' return_expression ')'
150                             { generate ("R"); }
151                         | For 
152                             {
153                               $1 = break_label; 
154                               break_label = next_label++;
155                             }
156                           '(' expression ';'
157                             {
158                               $4 = next_label++;
159                               sprintf (genstr, "pN%1d:", $4);
160                               generate (genstr);
161                             }
162                           relational_expression ';'
163                             {
164                               $7 = next_label++;
165                               sprintf (genstr, "B%1d:J%1d:", $7, break_label);
166                               generate (genstr);
167                               $<i_value>$ = next_label++;
168                               sprintf (genstr, "N%1d:", $<i_value>$);
169                               generate (genstr);
170                             }
171                           expression ')'
172                             {
173                               sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
174                               generate (genstr);
175                             }
176                           statement
177                             {
178                               sprintf (genstr, "J%1d:N%1d:", $<i_value>9,
179                                        break_label);
180                               generate (genstr);
181                               break_label = $1;
182                             }
183                         | If '(' relational_expression ')' 
184                             {
185                               $3 = next_label++;
186                               sprintf (genstr, "Z%1d:", $3);
187                               generate (genstr);
188                             }
189                           statement
190                             {
191                               sprintf (genstr, "N%1d:", $3); 
192                               generate (genstr);
193                             }
194                         | While 
195                             {
196                               $1 = next_label++;
197                               sprintf (genstr, "N%1d:", $1);
198                               generate (genstr);
199                             }
200                         '(' relational_expression 
201                             {
202                               $4 = break_label; 
203                               break_label = next_label++;
204                               sprintf (genstr, "Z%1d:", break_label);
205                               generate (genstr);
206                             }
207                         ')' statement
208                             {
209                               sprintf (genstr, "J%1d:N%1d:", $1, break_label);
210                               generate (genstr);
211                               break_label = $4;
212                             }
213                         | '{' statement_list '}'
214                             { $$ = 0; }
215                         ;
216 function                : Define NAME '(' opt_parameter_list ')' '{'
217                           NEWLINE opt_auto_define_list 
218                             {
219                               check_params ($4,$8);
220                               sprintf (genstr, "F%d,%s.%s[", lookup($2,FUNCT),
221                                        arg_str ($4), arg_str ($8));
222                               generate (genstr);
223                               free_args ($4);
224                               free_args ($8);
225                               $1 = next_label;
226                               next_label = 0;
227                             }
228                           statement_list NEWLINE '}'
229                             {
230                               generate ("0R]");
231                               next_label = $1;
232                             }
233                         ;
234 opt_parameter_list      : /* empty */ 
235                             { $$ = NULL; }
236                         | parameter_list
237                         ;
238 parameter_list          : NAME
239                             { $$ = nextarg (NULL, lookup($1,SIMPLE), FALSE); }
240                         | define_list ',' NAME
241                             { $$ = nextarg ($1, lookup($3,SIMPLE), FALSE); }
242                         ;
243 opt_auto_define_list    : /* empty */ 
244                             { $$ = NULL; }
245                         | Auto define_list NEWLINE
246                             { $$ = $2; } 
247                         | Auto define_list ';'
248                             { $$ = $2; } 
249                         ;
250 define_list             : NAME
251                             { $$ = nextarg (NULL, lookup($1,SIMPLE), FALSE); }
252                         | NAME '[' ']'
253                             { $$ = nextarg (NULL, lookup($1,ARRAY), FALSE); }
254                         | define_list ',' NAME
255                             { $$ = nextarg ($1, lookup($3,SIMPLE), FALSE); }
256                         | define_list ',' NAME '[' ']'
257                             { $$ = nextarg ($1, lookup($3,ARRAY), FALSE); }
258                         ;
259 opt_argument_list       : /* empty */
260                             { $$ = NULL; }
261                         | argument_list
262                         ;
263 argument_list           : expression
264                             { $$ = nextarg (NULL,0, FALSE); }
265                         | argument_list ',' expression
266                             { $$ = nextarg ($1,0, FALSE); }
267                         ;
268 relational_expression   : expression
269                             { $$ = 0; }
270                         | expression REL_OP expression
271                             {
272                               $$ = 0;
273                               switch (*($2))
274                                 {
275                                 case '=':
276                                   generate ("=");
277                                   break;
278                                 case '!':
279                                   generate ("#");
280                                   break;
281                                 case '<':
282                                   if ($2[1] == '=')
283                                     generate ("{");
284                                   else
285                                     generate ("<");
286                                   break;
287                                 case '>':
288                                   if ($2[1] == '=')
289                                     generate ("}");
290                                   else
291                                     generate (">");
292                                   break;
293                                 }
294                             }
295                         ;
296 return_expression       : /* empty */
297                             {
298                               $$ = 0;
299                               generate ("0");
300                             }
301                         | expression
302                         ;
303 expression              : named_expression ASSIGN_OP 
304                             {
305                               if ($2 != '=')
306                                 {
307                                   if ($1 < 0)
308                                     sprintf (genstr, "DL%d:", -$1);
309                                   else
310                                     sprintf (genstr, "l%d:", $1);
311                                   generate (genstr);
312                                 }
313                             }
314                           expression
315                             {
316                               $$ = 0;
317                               if ($2 != '=')
318                                 {
319                                   sprintf (genstr, "%c", $2);
320                                   generate (genstr);
321                                 }
322                               if ($1 < 0)
323                                 sprintf (genstr, "S%d:", -$1);
324                               else
325                                 sprintf (genstr, "s%d:", $1);
326                               generate (genstr);
327                             }
328                         | expression '+' expression
329                             { generate ("+"); }
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           %prec UNARY_MINUS
341                             { generate ("n"); $$ = 1;}
342                         | named_expression
343                             {
344                               $$ = 1;
345                               if ($1 < 0)
346                                 sprintf (genstr, "L%d:", -$1);
347                               else
348                                 sprintf (genstr, "l%d:", $1);
349                               generate (genstr);
350                             }
351                         | NUMBER
352                             {
353                               int len = strlen($1);
354                               $$ = 1;
355                               if (len == 1 && *$1 == '0')
356                                 generate ("0");
357                               else
358                                 {
359                                   if (len == 1 && *$1 == '1')
360                                     generate ("1");
361                                   else
362                                     {
363                                       generate ("K");
364                                       generate ($1);
365                                       generate (":");
366                                     }
367                                   free ($1);
368                                 }
369                             }
370                         | '(' expression ')'
371                             { $$ = 1; }
372                         | NAME '(' opt_argument_list ')'
373                             {
374                               $$ = 1;
375                               if ($3 != NULL)
376                                 { 
377                                   sprintf (genstr, "C%d,%s:", lookup($1,FUNCT),
378                                            arg_str ($3));
379                                   free_args ($3);
380                                 }
381                               else
382                                   sprintf (genstr, "C%d:", lookup($1,FUNCT));
383                               generate (genstr);
384                             }
385                         | INCR_DECR named_expression
386                             {
387                               $$ = 1;
388                               if ($2 < 0)
389                                 {
390                                   if ($1 == '+')
391                                     sprintf (genstr, "DA%d:L%d:", -$2, -$2);
392                                   else
393                                     sprintf (genstr, "DM%d:L%d:", -$2, -$2);
394                                 }
395                               else
396                                 {
397                                   if ($1 == '+')
398                                     sprintf (genstr, "i%d:l%d:", $2, $2);
399                                   else
400                                     sprintf (genstr, "d%d:l%d:", $2, $2);
401                                 }
402                               generate (genstr);
403                             }
404                         | named_expression INCR_DECR
405                             {
406                               $$ = 1;
407                               if ($1 < 0)
408                                 {
409                                   sprintf (genstr, "DL%d:x", -$1);
410                                   generate (genstr); 
411                                   if ($2 == '+')
412                                     sprintf (genstr, "A%d:", -$1);
413                                   else
414                                     sprintf (genstr, "M%d:", -$1);
415                                 }
416                               else
417                                 {
418                                   sprintf (genstr, "l%d:", $1);
419                                   generate (genstr);
420                                   if ($2 == '+')
421                                     sprintf (genstr, "i%d:", $1);
422                                   else
423                                     sprintf (genstr, "d%d:", $1);
424                                 }
425                               generate (genstr);
426                             }
427                         | Length '(' expression ')'
428                             { generate ("cL"); $$ = 1;}
429                         | Sqrt '(' expression ')'
430                             { generate ("cR"); $$ = 1;}
431                         | Scale '(' expression ')'
432                             { generate ("cS"); $$ = 1;}
433                         ;
434 named_expression        : NAME
435                             { $$ = lookup($1,SIMPLE); }
436                         | NAME '[' expression ']'
437                             { $$ = lookup($1,ARRAY); }
438                         | Ibase
439                             { $$ = 0; }
440                         | Obase
441                             { $$ = 1; }
442                         | Scale
443                             { $$ = 2; }
444                         ;
445
446 %%