|
Packit |
70b277 |
/* This file is part of GNU bc.
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 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 3 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, see
|
|
Packit |
70b277 |
<http://www.gnu.org/licenses>.
|
|
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 |
/* bc.y: The grammar for a POSIX compatable bc processor with some
|
|
Packit |
70b277 |
extensions to the language. */
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
%{
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
#include "bcdefs.h"
|
|
Packit |
70b277 |
#include "global.h"
|
|
Packit |
70b277 |
#include "proto.h"
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
/* current function number. */
|
|
Packit |
70b277 |
int cur_func = -1;
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
/* Expression encoded information -- See comment at expression rules. */
|
|
Packit |
70b277 |
#define EX_ASSGN 0
|
|
Packit |
70b277 |
#define EX_REG 1
|
|
Packit |
70b277 |
#define EX_COMP 2
|
|
Packit |
70b277 |
#define EX_PAREN 4
|
|
Packit |
70b277 |
#define EX_VOID 8
|
|
Packit |
70b277 |
#define EX_EMPTY 16
|
|
Packit |
70b277 |
|
|
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 |
/* Extensions over POSIX bc.
|
|
Packit |
70b277 |
a) NAME was LETTER. This grammar allows longer names.
|
|
Packit |
70b277 |
Single letter names will still work.
|
|
Packit |
70b277 |
b) Relational_expression allowed only one comparison.
|
|
Packit |
70b277 |
This grammar has added boolean expressions with
|
|
Packit |
70b277 |
&& (and) || (or) and ! (not) and allowed all of them in
|
|
Packit |
70b277 |
full expressions.
|
|
Packit |
70b277 |
c) Added an else to the if.
|
|
Packit |
70b277 |
d) Call by variable array parameters
|
|
Packit |
70b277 |
e) read() procedure that reads a number under program control from stdin.
|
|
Packit |
70b277 |
f) halt statement that halts the the program under program control. It
|
|
Packit |
70b277 |
is an executed statement.
|
|
Packit |
70b277 |
g) continue statement for for loops.
|
|
Packit |
70b277 |
h) optional expressions in the for loop.
|
|
Packit |
70b277 |
i) print statement to print multiple numbers per line.
|
|
Packit |
70b277 |
j) warranty statement to print an extended warranty notice.
|
|
Packit |
70b277 |
k) limits statement to print the processor's limits.
|
|
Packit |
70b277 |
l) void functions.
|
|
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 |
/* '=', '+=', '-=', '*=', '/=', '%=', '^=' */
|
|
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 |
/* 'define', 'break', 'quit', 'length' */
|
|
Packit |
70b277 |
%token <i_value> Define Break Quit Length
|
|
Packit |
70b277 |
/* 'return', 'for', 'if', 'while', 'sqrt', 'else' */
|
|
Packit |
70b277 |
%token <i_value> Return For If While Sqrt Else
|
|
Packit |
70b277 |
/* 'scale', 'ibase', 'obase', 'auto', 'read', 'random' */
|
|
Packit |
70b277 |
%token <i_value> Scale Ibase Obase Auto Read Random
|
|
Packit |
70b277 |
/* 'warranty', 'halt', 'last', 'continue', 'print', 'limits' */
|
|
Packit |
70b277 |
%token <i_value> Warranty Halt Last Continue Print Limits
|
|
Packit |
70b277 |
/* 'history', 'void' */
|
|
Packit |
70b277 |
%token <i_value> UNARY_MINUS HistoryVar Void
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
/* Types of all other things. */
|
|
Packit |
70b277 |
%type <i_value> expression return_expression named_expression opt_expression
|
|
Packit |
70b277 |
%type <c_value> '+' '-' '*' '/' '%'
|
|
Packit |
70b277 |
%type <a_value> opt_parameter_list opt_auto_define_list define_list
|
|
Packit |
70b277 |
%type <a_value> opt_argument_list argument_list
|
|
Packit |
70b277 |
%type <i_value> program input_item semicolon_list statement_list
|
|
Packit |
70b277 |
%type <i_value> statement function statement_or_error required_eol
|
|
Packit |
70b277 |
%type <i_value> opt_void
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
/* precedence */
|
|
Packit |
70b277 |
%left OR
|
|
Packit |
70b277 |
%left AND
|
|
Packit |
70b277 |
%nonassoc NOT
|
|
Packit |
70b277 |
%left 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 |
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 |
opt_newline : /* empty */
|
|
Packit |
70b277 |
| ENDOFLINE
|
|
Packit |
70b277 |
{ ct_warn ("newline not allowed"); }
|
|
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_or_error
|
|
Packit |
70b277 |
| statement_list ENDOFLINE
|
|
Packit |
70b277 |
| statement_list ENDOFLINE statement_or_error
|
|
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 (""); }
|
|
Packit |
70b277 |
| Limits
|
|
Packit |
70b277 |
{ limits (); }
|
|
Packit |
70b277 |
| expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($1 & EX_COMP)
|
|
Packit |
70b277 |
ct_warn ("comparison in expression");
|
|
Packit |
70b277 |
if ($1 & EX_REG)
|
|
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 |
snprintf (genstr, genlen, "J%1d:",
|
|
Packit |
70b277 |
break_label);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| Continue
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
ct_warn ("Continue statement");
|
|
Packit |
70b277 |
if (continue_label == 0)
|
|
Packit |
70b277 |
yyerror ("Continue outside a for");
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "J%1d:",
|
|
Packit |
70b277 |
continue_label);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| Quit
|
|
Packit |
70b277 |
{ bc_exit (0); }
|
|
Packit |
70b277 |
| Halt
|
|
Packit |
70b277 |
{ generate ("h"); }
|
|
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 |
'(' opt_expression ';'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($4 & EX_COMP)
|
|
Packit |
70b277 |
ct_warn ("Comparison in first for expression");
|
|
Packit |
70b277 |
if ($4 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("first expression is void");
|
|
Packit |
70b277 |
if (!($4 & EX_EMPTY))
|
|
Packit |
70b277 |
generate ("p");
|
|
Packit |
70b277 |
$4 = next_label++;
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "N%1d:", $4);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
opt_expression ';'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($7 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("second expression is void");
|
|
Packit |
70b277 |
if ($7 & EX_EMPTY ) generate ("1");
|
|
Packit |
70b277 |
$7 = next_label++;
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "B%1d:J%1d:", $7,
|
|
Packit |
70b277 |
break_label);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
$<i_value>$ = continue_label;
|
|
Packit |
70b277 |
continue_label = next_label++;
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "N%1d:",
|
|
Packit |
70b277 |
continue_label);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
opt_expression ')'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($10 & EX_COMP)
|
|
Packit |
70b277 |
ct_warn ("Comparison in third for expression");
|
|
Packit |
70b277 |
if ($10 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("third expression is void");
|
|
Packit |
70b277 |
if ($10 & EX_EMPTY)
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "J%1d:N%1d:", $4, $7);
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "pJ%1d:N%1d:", $4, $7);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
opt_newline statement
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "J%1d:N%1d:",
|
|
Packit |
70b277 |
continue_label, break_label);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
break_label = $1;
|
|
Packit |
70b277 |
continue_label = $<i_value>9;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| If '(' expression ')'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($3 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("void expression");
|
|
Packit |
70b277 |
$3 = if_label;
|
|
Packit |
70b277 |
if_label = next_label++;
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "Z%1d:", if_label);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
opt_newline statement opt_else
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "N%1d:", if_label);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
if_label = $3;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| While
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
$1 = continue_label;
|
|
Packit |
70b277 |
continue_label = next_label++;
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "N%1d:",
|
|
Packit |
70b277 |
continue_label);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
'(' expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($4 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("void expression");
|
|
Packit |
70b277 |
$4 = break_label;
|
|
Packit |
70b277 |
break_label = next_label++;
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "Z%1d:", break_label);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
')' opt_newline statement
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "J%1d:N%1d:",
|
|
Packit |
70b277 |
continue_label, break_label);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
break_label = $4;
|
|
Packit |
70b277 |
continue_label = $1;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| '{' statement_list '}'
|
|
Packit |
70b277 |
{ $$ = 0; }
|
|
Packit |
70b277 |
| Print
|
|
Packit |
70b277 |
{ ct_warn ("print statement"); }
|
|
Packit |
70b277 |
print_list
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
print_list : print_element
|
|
Packit |
70b277 |
| print_element ',' print_list
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
print_element : STRING
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
generate ("O");
|
|
Packit |
70b277 |
generate ($1);
|
|
Packit |
70b277 |
free ($1);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($1 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("void expression in print");
|
|
Packit |
70b277 |
generate ("P");
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
opt_else : /* nothing */
|
|
Packit |
70b277 |
| Else
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
ct_warn ("else clause in if statement");
|
|
Packit |
70b277 |
$1 = next_label++;
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "J%d:N%1d:", $1,
|
|
Packit |
70b277 |
if_label);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
if_label = $1;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
opt_newline statement
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
function : Define opt_void NAME '(' opt_parameter_list ')' opt_newline
|
|
Packit |
70b277 |
'{' required_eol opt_auto_define_list
|
|
Packit |
70b277 |
{ char *params, *autos;
|
|
Packit |
70b277 |
/* Check auto list against parameter list? */
|
|
Packit |
70b277 |
check_params ($5,$10);
|
|
Packit |
70b277 |
params = arg_str ($5);
|
|
Packit |
70b277 |
autos = arg_str ($10);
|
|
Packit |
70b277 |
set_genstr_size (30 + strlen (params)
|
|
Packit |
70b277 |
+ strlen (autos));
|
|
Packit |
70b277 |
cur_func = lookup($3,FUNCTDEF);
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "F%d,%s.%s[", cur_func,
|
|
Packit |
70b277 |
params, autos);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
functions[cur_func].f_void = $2;
|
|
Packit |
70b277 |
free_args ($5);
|
|
Packit |
70b277 |
free_args ($10);
|
|
Packit |
70b277 |
$1 = next_label;
|
|
Packit |
70b277 |
next_label = 1;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
statement_list /* ENDOFLINE */ '}'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
generate ("0R]");
|
|
Packit |
70b277 |
next_label = $1;
|
|
Packit |
70b277 |
cur_func = -1;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
opt_void : /* empty */
|
|
Packit |
70b277 |
{ $$ = 0; }
|
|
Packit |
70b277 |
| Void
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
$$ = 1;
|
|
Packit |
70b277 |
ct_warn ("void functions");
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
opt_parameter_list : /* empty */
|
|
Packit |
70b277 |
{ $$ = NULL; }
|
|
Packit |
70b277 |
| define_list
|
|
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 |
| '*' NAME '[' ']'
|
|
Packit |
70b277 |
{ $$ = nextarg (NULL, lookup ($2,ARRAY), TRUE);
|
|
Packit |
70b277 |
ct_warn ("Call by variable arrays");
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| '&' NAME '[' ']'
|
|
Packit |
70b277 |
{ $$ = nextarg (NULL, lookup ($2,ARRAY), TRUE);
|
|
Packit |
70b277 |
ct_warn ("Call by variable arrays");
|
|
Packit |
70b277 |
}
|
|
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 |
| define_list ',' '*' NAME '[' ']'
|
|
Packit |
70b277 |
{ $$ = nextarg ($1, lookup ($4,ARRAY), TRUE);
|
|
Packit |
70b277 |
ct_warn ("Call by variable arrays");
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| define_list ',' '&' NAME '[' ']'
|
|
Packit |
70b277 |
{ $$ = nextarg ($1, lookup ($4,ARRAY), TRUE);
|
|
Packit |
70b277 |
ct_warn ("Call by variable arrays");
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
opt_argument_list : /* empty */
|
|
Packit |
70b277 |
{ $$ = NULL; }
|
|
Packit |
70b277 |
| argument_list
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
argument_list : expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($1 & EX_COMP)
|
|
Packit |
70b277 |
ct_warn ("comparison in argument");
|
|
Packit |
70b277 |
if ($1 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("void argument");
|
|
Packit |
70b277 |
$$ = nextarg (NULL,0,FALSE);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| NAME '[' ']'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "K%d:",
|
|
Packit |
70b277 |
-lookup ($1,ARRAY));
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
$$ = nextarg (NULL,1,FALSE);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| argument_list ',' expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($3 & EX_COMP)
|
|
Packit |
70b277 |
ct_warn ("comparison in argument");
|
|
Packit |
70b277 |
if ($3 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("void argument");
|
|
Packit |
70b277 |
$$ = nextarg ($1,0,FALSE);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| argument_list ',' NAME '[' ']'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "K%d:",
|
|
Packit |
70b277 |
-lookup ($3,ARRAY));
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
$$ = nextarg ($1,1,FALSE);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
/* Expression lval meanings! (Bits mean something!) (See defines above)
|
|
Packit |
70b277 |
* 0 => Top op is assignment.
|
|
Packit |
70b277 |
* 1 => Top op is not assignment.
|
|
Packit |
70b277 |
* 2 => Comparison is somewhere in expression.
|
|
Packit |
70b277 |
* 4 => Expression is in parenthesis.
|
|
Packit |
70b277 |
* 8 => Expression is void!
|
|
Packit |
70b277 |
* 16 => Empty optional expression.
|
|
Packit |
70b277 |
*/
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
opt_expression : /* empty */
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
$$ = EX_EMPTY;
|
|
Packit |
70b277 |
ct_warn ("Missing expression in for statement");
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| expression
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
return_expression : /* empty */
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
$$ = 0;
|
|
Packit |
70b277 |
generate ("0");
|
|
Packit |
70b277 |
if (cur_func == -1)
|
|
Packit |
70b277 |
yyerror("Return outside of a function.");
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($1 & EX_COMP)
|
|
Packit |
70b277 |
ct_warn ("comparison in return expresion");
|
|
Packit |
70b277 |
if (!($1 & EX_PAREN))
|
|
Packit |
70b277 |
ct_warn ("return expression requires parenthesis");
|
|
Packit |
70b277 |
if ($1 & EX_VOID)
|
|
Packit |
70b277 |
yyerror("return requires non-void expression");
|
|
Packit |
70b277 |
if (cur_func == -1)
|
|
Packit |
70b277 |
yyerror("Return outside of a function.");
|
|
Packit |
70b277 |
else if (functions[cur_func].f_void)
|
|
Packit |
70b277 |
yyerror("Return expression in a void function.");
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
expression : named_expression ASSIGN_OP
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($2 != '=')
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($1 < 0)
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "DL%d:", -$1);
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "l%d:", $1);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($4 & EX_ASSGN)
|
|
Packit |
70b277 |
ct_warn("comparison in assignment");
|
|
Packit |
70b277 |
if ($4 & EX_VOID)
|
|
Packit |
70b277 |
yyerror("Assignment of a void expression");
|
|
Packit |
70b277 |
if ($2 != '=')
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "%c", $2);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
if ($1 < 0)
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "S%d:", -$1);
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "s%d:", $1);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
$$ = EX_ASSGN;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| expression AND
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
ct_warn("&& operator");
|
|
Packit |
70b277 |
$2 = next_label++;
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "DZ%d:p", $2);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if (($1 & EX_VOID) || ($4 & EX_VOID))
|
|
Packit |
70b277 |
yyerror ("void expression with &&";;
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "DZ%d:p1N%d:", $2, $2);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
$$ = ($1 | $4) & ~EX_PAREN;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| expression OR
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
ct_warn("|| operator");
|
|
Packit |
70b277 |
$2 = next_label++;
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "B%d:", $2);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
int tmplab;
|
|
Packit |
70b277 |
if (($1 & EX_VOID) || ($4 & EX_VOID))
|
|
Packit |
70b277 |
yyerror ("void expression with ||");
|
|
Packit |
70b277 |
tmplab = next_label++;
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "B%d:0J%d:N%d:1N%d:",
|
|
Packit |
70b277 |
$2, tmplab, $2, tmplab);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
$$ = ($1 | $4) & ~EX_PAREN;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| NOT expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($2 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("void expression with !");
|
|
Packit |
70b277 |
$$ = $2 & ~EX_PAREN;
|
|
Packit |
70b277 |
ct_warn("! operator");
|
|
Packit |
70b277 |
generate ("!");
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| expression REL_OP expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
|
Packit |
70b277 |
yyerror ("void expression with comparison");
|
|
Packit |
70b277 |
$$ = EX_REG | EX_COMP;
|
|
Packit |
70b277 |
switch (*($2))
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
case '=':
|
|
Packit |
70b277 |
generate ("=");
|
|
Packit |
70b277 |
break;
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
case '!':
|
|
Packit |
70b277 |
generate ("#");
|
|
Packit |
70b277 |
break;
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
case '<':
|
|
Packit |
70b277 |
if ($2[1] == '=')
|
|
Packit |
70b277 |
generate ("{");
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
generate ("<");
|
|
Packit |
70b277 |
break;
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
case '>':
|
|
Packit |
70b277 |
if ($2[1] == '=')
|
|
Packit |
70b277 |
generate ("}");
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
generate (">");
|
|
Packit |
70b277 |
break;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
free($2);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| expression '+' expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
|
Packit |
70b277 |
yyerror ("void expression with +");
|
|
Packit |
70b277 |
generate ("+");
|
|
Packit |
70b277 |
$$ = ($1 | $3) & ~EX_PAREN;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| expression '-' expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
|
Packit |
70b277 |
yyerror ("void expression with -");
|
|
Packit |
70b277 |
generate ("-");
|
|
Packit |
70b277 |
$$ = ($1 | $3) & ~EX_PAREN;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| expression '*' expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
|
Packit |
70b277 |
yyerror ("void expression with *");
|
|
Packit |
70b277 |
generate ("*");
|
|
Packit |
70b277 |
$$ = ($1 | $3) & ~EX_PAREN;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| expression '/' expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
|
Packit |
70b277 |
yyerror ("void expression with /");
|
|
Packit |
70b277 |
generate ("/");
|
|
Packit |
70b277 |
$$ = ($1 | $3) & ~EX_PAREN;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| expression '%' expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
|
Packit |
70b277 |
yyerror ("void expression with %");
|
|
Packit |
70b277 |
generate ("%");
|
|
Packit |
70b277 |
$$ = ($1 | $3) & ~EX_PAREN;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| expression '^' expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
|
Packit |
70b277 |
yyerror ("void expression with ^");
|
|
Packit |
70b277 |
generate ("^");
|
|
Packit |
70b277 |
$$ = ($1 | $3) & ~EX_PAREN;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| '-' expression %prec UNARY_MINUS
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($2 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("void expression with unary -");
|
|
Packit |
70b277 |
generate ("n");
|
|
Packit |
70b277 |
$$ = $2 & ~EX_PAREN;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| named_expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
$$ = EX_REG;
|
|
Packit |
70b277 |
if ($1 < 0)
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "L%d:", -$1);
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "l%d:", $1);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| NUMBER
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
int len = strlen($1);
|
|
Packit |
70b277 |
$$ = EX_REG;
|
|
Packit |
70b277 |
if (len == 1 && *$1 == '0')
|
|
Packit |
70b277 |
generate ("0");
|
|
Packit |
70b277 |
else 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 |
| '(' expression ')'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($2 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("void expression in parenthesis");
|
|
Packit |
70b277 |
$$ = $2 | EX_REG | EX_PAREN;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| NAME '(' opt_argument_list ')'
|
|
Packit |
70b277 |
{ int fn;
|
|
Packit |
70b277 |
fn = lookup ($1,FUNCT);
|
|
Packit |
70b277 |
if (functions[fn].f_void)
|
|
Packit |
70b277 |
$$ = EX_VOID;
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
$$ = EX_REG;
|
|
Packit |
70b277 |
if ($3 != NULL)
|
|
Packit |
70b277 |
{ char *params = call_str ($3);
|
|
Packit |
70b277 |
set_genstr_size (20 + strlen (params));
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "C%d,%s:", fn,
|
|
Packit |
70b277 |
params);
|
|
Packit |
70b277 |
free_args ($3);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "C%d:", fn);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| INCR_DECR named_expression
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
$$ = EX_REG;
|
|
Packit |
70b277 |
if ($2 < 0)
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($1 == '+')
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "DA%d:L%d:", -$2, -$2);
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "DM%d:L%d:", -$2, -$2);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($1 == '+')
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "i%d:l%d:", $2, $2);
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "d%d:l%d:", $2, $2);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| named_expression INCR_DECR
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
$$ = EX_REG;
|
|
Packit |
70b277 |
if ($1 < 0)
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "DL%d:x", -$1);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
if ($2 == '+')
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "A%d:", -$1);
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "M%d:", -$1);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "l%d:", $1);
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
if ($2 == '+')
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "i%d:", $1);
|
|
Packit |
70b277 |
else
|
|
Packit |
70b277 |
snprintf (genstr, genlen, "d%d:", $1);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
generate (genstr);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| Length '(' expression ')'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($3 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("void expression in length()");
|
|
Packit |
70b277 |
generate ("cL");
|
|
Packit |
70b277 |
$$ = EX_REG;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| Sqrt '(' expression ')'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($3 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("void expression in sqrt()");
|
|
Packit |
70b277 |
generate ("cR");
|
|
Packit |
70b277 |
$$ = EX_REG;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| Scale '(' expression ')'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($3 & EX_VOID)
|
|
Packit |
70b277 |
yyerror ("void expression in scale()");
|
|
Packit |
70b277 |
generate ("cS");
|
|
Packit |
70b277 |
$$ = EX_REG;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| Read '(' ')'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
ct_warn ("read function");
|
|
Packit |
70b277 |
generate ("cI");
|
|
Packit |
70b277 |
$$ = EX_REG;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| Random '(' ')'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
ct_warn ("random function");
|
|
Packit |
70b277 |
generate ("cX");
|
|
Packit |
70b277 |
$$ = EX_REG;
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
named_expression : NAME
|
|
Packit |
70b277 |
{ $$ = lookup($1,SIMPLE); }
|
|
Packit |
70b277 |
| NAME '[' expression ']'
|
|
Packit |
70b277 |
{
|
|
Packit |
70b277 |
if ($3 & EX_VOID)
|
|
Packit |
70b277 |
yyerror("void expression as subscript");
|
|
Packit |
70b277 |
if ($3 & EX_COMP)
|
|
Packit |
70b277 |
ct_warn("comparison in subscript");
|
|
Packit |
70b277 |
$$ = lookup($1,ARRAY);
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| Ibase
|
|
Packit |
70b277 |
{ $$ = 0; }
|
|
Packit |
70b277 |
| Obase
|
|
Packit |
70b277 |
{ $$ = 1; }
|
|
Packit |
70b277 |
| Scale
|
|
Packit |
70b277 |
{ $$ = 2; }
|
|
Packit |
70b277 |
| HistoryVar
|
|
Packit |
70b277 |
{ $$ = 3;
|
|
Packit |
70b277 |
ct_warn ("History variable");
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
| Last
|
|
Packit |
70b277 |
{ $$ = 4;
|
|
Packit |
70b277 |
ct_warn ("Last variable");
|
|
Packit |
70b277 |
}
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
required_eol : { ct_warn ("End of line required"); }
|
|
Packit |
70b277 |
| ENDOFLINE
|
|
Packit |
70b277 |
| required_eol ENDOFLINE
|
|
Packit |
70b277 |
{ ct_warn ("Too many end of lines"); }
|
|
Packit |
70b277 |
;
|
|
Packit |
70b277 |
|
|
Packit |
70b277 |
%%
|