diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /gnu/usr.bin/bc/sbc.y |
initial import of NetBSD tree
Diffstat (limited to 'gnu/usr.bin/bc/sbc.y')
-rw-r--r-- | gnu/usr.bin/bc/sbc.y | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/gnu/usr.bin/bc/sbc.y b/gnu/usr.bin/bc/sbc.y new file mode 100644 index 00000000000..7e6e5b00e25 --- /dev/null +++ b/gnu/usr.bin/bc/sbc.y @@ -0,0 +1,450 @@ +%{ +/* $NetBSD: sbc.y,v 1.2 1994/12/02 00:43:40 phil Exp $ */ + +/* 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, 1993, 1994 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; } + ; + +%% |