~ubuntu-branches/ubuntu/natty/bc/natty

« back to all changes in this revision

Viewing changes to bc/bc.y

  • Committer: Bazaar Package Importer
  • Author(s): John Hasler
  • Date: 2007-12-02 14:46:56 UTC
  • mto: (3.2.1 sid)
  • mto: This revision was merged to the branch mainline in revision 10.
  • Revision ID: james.westby@ubuntu.com-20071202144656-vz98qh9dd1zwdyny
Tags: upstream-1.06.94
ImportĀ upstreamĀ versionĀ 1.06.94

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
%{
2
 
/* bc.y: The grammar for a POSIX compatable bc processor with some
3
 
         extensions to the language. */
4
 
 
5
1
/*  This file is part of GNU bc.
6
 
    Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
 
2
 
 
3
    Copyright (C) 1991-1994, 1997, 2006 Free Software Foundation, Inc.
7
4
 
8
5
    This program is free software; you can redistribute it and/or modify
9
6
    it under the terms of the GNU General Public License as published by
18
15
    You should have received a copy of the GNU General Public License
19
16
    along with this program; see the file COPYING.  If not, write to:
20
17
      The Free Software Foundation, Inc.
21
 
      59 Temple Place, Suite 330
22
 
      Boston, MA 02111 USA
 
18
      Foundation, Inc.  51 Franklin Street, Fifth Floor,
 
19
      Boston, MA 02110-1301  USA
23
20
 
24
21
    You may contact the author by:
25
22
       e-mail:  philnelson@acm.org
30
27
       
31
28
*************************************************************************/
32
29
 
 
30
/* bc.y: The grammar for a POSIX compatable bc processor with some
 
31
         extensions to the language. */
 
32
 
 
33
%{
 
34
 
33
35
#include "bcdefs.h"
34
36
#include "global.h"
35
37
#include "proto.h"
 
38
 
 
39
/* current function number. */
 
40
int cur_func = -1;
 
41
 
 
42
/* Expression encoded information -- See comment at expression rules. */
 
43
#define EX_ASSGN 0 
 
44
#define EX_REG   1
 
45
#define EX_COMP  2
 
46
#define EX_PAREN 4
 
47
#define EX_VOID  8 
 
48
#define EX_EMPTY 16
 
49
 
36
50
%}
37
51
 
38
52
%start program
76
90
%token <i_value> Define    Break    Quit    Length
77
91
/*     'return', 'for', 'if', 'while', 'sqrt', 'else'   */
78
92
%token <i_value> Return    For    If    While    Sqrt   Else
79
 
/*     'scale', 'ibase', 'obase', 'auto', 'read'        */
80
 
%token <i_value> Scale    Ibase    Obase    Auto  Read
 
93
/*     'scale', 'ibase', 'obase', 'auto', 'read', 'random'      */
 
94
%token <i_value> Scale Ibase Obase Auto    Read    Random
81
95
/*     'warranty', 'halt', 'last', 'continue', 'print', 'limits'   */
82
 
%token <i_value> Warranty, Halt, Last, Continue, Print, Limits
83
 
/*     'history' */
84
 
%token <i_value> UNARY_MINUS HistoryVar
 
96
%token <i_value> Warranty  Halt  Last  Continue  Print  Limits
 
97
/*     'history', 'void' */
 
98
%token <i_value> UNARY_MINUS HistoryVar Void
 
99
 
85
100
 
86
101
/* Types of all other things. */
87
102
%type <i_value> expression return_expression named_expression opt_expression
90
105
%type <a_value> opt_argument_list argument_list
91
106
%type <i_value> program input_item semicolon_list statement_list
92
107
%type <i_value> statement function statement_or_error required_eol
 
108
%type <i_value> opt_void
93
109
 
94
110
/* precedence */
95
111
%left OR
153
169
                            { limits (); }
154
170
                        | expression
155
171
                            {
156
 
                              if ($1 & 2)
 
172
                              if ($1 & EX_COMP)
157
173
                                warn ("comparison in expression");
158
 
                              if ($1 & 1)
 
174
                              if ($1 & EX_REG)
159
175
                                generate ("W");
160
176
                              else 
161
177
                                generate ("p");
201
217
                            }
202
218
                          '(' opt_expression ';'
203
219
                            {
204
 
                              if ($4 & 2)
 
220
                              if ($4 & EX_COMP)
205
221
                                warn ("Comparison in first for expression");
206
 
                              if ($4 >= 0)
 
222
                              if ($4 & EX_VOID)
 
223
                                yyerror ("first expression is void");
 
224
                              if (!($4 & EX_EMPTY))
207
225
                                generate ("p");
208
226
                              $4 = next_label++;
209
227
                              sprintf (genstr, "N%1d:", $4);
211
229
                            }
212
230
                          opt_expression ';'
213
231
                            {
214
 
                              if ($7 < 0) generate ("1");
 
232
                              if ($7 & EX_VOID)
 
233
                                yyerror ("second expression is void");
 
234
                              if ($7 & EX_EMPTY ) generate ("1");
215
235
                              $7 = next_label++;
216
236
                              sprintf (genstr, "B%1d:J%1d:", $7, break_label);
217
237
                              generate (genstr);
222
242
                            }
223
243
                          opt_expression ')'
224
244
                            {
225
 
                              if ($10 & 2 )
 
245
                              if ($10 & EX_COMP)
226
246
                                warn ("Comparison in third for expression");
227
 
                              if ($10 & 16)
 
247
                              if ($10 & EX_VOID)
 
248
                                yyerror ("third expression is void");
 
249
                              if ($10 & EX_EMPTY)
228
250
                                sprintf (genstr, "J%1d:N%1d:", $4, $7);
229
251
                              else
230
252
                                sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
240
262
                            }
241
263
                        | If '(' expression ')' 
242
264
                            {
 
265
                              if ($3 & EX_VOID)
 
266
                                yyerror ("void expression");
243
267
                              $3 = if_label;
244
268
                              if_label = next_label++;
245
269
                              sprintf (genstr, "Z%1d:", if_label);
259
283
                            }
260
284
                        '(' expression 
261
285
                            {
 
286
                              if ($4 & EX_VOID)
 
287
                                yyerror ("void expression");
262
288
                              $4 = break_label; 
263
289
                              break_label = next_label++;
264
290
                              sprintf (genstr, "Z%1d:", break_label);
286
312
                              free ($1);
287
313
                            }
288
314
                        | expression
289
 
                            { generate ("P"); }
 
315
                            {
 
316
                              if ($1 & EX_VOID)
 
317
                                yyerror ("void expression in print");
 
318
                              generate ("P");
 
319
                            }
290
320
                        ;
291
321
opt_else                : /* nothing */
292
322
                        | Else 
298
328
                              if_label = $1;
299
329
                            }
