/* sbc.y: A POSIX bc processor written for minix with no extensions. */
/* This file is part of bc written for MINIX.
Copyright (C) 1991 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License , or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
You may contact the author by:
us-mail: Philip A. Nelson
Computer Science Department, 9062
Western Washington University
Bellingham, WA 98226-9062
*************************************************************************/
#include "global.h" /* To get the global variables. */
%token <i_value> NEWLINE AND OR NOT
%token <s_value> STRING NAME NUMBER
/* '-', '+' are tokens themselves */
%token <c_value> ASSIGN_OP
/* '=', '+=', '-=', '*=', '/=', '%=', '^=' */
/* '==', '<=', '>=', '!=', '<', '>' */
%token <c_value> INCR_DECR
%token <i_value> Define Break Quit Length
/* 'define', 'break', 'quit', 'length' */
%token <i_value> Return For If While Sqrt Else
/* 'return', 'for', 'if', 'while', 'sqrt', 'else' */
%token <i_value> Scale Ibase Obase Auto Read
/* 'scale', 'ibase', 'obase', 'auto', 'read' */
%token <i_value> Warranty, Halt, Last, Continue, Print, Limits
/* 'warranty', 'halt', 'last', 'continue', 'print', 'limits' */
/* The types of all other non-terminals. */
%type <i_value> expression named_expression return_expression
%type <a_value> opt_parameter_list parameter_list opt_auto_define_list
%type <a_value> define_list opt_argument_list argument_list
%type <i_value> program input_item semicolon_list statement_list
%type <i_value> statement_or_error statement function relational_expression
printf ("s%s\n", BC_VERSION);
input_item : semicolon_list NEWLINE
semicolon_list : /* empty */
| semicolon_list ';' statement_or_error
statement_list : /* empty */
| statement_list NEWLINE statement
| statement_list ';' statement
statement_or_error : statement
yyerror ("Break outside a for/while");
sprintf (genstr, "J%1d:", break_label);
| Return '(' return_expression ')'
break_label = next_label++;
sprintf (genstr, "pN%1d:", $4);
relational_expression ';'
sprintf (genstr, "B%1d:J%1d:", $7, break_label);
$<i_value>$ = next_label++;
sprintf (genstr, "N%1d:", $<i_value>$);
sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
sprintf (genstr, "J%1d:N%1d:", $<i_value>9,
| If '(' relational_expression ')'
sprintf (genstr, "Z%1d:", $3);
sprintf (genstr, "N%1d:", $3);
sprintf (genstr, "N%1d:", $1);
'(' relational_expression
break_label = next_label++;
sprintf (genstr, "Z%1d:", break_label);
sprintf (genstr, "J%1d:N%1d:", $1, break_label);
function : Define NAME '(' opt_parameter_list ')' '{'
NEWLINE opt_auto_define_list
sprintf (genstr, "F%d,%s.%s[", lookup($2,FUNCT),
arg_str ($4,TRUE), arg_str ($8,TRUE));
statement_list NEWLINE '}'
opt_parameter_list : /* empty */
{ $$ = nextarg (NULL, lookup($1,SIMPLE)); }
{ $$ = nextarg ($1, lookup($3,SIMPLE)); }
opt_auto_define_list : /* empty */
| Auto define_list NEWLINE
{ $$ = nextarg (NULL, lookup($1,SIMPLE)); }
{ $$ = nextarg (NULL, lookup($1,ARRAY)); }
{ $$ = nextarg ($1, lookup($3,SIMPLE)); }
| define_list ',' NAME '[' ']'
{ $$ = nextarg ($1, lookup($3,ARRAY)); }
opt_argument_list : /* empty */
argument_list : expression
{ $$ = nextarg (NULL,0); }
| argument_list ',' expression
relational_expression : expression
| expression REL_OP expression
return_expression : /* empty */
expression : named_expression ASSIGN_OP
sprintf (genstr, "DL%d:", -$1);
sprintf (genstr, "l%d:", $1);
sprintf (genstr, "%c", $2);
sprintf (genstr, "S%d:", -$1);
sprintf (genstr, "s%d:", $1);
| expression '+' expression
| expression '-' expression
| expression MUL_OP expression
| expression '^' expression
| '-' expression %prec UNARY_MINUS
{ generate ("n"); $$ = 1;}
sprintf (genstr, "L%d:", -$1);
sprintf (genstr, "l%d:", $1);
if (len == 1 && *$1 == '0')
if (len == 1 && *$1 == '1')
| NAME '(' opt_argument_list ')'
sprintf (genstr, "C%d,%s:", lookup($1,FUNCT),
sprintf (genstr, "C%d:", lookup($1,FUNCT));
| INCR_DECR named_expression
sprintf (genstr, "DA%d:L%d:", -$2, -$2);
sprintf (genstr, "DM%d:L%d:", -$2, -$2);
sprintf (genstr, "i%d:l%d:", $2, $2);
sprintf (genstr, "d%d:l%d:", $2, $2);
| named_expression INCR_DECR
sprintf (genstr, "DL%d:x", -$1);
sprintf (genstr, "A%d:", -$1);
sprintf (genstr, "M%d:", -$1);
sprintf (genstr, "l%d:", $1);
sprintf (genstr, "i%d:", $1);
sprintf (genstr, "d%d:", $1);
| Length '(' expression ')'
{ generate ("cL"); $$ = 1;}
| Sqrt '(' expression ')'
{ generate ("cR"); $$ = 1;}
| Scale '(' expression ')'
{ generate ("cS"); $$ = 1;}
{ $$ = lookup($1,SIMPLE); }
| NAME '[' expression ']'
{ $$ = lookup($1,ARRAY); }