449 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Plaintext
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			449 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Plaintext
		
	
	
		
			Executable File
		
	
	
	
	
, %{
 | 
						|
/* sbc.y: A POSIX bc processor written for minix with no extensions.  */
 | 
						|
 
 | 
						|
/*  This file is part of bc written for MINIX.
 | 
						|
    Copyright (C) 1991, 1992 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:
 | 
						|
       e-mail:  phil@cs.wwu.edu
 | 
						|
      us-mail:  Philip A. Nelson
 | 
						|
                Computer Science Department, 9062
 | 
						|
                Western Washington University
 | 
						|
                Bellingham, WA 98226-9062
 | 
						|
       
 | 
						|
*************************************************************************/
 | 
						|
 | 
						|
#include "bcdefs.h"
 | 
						|
#include "global.h"     /* To get the global variables. */
 | 
						|
#include "proto.h"
 | 
						|
%}
 | 
						|
 | 
						|
%start program
 | 
						|
 | 
						|
%union {
 | 
						|
	char *s_value;
 | 
						|
	char  c_value;
 | 
						|
	int   i_value;
 | 
						|
	arg_list *a_value;
 | 
						|
       }
 | 
						|
 | 
						|
%token <i_value> NEWLINE AND OR NOT
 | 
						|
%token <s_value> STRING NAME NUMBER
 | 
						|
/*     '-', '+' are tokens themselves		*/
 | 
						|
%token <c_value> MUL_OP
 | 
						|
/*     '*', '/', '%' 				*/
 | 
						|
%token <c_value> ASSIGN_OP
 | 
						|
/*     '=', '+=',  '-=', '*=', '/=', '%=', '^=' */
 | 
						|
%token <s_value> REL_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 
 | 
						|
 | 
						|
/* precedence */
 | 
						|
%nonassoc REL_OP
 | 
						|
%right ASSIGN_OP
 | 
						|
%left '+' '-'
 | 
						|
%left MUL_OP
 | 
						|
%right '^'
 | 
						|
%nonassoc UNARY_MINUS
 | 
						|
%nonassoc INCR_DECR
 | 
						|
 | 
						|
%%
 | 
						|
program			: /* empty */
 | 
						|
			    {
 | 
						|
			      $$ = 0;
 | 
						|
			      std_only = TRUE;
 | 
						|
			      if (interactive)
 | 
						|
				{
 | 
						|
				  printf ("s%s\n", BC_VERSION);
 | 
						|
				  welcome();
 | 
						|
				}
 | 
						|
			    }
 | 
						|
			| program input_item
 | 
						|
			;
 | 
						|
input_item		: semicolon_list NEWLINE
 | 
						|
			    { run_code(); }
 | 
						|
			| function
 | 
						|
			    { run_code(); }
 | 
						|
			| error NEWLINE
 | 
						|
			    {
 | 
						|
			      yyerrok; 
 | 
						|
			      init_gen() ;
 | 
						|
			    }
 | 
						|
			;
 | 
						|
semicolon_list		: /* empty */
 | 
						|
			    { $$ = 0; }
 | 
						|
			| statement_or_error
 | 
						|
			| semicolon_list ';' statement_or_error
 | 
						|
			| semicolon_list ';'
 | 
						|
			;
 | 
						|
statement_list		: /* empty */
 | 
						|
			    { $$ = 0; }
 | 
						|
			| statement
 | 
						|
			| statement_list NEWLINE
 | 
						|
			| statement_list NEWLINE statement
 | 
						|
			| statement_list ';'
 | 
						|
			| statement_list ';' statement
 | 
						|
			;
 | 
						|
statement_or_error	: statement
 | 
						|
			| error statement
 | 
						|
			    { $$ = $2; }
 | 
						|
			;
 | 
						|
