Blame bc/sbc.y

Packit 70b277
%{
Packit 70b277
/* sbc.y: A POSIX bc processor written for minix with no extensions.  */
Packit 70b277
 
Packit 70b277
/*  This file is part of GNU bc.
Packit 70b277
    Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
Packit 70b277
Packit 70b277
    This program is free software; you can redistribute it and/or modify
Packit 70b277
    it under the terms of the GNU General Public License as published by
Packit 70b277
    the Free Software Foundation; either version 2 of the License , or
Packit 70b277
    (at your option) any later version.
Packit 70b277
Packit 70b277
    This program is distributed in the hope that it will be useful,
Packit 70b277
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 70b277
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 70b277
    GNU General Public License for more details.
Packit 70b277
Packit 70b277
    You should have received a copy of the GNU General Public License
Packit 70b277
    along with this program; see the file COPYING.  If not, write to
Packit 70b277
      The Free Software Foundation, Inc.
Packit 70b277
      51 Franklin Street, Fifth Floor
Packit 70b277
      Boston, MA 02110-1301  USA
Packit 70b277
Packit 70b277
Packit 70b277
    You may contact the author by:
Packit 70b277
       e-mail:  philnelson@acm.org
Packit 70b277
      us-mail:  Philip A. Nelson
Packit 70b277
                Computer Science Department, 9062
Packit 70b277
                Western Washington University
Packit 70b277
                Bellingham, WA 98226-9062
Packit 70b277
       
Packit 70b277
*************************************************************************/
Packit 70b277
Packit 70b277
#include "bcdefs.h"
Packit 70b277
#include "global.h"     /* To get the global variables. */
Packit 70b277
#include "proto.h"
Packit 70b277
%}
Packit 70b277
Packit 70b277
%start program
Packit 70b277
Packit 70b277
%union {
Packit 70b277
	char *s_value;
Packit 70b277
	char  c_value;
Packit 70b277
	int   i_value;
Packit 70b277
	arg_list *a_value;
Packit 70b277
       }
Packit 70b277
Packit 70b277
%token <i_value> ENDOFLINE AND OR NOT
Packit 70b277
%token <s_value> STRING NAME NUMBER
Packit 70b277
/*     '-', '+' are tokens themselves		*/
Packit 70b277
%token <c_value> ASSIGN_OP
Packit 70b277
/*     '=', '+=',  '-=', '*=', '/=', '%=', '^=' */
Packit 70b277
%token <s_value> REL_OP
Packit 70b277
/*     '==', '<=', '>=', '!=', '<', '>' 	*/
Packit 70b277
%token <c_value> INCR_DECR
Packit 70b277
/*     '++', '--' 				*/
Packit 70b277
%token <i_value> Define    Break    Quit    Length
Packit 70b277
/*     'define', 'break', 'quit', 'length' 	*/
Packit 70b277
%token <i_value> Return    For    If    While    Sqrt  Else
Packit 70b277
/*     'return', 'for', 'if', 'while', 'sqrt',  'else' 	*/
Packit 70b277
%token <i_value> Scale    Ibase    Obase    Auto  Read
Packit 70b277
/*     'scale', 'ibase', 'obase', 'auto', 'read' 	*/
Packit 70b277
%token <i_value> Warranty, Halt, Last, Continue, Print, Limits
Packit 70b277
/*     'warranty', 'halt', 'last', 'continue', 'print', 'limits'  */
Packit 70b277
Packit 70b277
/* The types of all other non-terminals. */
Packit 70b277
%type <i_value> expression named_expression return_expression
Packit 70b277
%type <a_value> opt_parameter_list parameter_list opt_auto_define_list
Packit 70b277
%type <a_value> define_list opt_argument_list argument_list
Packit 70b277
%type <i_value> program input_item semicolon_list statement_list
Packit 70b277
%type <i_value> statement_or_error statement function relational_expression 
Packit 70b277
Packit 70b277
/* precedence */
Packit 70b277
%nonassoc REL_OP
Packit 70b277
%right ASSIGN_OP
Packit 70b277
%left '+' '-'
Packit 70b277
%left '*' '/' '%'
Packit 70b277
%right '^'
Packit 70b277
%nonassoc UNARY_MINUS
Packit 70b277
%nonassoc INCR_DECR
Packit 70b277
Packit 70b277
%%
Packit 70b277
program			: /* empty */
Packit 70b277
			    {
Packit 70b277
			      $$ = 0;
Packit 70b277
			      std_only = TRUE;
Packit 70b277
			      if (interactive && !quiet)
Packit 70b277
				{
Packit 70b277
				  show_bc_version ();
Packit 70b277
				  welcome ();
Packit 70b277
				}
Packit 70b277
			    }
