summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/bc/sbc.y
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /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.y450
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; }
+ ;
+
+%%