statement 		: Warranty
 | 
						|
			    { warranty("s"); }
 | 
						|
			| expression
 | 
						|
			    {
 | 
						|
			      if ($1 & 1)
 | 
						|
				generate ("W");
 | 
						|
			      else
 | 
						|
				generate ("p");
 | 
						|
			    }
 | 
						|
			| STRING
 | 
						|
			    {
 | 
						|
			      $$ = 0;
 | 
						|
			      generate ("w");
 | 
						|
			      generate ($1);
 | 
						|
			      free ($1);
 | 
						|
			    }
 | 
						|
			| Break
 | 
						|
			    {
 | 
						|
			      if (break_label == 0)
 | 
						|
				yyerror ("Break outside a for/while");
 | 
						|
			      else
 | 
						|
				{
 | 
						|
				  sprintf (genstr, "J%1d:", break_label);
 | 
						|
				  generate (genstr);
 | 
						|
				}
 | 
						|
			    }
 | 
						|
			| Quit
 | 
						|
			    { exit(0); }
 | 
						|
			| Return
 | 
						|
			    { generate ("0R"); }
 | 
						|
			| Return '(' return_expression ')'
 | 
						|
			    { generate ("R"); }
 | 
						|
			| For 
 | 
						|
			    {
 | 
						|
			      $1 = break_label; 
 | 
						|
			      break_label = next_label++;
 | 
						|
			    }
 | 
						|
			  '(' expression ';'
 | 
						|
			    {
 | 
						|
			      $4 = next_label++;
 | 
						|
			      sprintf (genstr, "pN%1d:", $4);
 | 
						|
			      generate (genstr);
 | 
						|
			    }
 | 
						|
			  relational_expression ';'
 | 
						|
			    {
 | 
						|
			      $7 = next_label++;
 | 
						|
			      sprintf (genstr, "B%1d:J%1d:", $7, break_label);
 | 
						|
			      generate (genstr);
 | 
						|
			      $<i_value>$ = next_label++;
 | 
						|
			      sprintf (genstr, "N%1d:", $<i_value>$);
 | 
						|
			      generate (genstr);
 | 
						|
			    }
 | 
						|
			  expression ')'
 | 
						|
			    {
 | 
						|
			      sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
 | 
						|
			      generate (genstr);
 | 
						|
			    }
 | 
						|
			  statement
 | 
						|
			    {
 | 
						|
			      sprintf (genstr, "J%1d:N%1d:", $<i_value>9,
 | 
						|
				       break_label);
 | 
						|
			      generate (genstr);
 | 
						|
			      break_label = $1;
 | 
						|
			    }
 | 
						|
			| If '(' relational_expression ')' 
 | 
						|
			    {
 | 
						|
			      $3 = next_label++;
 | 
						|
			      sprintf (genstr, "Z%1d:", $3);
 | 
						|
			      generate (genstr);
 | 
						|
			    }
 | 
						|
			  statement
 | 
						|
			    {
 | 
						|
			      sprintf (genstr, "N%1d:", $3); 
 | 
						|
			      generate (genstr);
 | 
						|
			    }
 | 
						|
			| While 
 | 
						|
			    {
 | 
						|
			      $1 = next_label++;
 | 
						|
			      sprintf (genstr, "N%1d:", $1);
 | 
						|
			      generate (genstr);
 | 
						|
			    }
 | 
						|
			'(' relational_expression 
 | 
						|
			    {
 | 
						|
			      $4 = break_label; 
 | 
						|
			      break_label = next_label++;
 | 
						|
			      sprintf (genstr, "Z%1d:", break_label);
 | 
						|
			      generate (genstr);
 | 
						|
			    }
 | 
						|
			')' statement
 | 
						|
			    {
 | 
						|
			      sprintf (genstr, "J%1d:N%1d:", $1, break_label);
 | 
						|
			      generate (genstr);
 | 
						|
			      break_label = $4;
 | 
						|
			    }
 | 
						|
			| '{' statement_list '}'
 | 
						|
			    { $$ = 0; }
 | 
						|
			;
 | 
						|
function 		: Define NAME '(' opt_parameter_list ')' '{'
 | 
						|
       			  NEWLINE opt_auto_define_list 
 | 
						|
			    {
 | 
						|
			      check_params ($4,$8);
 | 
						|
			      sprintf (genstr, "F%d,%s.%s[", lookup($2,FUNCT),
 | 
						|
				       arg_str ($4,TRUE), arg_str ($8,TRUE));
 | 
						|
			      generate (genstr);
 | 
						|
			      free_args ($4);
 | 
						|
			      free_args ($8);
 | 
						|
			      $1 = next_label;
 | 
						|
			      next_label = 0;
 | 
						|
			    }
 | 
						|
			  statement_list NEWLINE '}'
 | 
						|
			    {
 | 
						|
			      generate ("0R]");
 | 
						|
			      next_label = $1;
 | 
						|
			    }
 | 
						|
			;
 | 
						|
opt_parameter_list	: /* empty */ 
 | 
						|
			    { $$ = NULL; }
 | 
						|
			| parameter_list
 | 
						|
			;
 | 
						|
parameter_list 		: NAME
 | 
						|
			    { $$ = nextarg (NULL, lookup($1,SIMPLE)); }
 | 
						|
			| define_list ',' NAME
 | 
						|
			    { $$ = nextarg ($1, lookup($3,SIMPLE)); }
 | 
						|
			;
 | 
						|
