home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BURKS 2
/
BURKS_AUG97.ISO
/
BURKS
/
SOFTWARE
/
SOURCES
/
MAWK11AS.ZIP
/
PARSE.Y
(
.txt
)
< prev
next >
Wrap
Text File
|
1992-01-08
|
35KB
|
1,264 lines
/********************************************
parse.y
copyright 1991, Michael D. Brennan
This is a source file for mawk, an implementation of
the AWK programming language.
Mawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
********************************************/
/* $Log: parse.y,v $
* Revision 5.2 92/01/08 16:11:42 brennan
* code FE_PUSHA carefully for MSDOS large mode
*
* Revision 5.1 91/12/05 07:50:22 brennan
* 1.1 pre-release
*
*/
%{
#include <stdio.h>
#include "mawk.h"
#include "code.h"
#include "symtype.h"
#include "memory.h"
#include "bi_funct.h"
#include "bi_vars.h"
#include "jmp.h"
#include "field.h"
#include "files.h"
#ifdef YYXBYACC
#define YYBYACC 1
#endif
#define YYMAXDEPTH 200
/* Bison's use of MSDOS and ours clashes */
#undef MSDOS
extern void PROTO( eat_nl, (void) ) ;
static void PROTO( resize_fblock, (FBLOCK *, INST *) ) ;
static void PROTO( code_array, (SYMTAB *) ) ;
static void PROTO( code_call_id, (CA_REC *, SYMTAB *) ) ;
static void PROTO( field_A2I, (void)) ;
static int PROTO( current_offset, (void) ) ;
static void PROTO( check_var, (SYMTAB *) ) ;
static void PROTO( check_array, (SYMTAB *) ) ;
static void PROTO( RE_as_arg, (void)) ;
static int scope ;
static FBLOCK *active_funct ;
/* when scope is SCOPE_FUNCT */
#define code_address(x) if( is_local(x) )\
{ code1(L_PUSHA) ; code1((x)->offset) ; }\
else code2(_PUSHA, (x)->stval.cp)
/* this nonsense caters to MSDOS large model */
#define CODE_FE_PUSHA() code_ptr->ptr = (PTR) 0 ; code1(FE_PUSHA)
%}
%union{
CELL *cp ;
SYMTAB *stp ;
INST *start ; /* code starting address */
PF_CP fp ; /* ptr to a (print/printf) or (sub/gsub) function */
BI_REC *bip ; /* ptr to info about a builtin */
FBLOCK *fbp ; /* ptr to a function block */
ARG2_REC *arg2p ;
CA_REC *ca_p ;
int ival ;
PTR ptr ;
}
/* two tokens to help with errors */
%token UNEXPECTED /* unexpected character */
%token BAD_DECIMAL
%token NL
%token SEMI_COLON
%token LBRACE RBRACE
%token LBOX RBOX
%token COMMA
%token <ival> IO_OUT /* > or output pipe */
%right ASSIGN ADD_ASG SUB_ASG MUL_ASG DIV_ASG MOD_ASG POW_ASG
%right QMARK COLON
%left OR
%left AND
%left IN
%left <ival> MATCH /* ~ or !~ */
%left EQ NEQ LT LTE GT GTE
%left CAT
%left GETLINE
%left PLUS MINUS
%left MUL DIV MOD
%left NOT UMINUS
%nonassoc IO_IN PIPE
%right POW
%left <ival> INC_or_DEC
%left DOLLAR FIELD /* last to remove a SR conflict
with getline */
%right LPAREN RPAREN /* removes some SR conflicts */
%token <ptr> DOUBLE STRING_ RE
%token <stp> ID D_ID
%token <fbp> FUNCT_ID
%token <bip> BUILTIN
%token <cp> FIELD
%token PRINT PRINTF SPLIT MATCH_FUNC SUB GSUB
/* keywords */
%token DO WHILE FOR BREAK CONTINUE IF ELSE IN
%token DELETE BEGIN END EXIT NEXT RETURN FUNCTION
%type <start> block block_or_separator
%type <start> statement_list statement mark
%type <ival> pr_args
%type <arg2p> arg2
%type <start> builtin
%type <start> getline_file
%type <start> lvalue field fvalue
%type <start> expr cat_expr p_expr
%type <start> while_front if_front
%type <start> for1 for2
%type <start> array_loop_front
%type <start> return_statement
%type <start> split_front re_arg sub_back
%type <ival> arglist args
%type <fp> print sub_or_gsub
%type <fbp> funct_start funct_head
%type <ca_p> call_args ca_front ca_back
%type <ival> f_arglist f_args
%%
/* productions */
program : program_block
| program program_block
;
program_block : PA_block /* pattern-action */
| function_def
| error block
{ if (scope == SCOPE_FUNCT)
{ restore_ids() ; scope = SCOPE_MAIN ; }
code_ptr = main_code_ptr ;
}
;
PA_block : block
{ /* this do nothing action removes a vacuous warning
from Bison */
}
| BEGIN
{
be_expand(&begin_code) ;
scope = SCOPE_BEGIN ;
}
block
{ be_shrink(&begin_code) ;
scope = SCOPE_MAIN ;
}
| END
{
be_expand(&end_code) ;
scope = SCOPE_END ;
}
block
{ be_shrink(&end_code) ;
scope = SCOPE_MAIN ;
}
| expr /* this works just like an if statement */
{ code_jmp(_JZ, (INST*)0) ; }
block_or_separator
{ patch_jmp( code_ptr ) ; }
/* range pattern, see comment in execute.c near _RANGE */
| expr COMMA
{ code_push($1, code_ptr - $1) ;
code_ptr = $1 ;
code1(_RANGE) ; code1(1) ;
code_ptr += 3 ;
code_ptr += code_pop(code_ptr) ;
code1(_STOP) ;
$1[2].op = code_ptr - ($1+1) ;
}
expr
{ code1(_STOP) ; }
block_or_separator
{ $1[3].op = $6 - ($1+1) ;
$1[4].op = code_ptr - ($1+1) ;
}
;
block : LBRACE statement_list RBRACE
{ $$ = $2 ; }
| LBRACE error RBRACE
{ $$ = code_ptr ; /* does nothing won't be executed */
print_flag = getline_flag = paren_cnt = 0 ;
yyerrok ; }
;
block_or_separator : block
| separator /* default print action */
{ $$ = code_ptr ;
code1(_PUSHINT) ; code1(0) ;
code2(_PRINT, bi_print) ;
}
statement_list : statement
| statement_list statement
;
statement : block
| expr separator
{ code1(_POP) ; }
| /* empty */ separator
{ $$ = code_ptr ; }
| error separator
{ $$ = code_ptr ;
print_flag = getline_flag = 0 ;
paren_cnt = 0 ;
yyerrok ;
}
| BREAK separator
{ $$ = code_ptr ; BC_insert('B', code_ptr+1) ;
code2(_JMP, 0) /* don't use code_jmp ! */ ; }
| CONTINUE separator
{ $$ = code_ptr ; BC_insert('C', code_ptr+1) ;
code2(_JMP, 0) ; }
| return_statement
{ if ( scope != SCOPE_FUNCT )
compile_error("return outside function body") ;
}
| NEXT separator
{ if ( scope != SCOPE_MAIN )
compile_error( "improper use of next" ) ;
$$ = code_ptr ;
code1(_NEXT) ;
}
;
separator : NL | SEMI_COLON
;
expr : cat_expr
| lvalue ASSIGN expr { code1(_ASSIGN) ; }
| lvalue ADD_ASG expr { code1(_ADD_ASG) ; }
| lvalue SUB_ASG expr { code1(_SUB_ASG) ; }
| lvalue MUL_ASG expr { code1(_MUL_ASG) ; }
| lvalue DIV_ASG expr { code1(_DIV_ASG) ; }
| lvalue MOD_ASG expr { code1(_MOD_ASG) ; }
| lvalue POW_ASG expr { code1(_POW_ASG) ; }
| expr EQ expr { code1(_EQ) ; }
| expr NEQ expr { code1(_NEQ) ; }
| expr LT expr { code1(_LT) ; }
| expr LTE expr { code1(_LTE) ; }
| expr GT expr { code1(_GT) ; }
| expr GTE expr { code1(_GTE) ; }
| expr MATCH expr
{
if ( $3 == code_ptr - 2 )
{
if ( $3->op == _MATCH0 ) $3->op = _MATCH1 ;
else /* check for string */
i