Packit 70b277
			| program input_item
Packit 70b277
			;
Packit 70b277
input_item		: semicolon_list ENDOFLINE
Packit 70b277
			    { run_code (); }
Packit 70b277
			| function
Packit 70b277
			    { run_code (); }
Packit 70b277
			| error ENDOFLINE
Packit 70b277
			    {
Packit 70b277
			      yyerrok; 
Packit 70b277
			      init_gen () ;
Packit 70b277
			    }
Packit 70b277
			;
Packit 70b277
semicolon_list		: /* empty */
Packit 70b277
			    { $$ = 0; }
Packit 70b277
			| statement_or_error
Packit 70b277
			| semicolon_list ';' statement_or_error
Packit 70b277
			| semicolon_list ';'
Packit 70b277
			;
Packit 70b277
statement_list		: /* empty */
Packit 70b277
			    { $$ = 0; }
Packit 70b277
			| statement
Packit 70b277
			| statement_list ENDOFLINE
Packit 70b277
			| statement_list ENDOFLINE statement
Packit 70b277
			| statement_list ';'
Packit 70b277
			| statement_list ';' statement
Packit 70b277
			;
Packit 70b277
statement_or_error	: statement
Packit 70b277
			| error statement
Packit 70b277
			    { $$ = $2; }
Packit 70b277
			;
Packit 70b277
statement 		: Warranty
Packit 70b277
			    { warranty ("s"); }
Packit 70b277
			| expression
Packit 70b277
			    {
Packit 70b277
			      if ($1 & 1)
Packit 70b277
				generate ("W");
Packit 70b277
			      else
Packit 70b277
				generate ("p");
Packit 70b277
			    }
Packit 70b277
			| STRING
Packit 70b277
			    {
Packit 70b277
			      $$ = 0;
Packit 70b277
			      generate ("w");
Packit 70b277
			      generate ($1);
Packit 70b277
			      free ($1);
Packit 70b277
			    }
Packit 70b277
			| Break
Packit 70b277
			    {
Packit 70b277
			      if (break_label == 0)
Packit 70b277
				yyerror ("Break outside a for/while");
Packit 70b277
			      else
Packit 70b277
				{
Packit 70b277
				  sprintf (genstr, "J%1d:", break_label);
Packit 70b277
				  generate (genstr);
Packit 70b277
				}
Packit 70b277
			    }
Packit 70b277
			| Quit
Packit 70b277
			    { bc_exit (0); }
Packit 70b277
			| Return
Packit 70b277
			    { generate ("0R"); }
Packit 70b277
			| Return '(' return_expression ')'
Packit 70b277
			    { generate ("R"); }
Packit 70b277
			| For 
Packit 70b277
			    {
Packit 70b277
			      $1 = break_label; 
Packit 70b277
			      break_label = next_label++;
Packit 70b277
			    }
Packit 70b277
			  '(' expression ';'
Packit 70b277
			    {
Packit 70b277
			      $4 = next_label++;
Packit 70b277
			      sprintf (genstr, "pN%1d:", $4);
Packit 70b277
			      generate (genstr);
Packit 70b277
			    }
Packit 70b277
			  relational_expression ';'
Packit 70b277
			    {
Packit 70b277
			      $7 = next_label++;
Packit 70b277
			      sprintf (genstr, "B%1d:J%1d:", $7, break_label);
Packit 70b277
			      generate (genstr);
Packit 70b277
			      $<i_value>$ = next_label++;
Packit 70b277
			      sprintf (genstr, "N%1d:", $<i_value>$);
Packit 70b277
			      generate (genstr);
Packit 70b277
			    }
Packit 70b277
			  expression ')'
Packit 70b277
			    {
Packit 70b277
			      sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
Packit 70b277
			      generate (genstr);
Packit 70b277
			    }
Packit 70b277
			  statement
Packit 70b277
			    {
Packit 70b277
			      sprintf (genstr, "J%1d:N%1d:", $<i_value>9,
Packit 70b277
				       break_label);
Packit 70b277
			      generate (genstr);
Packit 70b277
			      break_label = $1;
Packit 70b277
			    }