300
330
                          opt_newline statement
301
 
function                : Define NAME '(' opt_parameter_list ')' opt_newline
 
331
                        ;
 
332
function                : Define opt_void NAME '(' opt_parameter_list ')' opt_newline
302
333
                          '{' required_eol opt_auto_define_list 
303
 
                            {
 
334
                            { char *params, *autos;
304
335
                              /* Check auto list against parameter list? */
305
 
                              check_params ($4,$9);
306
 
                              sprintf (genstr, "F%d,%s.%s[",
307
 
                                       lookup($2,FUNCTDEF), 
308
 
                                       arg_str ($4), arg_str ($9));
 
336
                              check_params ($5,$10);
 
337
                              params = arg_str ($5);
 
338
                              autos  = arg_str ($10);
 
339
                              set_genstr_size (30 + strlen (params)
 
340
                                               + strlen (autos));
 
341
                              cur_func = lookup($3,FUNCTDEF);
 
342
                              sprintf (genstr, "F%d,%s.%s[", cur_func, params,
 
343
                                       autos); 
309
344
                              generate (genstr);
310
 
                              free_args ($4);
311
 
                              free_args ($9);
 
345
                              functions[cur_func].f_void = $2;
 
346
                              free_args ($5);
 
347
                              free_args ($10);
312
348
                              $1 = next_label;
313
349
                              next_label = 1;
314
350
                            }
316
352
                            {
317
353
                              generate ("0R]");
318
354
                              next_label = $1;
 
355
                              cur_func = -1;
 
356
                            }
 
357
                        ;
 
358
opt_void                : /* empty */
 
359
                            { $$ = 0; }
 
360
                        | Void
 
361
                            {
 
362
                              $$ = 1;
 
363
                              warn ("void functions");
319
364
                            }
320
365
                        ;
321
366
opt_parameter_list      : /* empty */ 
334
379
                        | NAME '[' ']'
335
380
                            { $$ = nextarg (NULL, lookup ($1,ARRAY), FALSE); }
336
381
                        | '*' NAME '[' ']'
337
 
                            { $$ = nextarg (NULL, lookup ($2,ARRAY), TRUE); }
 
382
                            { $$ = nextarg (NULL, lookup ($2,ARRAY), TRUE);
 
383
                              warn ("Call by variable arrays");
 
384
                            }
 
385
                        | '&' NAME '[' ']'
 
386
                            { $$ = nextarg (NULL, lookup ($2,ARRAY), TRUE);
 
387
                              warn ("Call by variable arrays");
 
388
                            }
338
389
                        | define_list ',' NAME
339
390
                            { $$ = nextarg ($1, lookup ($3,SIMPLE), FALSE); }
340
391
                        | define_list ',' NAME '[' ']'
341
392
                            { $$ = nextarg ($1, lookup ($3,ARRAY), FALSE); }
342
393
                        | define_list ',' '*' NAME '[' ']'
343
 
                            { $$ = nextarg ($1, lookup ($4,ARRAY), TRUE); }
 
394
                            { $$ = nextarg ($1, lookup ($4,ARRAY), TRUE);
 
395
                              warn ("Call by variable arrays");
 
396
                            }
 
397
                        | define_list ',' '&' NAME '[' ']'
 
398
                            { $$ = nextarg ($1, lookup ($4,ARRAY), TRUE);
 
399
                              warn ("Call by variable arrays");
 
400
                            }
344
401
                        ;
345
402
opt_argument_list       : /* empty */
346
403
                            { $$ = NULL; }
348
405
                        ;
349
406
argument_list           : expression
350
407
                            {
351
 
                              if ($1 & 2) warn ("comparison in argument");
 
408
                              if ($1 & EX_COMP)
 
409
                                warn ("comparison in argument");
 
410
                              if ($1 & EX_VOID)
 
411
                                yyerror ("void argument");
352
412
                              $$ = nextarg (NULL,0,FALSE);
353
413
                            }
354
414
                        | NAME '[' ']'
359
419
                            }