opt_auto_define_list 	: /* empty */ 
 | 
						|
			    { $$ = NULL; }
 | 
						|
			| Auto define_list NEWLINE
 | 
						|
			    { $$ = $2; } 
 | 
						|
			| Auto define_list ';'
 | 
						|
			    { $$ = $2; } 
 | 
						|
			;
 | 
						|
define_list 		: NAME
 | 
						|
			    { $$ = nextarg (NULL, lookup($1,SIMPLE)); }
 | 
						|
			| NAME '[' ']'
 | 
						|
			    { $$ = nextarg (NULL, lookup($1,ARRAY)); }
 | 
						|
			| define_list ',' NAME
 | 
						|
			    { $$ = nextarg ($1, lookup($3,SIMPLE)); }
 | 
						|
			| define_list ',' NAME '[' ']'
 | 
						|
			    { $$ = nextarg ($1, lookup($3,ARRAY)); }
 | 
						|
			;
 | 
						|
opt_argument_list	: /* empty */
 | 
						|
			    { $$ = NULL; }
 | 
						|
			| argument_list
 | 
						|
			;
 | 
						|
argument_list 		: expression
 | 
						|
			    { $$ = nextarg (NULL,0); }
 | 
						|
			| argument_list ',' expression
 | 
						|
			    { $$ = nextarg ($1,0); }
 | 
						|
			;
 | 
						|
relational_expression	: expression
 | 
						|
			    { $$ = 0; }
 | 
						|
			| expression REL_OP expression
 | 
						|
			    {
 | 
						|
			      $$ = 0;
 | 
						|
			      switch (*($2))
 | 
						|
				{
 | 
						|
				case '=':
 | 
						|
				  generate ("=");
 | 
						|
				  break;
 | 
						|
				case '!':
 | 
						|
				  generate ("#");
 | 
						|
				  break;
 | 
						|
				case '<':
 | 
						|
				  if ($2[1] == '=')
 | 
						|
				    generate ("{");
 | 
						|
				  else
 | 
						|
				    generate ("<");
 | 
						|
				  break;
 | 
						|
				case '>':
 | 
						|
				  if ($2[1] == '=')
 | 
						|
				    generate ("}");
 | 
						|
				  else
 | 
						|
				    generate (">");
 | 
						|
				  break;
 | 
						|
				}
 | 
						|
			    }
 | 
						|
			;
 | 
						|
return_expression	: /* empty */
 | 
						|
			    {
 | 
						|
			      $$ = 0;
 | 
						|
			      generate ("0");
 | 
						|
			    }
 | 
						|
			| expression
 | 
						|
			;
 | 
						|