Packit 70b277
			| If '(' relational_expression ')' 
Packit 70b277
			    {
Packit 70b277
			      $3 = next_label++;
Packit 70b277
			      sprintf (genstr, "Z%1d:", $3);
Packit 70b277
			      generate (genstr);
Packit 70b277
			    }
Packit 70b277
			  statement
Packit 70b277
			    {
Packit 70b277
			      sprintf (genstr, "N%1d:", $3); 
Packit 70b277
			      generate (genstr);
Packit 70b277
			    }
Packit 70b277
			| While 
Packit 70b277
			    {
Packit 70b277
			      $1 = next_label++;
Packit 70b277
			      sprintf (genstr, "N%1d:", $1);
Packit 70b277
			      generate (genstr);
Packit 70b277
			    }
Packit 70b277
			'(' relational_expression 
Packit 70b277
			    {
Packit 70b277
			      $4 = break_label; 
Packit 70b277
			      break_label = next_label++;
Packit 70b277
			      sprintf (genstr, "Z%1d:", break_label);
Packit 70b277
			      generate (genstr);
Packit 70b277
			    }
Packit 70b277
			')' statement
Packit 70b277
			    {
Packit 70b277
			      sprintf (genstr, "J%1d:N%1d:", $1, break_label);
Packit 70b277
			      generate (genstr);
Packit 70b277
			      break_label = $4;
Packit 70b277
			    }
Packit 70b277
			| '{' statement_list '}'
Packit 70b277
			    { $$ = 0; }
Packit 70b277
			;
Packit 70b277
function 		: Define NAME '(' opt_parameter_list ')' '{'
Packit 70b277
       			  ENDOFLINE opt_auto_define_list 
Packit 70b277
			    { char *params, *autos;
Packit 70b277
			      check_params ($4,$8);
Packit 70b277
			      params = arg_str ($4);
Packit 70b277
			      autos = arg_str ($8);
Packit 70b277
			      set_genstr_size (30 + strlen (params)
Packit 70b277
					       + strlen (autos));
Packit 70b277
			      sprintf (genstr, "F%d,%s.%s[", lookup ($2,FUNCT),
Packit 70b277
				       params, autos);
Packit 70b277
			      generate (genstr);
Packit 70b277
			      free_args ($4);
Packit 70b277
			      free_args ($8);
Packit 70b277
			      $1 = next_label;
Packit 70b277
			      next_label = 0;
Packit 70b277
			    }
Packit 70b277
			  statement_list ENDOFLINE '}'
Packit 70b277
			    {
Packit 70b277
			      generate ("0R]");
Packit 70b277
			      next_label = $1;
Packit 70b277
			    }
Packit 70b277
			;
Packit 70b277
opt_parameter_list	: /* empty */ 
Packit 70b277
			    { $$ = NULL; }
Packit 70b277
			| parameter_list
Packit 70b277
			;
Packit 70b277
parameter_list 		: NAME
Packit 70b277
			    { $$ = nextarg (NULL, lookup ($1,SIMPLE), FALSE); }
Packit 70b277
			| define_list ',' NAME
Packit 70b277
			    { $$ = nextarg ($1, lookup ($3,SIMPLE), FALSE); }
Packit 70b277
			;
Packit 70b277
opt_auto_define_list 	: /* empty */ 
Packit 70b277
			    { $$ = NULL; }
Packit 70b277
			| Auto define_list ENDOFLINE
Packit 70b277
			    { $$ = $2; } 
Packit 70b277
			| Auto define_list ';'
Packit 70b277
			    { $$ = $2; } 
Packit 70b277
			;
Packit 70b277
define_list 		: NAME
Packit 70b277
			    { $$ = nextarg (NULL, lookup ($1,SIMPLE), FALSE); }
Packit 70b277
			| NAME '[' ']'
Packit 70b277
			    { $$ = nextarg (NULL, lookup ($1,ARRAY), FALSE); }
Packit 70b277
			| define_list ',' NAME
Packit 70b277
			    { $$ = nextarg ($1, lookup ($3,SIMPLE), FALSE); }
Packit 70b277
			| define_list ',' NAME '[' ']'
Packit 70b277
			    { $$ = nextarg ($1, lookup ($3,ARRAY), FALSE); }