360
420
                        | argument_list ',' expression
361
421
                            {
362
 
                              if ($3 & 2) warn ("comparison in argument");
 
422
                              if ($3 & EX_COMP)
 
423
                                warn ("comparison in argument");
 
424
                              if ($3 & EX_VOID)
 
425
                                yyerror ("void argument");
363
426
                              $$ = nextarg ($1,0,FALSE);
364
427
                            }
365
428
                        | argument_list ',' NAME '[' ']'
370
433
                            }
371
434
                        ;
372
435
 
373
 
/* Expression lval meanings!  (Bits mean something!)
 
436
/* Expression lval meanings!  (Bits mean something!)  (See defines above)
374
437
 *  0 => Top op is assignment.
375
438
 *  1 => Top op is not assignment.
376
439
 *  2 => Comparison is somewhere in expression.
377
440
 *  4 => Expression is in parenthesis.
 
441
 *  8 => Expression is void!
378
442
 * 16 => Empty optional expression.
379
443
 */
380
444
 
381
445
opt_expression          : /* empty */
382
446
                            {
383
 
                              $$ = 16;
 
447
                              $$ = EX_EMPTY;
384
448
                              warn ("Missing expression in for statement");
385
449
                            }
386
450
                        | expression
389
453
                            {
390
454
                              $$ = 0;
391
455
                              generate ("0");
 
456
                              if (cur_func == -1)
 
457
                                yyerror("Return outside of a function.");
392
458
                            }
393
459
                        | expression
394
460
                            {
395
 
                              if ($1 & 2)
 
461
                              if ($1 & EX_COMP)
396
462
                                warn ("comparison in return expresion");
397
 
                              if (!($1 & 4))
 
463
                              if (!($1 & EX_PAREN))
398
464
                                warn ("return expression requires parenthesis");
 
465
                              if ($1 & EX_VOID)
 
466
                                yyerror("return requires non-void expression");
 
467
                              if (cur_func == -1)
 
468
                                yyerror("Return outside of a function.");
 
469
                              else if (functions[cur_func].f_void)
 
470
                                yyerror("Return expression in a void function.");
399
471
                            }
400
472
                        ;
401
473
expression              :  named_expression ASSIGN_OP 
411
483
                            }
412
484
                          expression