expression		: named_expression ASSIGN_OP 
 | 
						|
			    {
 | 
						|
			      if ($2 != '=')
 | 
						|
				{
 | 
						|
				  if ($1 < 0)
 | 
						|
				    sprintf (genstr, "DL%d:", -$1);
 | 
						|
				  else
 | 
						|
				    sprintf (genstr, "l%d:", $1);
 | 
						|
				  generate (genstr);
 | 
						|
				}
 | 
						|
			    }
 | 
						|
			  expression
 | 
						|
			    {
 | 
						|
			      $$ = 0;
 | 
						|
			      if ($2 != '=')
 | 
						|
				{
 | 
						|
				  sprintf (genstr, "%c", $2);
 | 
						|
				  generate (genstr);
 | 
						|
				}
 | 
						|
			      if ($1 < 0)
 | 
						|
				sprintf (genstr, "S%d:", -$1);
 | 
						|
			      else
 | 
						|
				sprintf (genstr, "s%d:", $1);
 | 
						|
			      generate (genstr);
 | 
						|
			    }
 | 
						|
			| expression '+' expression
 | 
						|
			    { generate ("+"); }
 | 
						|
			| expression '-' expression
 | 
						|
			    { generate ("-"); }
 | 
						|
			| expression MUL_OP expression
 | 
						|
			    {
 | 
						|
			      genstr[0] = $2;
 | 
						|
			      genstr[1] = 0;
 | 
						|
			      generate (genstr);
 | 
						|
			    }
 | 
						|
			| expression '^' expression
 | 
						|
			    { generate ("^"); }
 | 
						|
			| '-' expression           %prec UNARY_MINUS
 | 
						|
			    { generate ("n"); $$ = 1;}
 | 
						|
			| named_expression
 | 
						|
			    {
 | 
						|
			      $$ = 1;
 | 
						|
			      if ($1 < 0)
 | 
						|
				sprintf (genstr, "L%d:", -$1);
 | 
						|
			      else
 | 
						|
				sprintf (genstr, "l%d:", $1);
 | 
						|
			      generate (genstr);
 | 
						|
			    }
 | 
						|
			| NUMBER
 | 
						|
			    {
 | 
						|
			      int len = strlen($1);
 | 
						|
			      $$ = 1;
 | 
						|
			      if (len == 1 && *$1 == '0')
 | 
						|
				generate ("0");
 | 
						|
			      else
 | 
						|
				{
 | 
						|
				  if (len == 1 && *$1 == '1')
 | 
						|
				    generate ("1");
 | 
						|
				  else
 | 
						|
				    {
 | 
						|
				      generate ("K");
 | 
						|
				      generate ($1);
 | 
						|
				      generate (":");
 | 
						|
				    }
 | 
						|
				  free ($1);
 | 
						|
				}
 | 
						|
			    }
 | 
						|
			| '(' expression ')'
 | 
						|
			    { $$ = 1; }
 | 
						|
			| NAME '(' opt_argument_list ')'
 | 
						|
			    {
 | 
						|
			      $$ = 1;
 | 
						|
			      if ($3 != NULL)
 | 
						|
				{ 
 | 
						|
				  sprintf (genstr, "C%d,%s:", lookup($1,FUNCT),
 | 
						|
					   arg_str ($3,FALSE));
 | 
						|
				  free_args ($3);
 | 
						|
				}
 | 
						|
			      else
 | 
						|
				  sprintf (genstr, "C%d:", lookup($1,FUNCT));
 | 
						|
			      generate (genstr);
 | 
						|
			    }
 | 
						|
			| INCR_DECR named_expression
 | 
						|
			    {
 | 
						|
			      $$ = 1;
 | 
						|
			      if ($2 < 0)
 | 
						|
				{
 | 
						|
				  if ($1 == '+')
 | 
						|
				    sprintf (genstr, "DA%d:L%d:", -$2, -$2);
 | 
						|
				  else
 | 
						|
				    sprintf (genstr, "DM%d:L%d:", -$2, -$2);
 | 
						|
				}
 | 
						|
			      else
 | 
						|
				{
 | 
						|
				  if ($1 == '+')
 | 
						|
				    sprintf (genstr, "i%d:l%d:", $2, $2);
 | 
						|
				  else
 | 
						|
				    sprintf (genstr, "d%d:l%d:", $2, $2);
 | 
						|
				}
 | 
						|
			      generate (genstr);
 | 
						|
			    }
 | 
						|
			| named_expression INCR_DECR
 | 
						|
			    {
 | 
						|
			      $$ = 1;
 | 
						|
			      if ($1 < 0)
 | 
						|
				{
 | 
						|
				  sprintf (genstr, "DL%d:x", -$1);
 | 
						|
				  generate (genstr); 
 | 
						|
				  if ($2 == '+')
 | 
						|
				    sprintf (genstr, "A%d:", -$1);
 | 
						|
				  else
 | 
						|
				    sprintf (genstr, "M%d:", -$1);
 | 
						|
				}
 | 
						|
			      else
 | 
						|
				{
 | 
						|
				  sprintf (genstr, "l%d:", $1);
 | 
						|
				  generate (genstr);
 | 
						|
				  if ($2 == '+')
 | 
						|
				    sprintf (genstr, "i%d:", $1);
 | 
						|
				  else
 | 
						|
				    sprintf (genstr, "d%d:", $1);
 | 
						|
				}
 | 
						|
			      generate (genstr);
 | 
						|
			    }
 | 
						|
			| Length '(' expression ')'
 | 
						|
			    { generate ("cL"); $$ = 1;}
 | 
						|
			| Sqrt '(' expression ')'
 | 
						|
			    { generate ("cR"); $$ = 1;}
 | 
						|
			| Scale '(' expression ')'
 | 
						|
			    { generate ("cS"); $$ = 1;}
 | 
						|
			;
 | 
						|
named_expression	: NAME
 | 
						|
			    { $$ = lookup($1,SIMPLE); }
 | 
						|
			| NAME '[' expression ']'
 | 
						|
			    { $$ = lookup($1,ARRAY); }
 | 
						|
			| Ibase
 | 
						|
			    { $$ = 0; }
 | 
						|
			| Obase
 | 
						|
			    { $$ = 1; }
 | 
						|
			| Scale
 | 
						|
			    { $$ = 2; }
 | 
						|
			;
 | 
						|
 | 
						|
%%
 |