Packit 70b277
			;
Packit 70b277
opt_argument_list	: /* empty */
Packit 70b277
			    { $$ = NULL; }
Packit 70b277
			| argument_list
Packit 70b277
			;
Packit 70b277
argument_list 		: expression
Packit 70b277
			    { $$ = nextarg (NULL,0, FALSE); }
Packit 70b277
			| argument_list ',' expression
Packit 70b277
			    { $$ = nextarg ($1,0, FALSE); }
Packit 70b277
			;
Packit 70b277
relational_expression	: expression
Packit 70b277
			    { $$ = 0; }
Packit 70b277
			| expression REL_OP expression
Packit 70b277
			    {
Packit 70b277
			      $$ = 0;
Packit 70b277
			      switch (*($2))
Packit 70b277
				{
Packit 70b277
				case '=':
Packit 70b277
				  generate ("=");
Packit 70b277
				  break;
Packit 70b277
				case '!':
Packit 70b277
				  generate ("#");
Packit 70b277
				  break;
Packit 70b277
				case '<':
Packit 70b277
				  if ($2[1] == '=')
Packit 70b277
				    generate ("{");
Packit 70b277
				  else
Packit 70b277
				    generate ("<");
Packit 70b277
				  break;
Packit 70b277
				case '>':
Packit 70b277
				  if ($2[1] == '=')
Packit 70b277
				    generate ("}");
Packit 70b277
				  else
Packit 70b277
				    generate (">");
Packit 70b277
				  break;
Packit 70b277
				}
Packit 70b277
			    }
Packit 70b277
			;
Packit 70b277
return_expression	: /* empty */
Packit 70b277
			    {
Packit 70b277
			      $$ = 0;
Packit 70b277
			      generate ("0");
Packit 70b277
			    }
Packit 70b277
			| expression
Packit 70b277
			;
Packit 70b277
expression		: named_expression ASSIGN_OP 
Packit 70b277
			    {
Packit 70b277
			      if ($2 != '=')
Packit 70b277
				{
Packit 70b277
				  if ($1 < 0)
Packit 70b277
				    sprintf (genstr, "DL%d:", -$1);
Packit 70b277
				  else
Packit 70b277
				    sprintf (genstr, "l%d:", $1);
Packit 70b277
				  generate (genstr);
Packit 70b277
				}
Packit 70b277
			    }
Packit 70b277
			  expression
Packit 70b277
			    {
Packit 70b277
			      $$ = 0;
Packit 70b277
			      if ($2 != '=')
Packit 70b277
				{
Packit 70b277
				  sprintf (genstr, "%c", $2);
Packit 70b277
				  generate (genstr);
Packit 70b277
				}
Packit 70b277
			      if ($1 < 0)
Packit 70b277
				sprintf (genstr, "S%d:", -$1);
Packit 70b277
			      else
Packit 70b277
				sprintf (genstr, "s%d:", $1);
Packit 70b277
			      generate (genstr);
Packit 70b277
			    }
Packit 70b277
			| expression '+' expression
Packit 70b277
			    { generate ("+"); }
Packit 70b277
			| expression '-' expression
Packit 70b277
			    { generate ("-"); }
Packit 70b277
			| expression '*' expression
Packit 70b277
			    { generate ("*"); }
Packit 70b277
			| expression '/' expression
Packit 70b277
			    { generate ("/"); }
Packit 70b277
			| expression '%' expression
Packit 70b277
			    { generate ("%"); }
Packit 70b277
			| expression '^' expression
Packit 70b277
			    { generate ("^"); }
Packit 70b277
			| '-' expression           %prec UNARY_MINUS
Packit 70b277
			    { generate ("n"); $$ = 1;}
Packit 70b277
			| named_expression
Packit 70b277
			    {
Packit 70b277
			      $$ = 1;
Packit 70b277
			      if ($1 < 0)
Packit 70b277
				sprintf (genstr, "L%d:", -$1);
Packit 70b277
			      else
Packit 70b277
				sprintf (genstr, "l%d:", $1);
Packit 70b277
			      generate (genstr);
Packit 70b277
			    }
Packit 70b277
			| NUMBER