413
485
                            {
414
 
                              if ($4 & 2) warn("comparison in assignment");
 
486
                              if ($4 & EX_ASSGN)
 
487
                                warn("comparison in assignment");
 
488
                              if ($4 & EX_VOID)
 
489
                                yyerror("Assignment of a void expression");
415
490
                              if ($2 != '=')
416
491
                                {
417
492
                                  sprintf (genstr, "%c", $2);
422
497
                              else
423
498
                                sprintf (genstr, "s%d:", $1);
424
499
                              generate (genstr);
425
 
                              $$ = 0;
 
500
                              $$ = EX_ASSGN;
426
501
                            }
427
 
                        ;
428
502
                        | expression AND 
429
503
                            {
430
504
                              warn("&& operator");
434
508
                            }
435
509
                          expression
436
510
                            {
 
511
                              if (($1 & EX_VOID) || ($4 & EX_VOID))
 
512
                                yyerror ("void expression with &&");
437
513
                              sprintf (genstr, "DZ%d:p1N%d:", $2, $2);
438
514
                              generate (genstr);
439
 
                              $$ = ($1 | $4) & ~4;
 
515
                              $$ = ($1 | $4) & ~EX_PAREN;
440
516
                            }
441
517
                        | expression OR
442
518
                            {
448
524
                          expression
449
525
                            {
450
526
                              int tmplab;
 
527
                              if (($1 & EX_VOID) || ($4 & EX_VOID))
 
528
                                yyerror ("void expression with ||");
451
529
                              tmplab = next_label++;
452
530
                              sprintf (genstr, "B%d:0J%d:N%d:1N%d:",
453
531
                                       $2, tmplab, $2, tmplab);
454
532
                              generate (genstr);
455
 
                              $$ = ($1 | $4) & ~4;
 
533
                              $$ = ($1 | $4) & ~EX_PAREN;
456
534
                            }
457
535
                        | NOT expression
458
536
                            {
459
 
                              $$ = $2 & ~4;
 
537
                              if ($2 & EX_VOID)
 
538
                                yyerror ("void expression with !");
 
539
                              $$ = $2 & ~EX_PAREN;
460
540
                              warn("! operator");
461
541
                              generate ("!");
462
542
                            }
463
543
                        | expression REL_OP expression
464
544
                            {
465
 
                              $$ = 3;
 
545
                              if (($1 & EX_VOID) || ($3 & EX_VOID))
 
546
                                yyerror ("void expression with comparison");
 
547
                              $$ = EX_REG | EX_COMP;
466
548
                              switch (*($2))
467
549
                                {
468
550
                                case '=':
490
572
                            }
491
573
                        | expression '+' expression
492
574
                            {
 
575
                              if (($1 & EX_VOID) || ($3 & EX_VOID))
 
576
                                yyerror ("void expression with +");
493
577
                              generate ("+");
494
 
                              $$ = ($1 | $3) & ~4;
 
578
                              $$ = ($1 | $3) & ~EX_PAREN;
495
579
                            }
496
580
                        | expression '-' expression
497
581
                            {
 
582
                              if (($1 & EX_VOID) || ($3 & EX_VOID))
 
583
                                yyerror ("void expression with -");
498
584
                              generate ("-");
499
 
                              $$ = ($1 | $3) & ~4;
 
585
                              $$ = ($1 | $3) & ~EX_PAREN;
500
586
                            }
501
587
                        | expression '*' expression
502
588
                            {
 
589
                              if (($1 & EX_VOID) || ($3 & EX_VOID))
 
590
                                yyerror ("void expression with *");
503
591
                              generate ("*");
504
 
                              $$ = ($1 | $3) & ~4;
 
592
                              $$ = ($1 | $3) & ~EX_PAREN;
505
593
                            }
506
594
                        | expression '/' expression
507
595
                            {
 
596
                              if (($1 & EX_VOID) || ($3 & EX_VOID))
 
597
                                yyerror ("void expression with /");
508
598
                              generate ("/");
509
 
                              $$ = ($1 | $3) & ~4;
 
599
                              $$ = ($1 | $3) & ~EX_PAREN;
510
600
                            }
511
601
                        | expression '%' expression
512
602
                            {
 
603
                              if (($1 & EX_VOID) || ($3 & EX_VOID))
 
604
                                yyerror ("void expression with %");
513
605
                              generate ("%");
514
 
                              $$ = ($1 | $3) & ~4;
 
606
                              $$ = ($1 | $3) & ~EX_PAREN;
515
607
                            }
516
608
                        | expression '^' expression
517
609
                            {
 
610
                              if (($1 & EX_VOID) || ($3 & EX_VOID))
 
611
                                yyerror ("void expression with ^");
518
612
                              generate ("^");
519
 
                              $$ = ($1 | $3) & ~4;
 
613
                              $$ = ($1 | $3) & ~EX_PAREN;
520
614
                            }
521
615
                        | '-' expression  %prec UNARY_MINUS
522
616
                            {
 
617
                              if ($2 & EX_VOID)
 
618
                                yyerror ("void expression with unary -");
523
619
                              generate ("n");
524
 
                              $$ = $2 & ~4;
 
620
                              $$ = $2 & ~EX_PAREN;
525
621
                            }
526
622
                        | named_expression
527
623
                            {
528
 
                              $$ = 1;
 
624
                              $$ = EX_REG;
529
625
                              if ($1 < 0)
530
626
                                sprintf (genstr, "L%d:", -$1);
531
627
                              else
535
631
                        | NUMBER
536
632
                            {
537
633
                              int len = strlen($1);
538
 
                              $$ = 1;
 
634
                              $$ = EX_REG;
539
635
                              if (len == 1 && *$1 == '0')
540
636
                                generate ("0");
541
637
                              else if (len == 1 && *$1 == '1')
549
645
                              free ($1);
550
646
                            }
551
647
                        | '(' expression ')'
552
 
                            { $$ = $2 | 5; }
 
648
                            { 
 
649
                              if ($2 & EX_VOID)
 
650
                                yyerror ("void expression in parenthesis");
 
651
                              $$ = $2 | EX_REG | EX_PAREN;
 
652
                            }
553
653
                        | NAME '(' opt_argument_list ')'
554
 
                            {
555
 
                              $$ = 1;
 
654
                            { int fn;
 
655
                              fn = lookup ($1,FUNCT);
 
656
                              if (functions[fn].f_void)
 
657
                                $$ = EX_VOID;
 
658
                              else
 
659
                                $$ = EX_REG;
556
660
                              if ($3 != NULL)
557
 
                                { 
558
 
                                  sprintf (genstr, "C%d,%s:",
559
 
                                           lookup ($1,FUNCT),
560
 
                                           call_str ($3));
 
661
                                { char *params = call_str ($3);
 
662
                                  set_genstr_size (20 + strlen (params));
 
663
                                  sprintf (genstr, "C%d,%s:", fn, params);
561
664
                                  free_args ($3);
562
665
                                }
563
666
                              else
564
667
                                {
565
 
                                  sprintf (genstr, "C%d:", lookup ($1,FUNCT));
 
668
                                  sprintf (genstr, "C%d:", fn);
566
669
                                }
567
670
                              generate (genstr);
568
671
                            }
569
672
                        | INCR_DECR named_expression
570
673
                            {
571
 
                              $$ = 1;
 
674
                              $$ = EX_REG;
572
675
                              if ($2 < 0)
573
676
                                {
574
677
                                  if ($1 == '+')
587
690
                            }
588
691
                        | named_expression INCR_DECR
589
692
                            {
590
 
                              $$ = 1;
 
693
                              $$ = EX_REG;
591
694
                              if ($1 < 0)
592
695
                                {
593
696
                                  sprintf (genstr, "DL%d:x", -$1);
609
712
                              generate (genstr);
610
713
                            }
611
714
                        | Length '(' expression ')'
612
 
                            { generate ("cL"); $$ = 1;}
 
715
                            {
 
716
                              if ($3 & EX_VOID)
 
717
                                yyerror ("void expression in length()");
 
718
                              generate ("cL");
 
719
                              $$ = EX_REG;
 
720
                            }
613
721
                        | Sqrt '(' expression ')'
614
 
                            { generate ("cR"); $$ = 1;}
 
722
                            {
 
723
                              if ($3 & EX_VOID)
 
724
                                yyerror ("void expression in sqrt()");
 
725
                              generate ("cR");
 
726
                              $$ = EX_REG;
 
727
                            }
615
728
                        | Scale '(' expression ')'
616
 
                            { generate ("cS"); $$ = 1;}
 
729
                            {
 
730
                              if ($3 & EX_VOID)
 
731
                                yyerror ("void expression in scale()");
 
732
                              generate ("cS");
 
733
                              $$ = EX_REG;
 
734
                            }
617
735
                        | Read '(' ')'
618
736
                            {
619
737
                              warn ("read function");
620
 
                              generate ("cI"); $$ = 1;
 
738
                              generate ("cI");
 
739
                              $$ = EX_REG;
 
740
                            }
 
741
                        | Random '(' ')'
 
742
                            {
 
743
                              warn ("random function");
 
744
                              generate ("cX");
 
745
                              $$ = EX_REG;
621
746
                            }
622
747
                        ;
623
748
named_expression        : NAME
624
749
                            { $$ = lookup($1,SIMPLE); }
625
750
                        | NAME '[' expression ']'
626
751
                            {
627
 
                              if ($3 > 1) warn("comparison in subscript");
 
752
                              if ($3 & EX_VOID)
 
753
                                yyerror("void expression as subscript");
 
754
                              if ($3 & EX_COMP)
 
755
                                warn("comparison in subscript");
628
756
                              $$ = lookup($1,ARRAY);
629
757
                            }
630
758
                        | Ibase