2
/* bc.y: The grammar for a POSIX compatable bc processor with some
3
extensions to the language. */
5
1
/* This file is part of GNU bc.
6
Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
3
Copyright (C) 1991-1994, 1997, 2006 Free Software Foundation, Inc.
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
18
Foundation, Inc. 51 Franklin Street, Fifth Floor,
19
Boston, MA 02110-1301 USA
24
21
You may contact the author by:
25
22
e-mail: philnelson@acm.org
31
28
*************************************************************************/
30
/* bc.y: The grammar for a POSIX compatable bc processor with some
31
extensions to the language. */
33
35
#include "bcdefs.h"
34
36
#include "global.h"
39
/* current function number. */
42
/* Expression encoded information -- See comment at expression rules. */
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
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
86
101
/* Types of all other things. */
87
102
%type <i_value> expression return_expression named_expression opt_expression
212
230
opt_expression ';'
214
if ($7 < 0) generate ("1");
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);
223
243
opt_expression ')'
226
246
warn ("Comparison in third for expression");
248
yyerror ("third expression is void");
228
250
sprintf (genstr, "J%1d:N%1d:", $4, $7);
230
252
sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
300
330
opt_newline statement
301
function : Define NAME '(' opt_parameter_list ')' opt_newline
332
function : Define opt_void NAME '(' opt_parameter_list ')' opt_newline
302
333
'{' required_eol opt_auto_define_list
334
{ char *params, *autos;
304
335
/* Check auto list against parameter list? */
305
check_params ($4,$9);
306
sprintf (genstr, "F%d,%s.%s[",
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)
341
cur_func = lookup($3,FUNCTDEF);
342
sprintf (genstr, "F%d,%s.%s[", cur_func, params,
309
344
generate (genstr);
345
functions[cur_func].f_void = $2;
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");
386
{ $$ = nextarg (NULL, lookup ($2,ARRAY), TRUE);
387
warn ("Call by variable arrays");
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");
397
| define_list ',' '&' NAME '[' ']'
398
{ $$ = nextarg ($1, lookup ($4,ARRAY), TRUE);
399
warn ("Call by variable arrays");
345
402
opt_argument_list : /* empty */
349
406
argument_list : expression
351
if ($1 & 2) warn ("comparison in argument");
409
warn ("comparison in argument");
411
yyerror ("void argument");
352
412
$$ = nextarg (NULL,0,FALSE);
360
420
| argument_list ',' expression
362
if ($3 & 2) warn ("comparison in argument");
423
warn ("comparison in argument");
425
yyerror ("void argument");
363
426
$$ = nextarg ($1,0,FALSE);
365
428
| argument_list ',' NAME '[' ']'
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.
381
445
opt_expression : /* empty */
384
448
warn ("Missing expression in for statement");
457
yyerror("Return outside of a function.");
396
462
warn ("comparison in return expresion");
463
if (!($1 & EX_PAREN))
398
464
warn ("return expression requires parenthesis");
466
yyerror("return requires non-void expression");
468
yyerror("Return outside of a function.");
469
else if (functions[cur_func].f_void)
470
yyerror("Return expression in a void function.");
401
473
expression : named_expression ASSIGN_OP
414
if ($4 & 2) warn("comparison in assignment");
487
warn("comparison in assignment");
489
yyerror("Assignment of a void expression");
417
492
sprintf (genstr, "%c", $2);
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);
515
$$ = ($1 | $4) & ~EX_PAREN;
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);
533
$$ = ($1 | $4) & ~EX_PAREN;
538
yyerror ("void expression with !");
460
540
warn("! operator");
463
543
| expression REL_OP expression
545
if (($1 & EX_VOID) || ($3 & EX_VOID))
546
yyerror ("void expression with comparison");
547
$$ = EX_REG | EX_COMP;
491
573
| expression '+' expression
575
if (($1 & EX_VOID) || ($3 & EX_VOID))
576
yyerror ("void expression with +");
578
$$ = ($1 | $3) & ~EX_PAREN;
496
580
| expression '-' expression
582
if (($1 & EX_VOID) || ($3 & EX_VOID))
583
yyerror ("void expression with -");
585
$$ = ($1 | $3) & ~EX_PAREN;
501
587
| expression '*' expression
589
if (($1 & EX_VOID) || ($3 & EX_VOID))
590
yyerror ("void expression with *");
592
$$ = ($1 | $3) & ~EX_PAREN;
506
594
| expression '/' expression
596
if (($1 & EX_VOID) || ($3 & EX_VOID))
597
yyerror ("void expression with /");
599
$$ = ($1 | $3) & ~EX_PAREN;
511
601
| expression '%' expression
603
if (($1 & EX_VOID) || ($3 & EX_VOID))
604
yyerror ("void expression with %");
606
$$ = ($1 | $3) & ~EX_PAREN;
516
608
| expression '^' expression
610
if (($1 & EX_VOID) || ($3 & EX_VOID))
611
yyerror ("void expression with ^");
613
$$ = ($1 | $3) & ~EX_PAREN;
521
615
| '-' expression %prec UNARY_MINUS
618
yyerror ("void expression with unary -");
526
622
| named_expression
530
626
sprintf (genstr, "L%d:", -$1);
551
647
| '(' expression ')'
650
yyerror ("void expression in parenthesis");
651
$$ = $2 | EX_REG | EX_PAREN;
553
653
| NAME '(' opt_argument_list ')'
655
fn = lookup ($1,FUNCT);
656
if (functions[fn].f_void)
558
sprintf (genstr, "C%d,%s:",
661
{ char *params = call_str ($3);
662
set_genstr_size (20 + strlen (params));
663
sprintf (genstr, "C%d,%s:", fn, params);
565
sprintf (genstr, "C%d:", lookup ($1,FUNCT));
668
sprintf (genstr, "C%d:", fn);
567
670
generate (genstr);
569
672
| INCR_DECR named_expression
609
712
generate (genstr);
611
714
| Length '(' expression ')'
612
{ generate ("cL"); $$ = 1;}
717
yyerror ("void expression in length()");
613
721
| Sqrt '(' expression ')'
614
{ generate ("cR"); $$ = 1;}
724
yyerror ("void expression in sqrt()");
615
728
| Scale '(' expression ')'
616
{ generate ("cS"); $$ = 1;}
731
yyerror ("void expression in scale()");
619
737
warn ("read function");
620
generate ("cI"); $$ = 1;
743
warn ("random function");
623
748
named_expression : NAME
624
749
{ $$ = lookup($1,SIMPLE); }
625
750
| NAME '[' expression ']'
627
if ($3 > 1) warn("comparison in subscript");
753
yyerror("void expression as subscript");
755
warn("comparison in subscript");
628
756
$$ = lookup($1,ARRAY);