Packit 70b277
			    {
Packit 70b277
			      int len = strlen ($1);
Packit 70b277
			      $$ = 1;
Packit 70b277
			      if (len == 1 && *$1 == '0')
Packit 70b277
				generate ("0");
Packit 70b277
			      else
Packit 70b277
				{
Packit 70b277
				  if (len == 1 && *$1 == '1')
Packit 70b277
				    generate ("1");
Packit 70b277
				  else
Packit 70b277
				    {
Packit 70b277
				      generate ("K");
Packit 70b277
				      generate ($1);
Packit 70b277
				      generate (":");
Packit 70b277
				    }
Packit 70b277
				  free ($1);
Packit 70b277
				}
Packit 70b277
			    }
Packit 70b277
			| '(' expression ')'
Packit 70b277
			    { $$ = 1; }
Packit 70b277
			| NAME '(' opt_argument_list ')'
Packit 70b277
			    {
Packit 70b277
			      $$ = 1;
Packit 70b277
			      if ($3 != NULL)
Packit 70b277
				{ char *params = call_str ($3);
Packit 70b277
				  set_genstr_size (20 + strlen (params));
Packit 70b277
				  sprintf (genstr, "C%d,%s:",
Packit 70b277
					   lookup ($1,FUNCT), params);
Packit 70b277
				  free_args ($3);
Packit 70b277
				}
Packit 70b277
			      else
Packit 70b277
				  sprintf (genstr, "C%d:", lookup ($1,FUNCT));
Packit 70b277
			      generate (genstr);
Packit 70b277
			    }
Packit 70b277
			| INCR_DECR named_expression
Packit 70b277
			    {
Packit 70b277
			      $$ = 1;
Packit 70b277
			      if ($2 < 0)
Packit 70b277
				{
Packit 70b277
				  if ($1 == '+')
Packit 70b277
				    sprintf (genstr, "DA%d:L%d:", -$2, -$2);
Packit 70b277
				  else
Packit 70b277
				    sprintf (genstr, "DM%d:L%d:", -$2, -$2);
Packit 70b277
				}
Packit 70b277
			      else
Packit 70b277
				{
Packit 70b277
				  if ($1 == '+')
Packit 70b277
				    sprintf (genstr, "i%d:l%d:", $2, $2);
Packit 70b277
				  else
Packit 70b277
				    sprintf (genstr, "d%d:l%d:", $2, $2);
Packit 70b277
				}
Packit 70b277
			      generate (genstr);
Packit 70b277
			    }
Packit 70b277
			| named_expression INCR_DECR
Packit 70b277
			    {
Packit 70b277
			      $$ = 1;
Packit 70b277
			      if ($1 < 0)
Packit 70b277
				{
Packit 70b277
				  sprintf (genstr, "DL%d:x", -$1);
Packit 70b277
				  generate (genstr); 
Packit 70b277
				  if ($2 == '+')
Packit 70b277
				    sprintf (genstr, "A%d:", -$1);
Packit 70b277
				  else
Packit 70b277
				    sprintf (genstr, "M%d:", -$1);
Packit 70b277
				}
Packit 70b277
			      else
Packit 70b277
				{
Packit 70b277
				  sprintf (genstr, "l%d:", $1);
Packit 70b277
				  generate (genstr);
Packit 70b277
				  if ($2 == '+')
Packit 70b277
				    sprintf (genstr, "i%d:", $1);
Packit 70b277
				  else
Packit 70b277
				    sprintf (genstr, "d%d:", $1);
Packit 70b277
				}
Packit 70b277
			      generate (genstr);
Packit 70b277
			    }
Packit 70b277
			| Length '(' expression ')'
Packit 70b277
			    { generate ("cL"); $$ = 1;}
Packit 70b277
			| Sqrt '(' expression ')'
Packit 70b277
			    { generate ("cR"); $$ = 1;}
Packit 70b277
			| Scale '(' expression ')'
Packit 70b277
			    { generate ("cS"); $$ = 1;}
Packit 70b277
			;
Packit 70b277
named_expression	: NAME
Packit 70b277
			    { $$ = lookup ($1,SIMPLE); }
Packit 70b277
			| NAME '[' expression ']'
Packit 70b277
			    { $$ = lookup ($1,ARRAY); }
Packit 70b277
			| Ibase
Packit 70b277
			    { $$ = 0; }
Packit 70b277
			| Obase
Packit 70b277
			    { $$ = 1; }
Packit 70b277
			| Scale
Packit 70b277
			    { $$ = 2; }
Packit 70b277
			;
Packit 70b277
Packit 70b277
%%