                                                               
// Grammar for RZ language	    			1 May 2001

// fix bug if, unary minus in item, change symtab  	23 Dec 2001
// change to one pass  					3 Jan 2002
// change syntax for variable declare name, ... ;  	24 Sept 2002
// lot of modifications to untangle parsing parameters
//   in function call        				6 Oct 2010
// change to generate parse tree			20 Oct 2010
// rz-grammar9    simplify expr       			23 Oct 2010
// add def, mod, shl, shr, syscall()			8 Feb 2013

"// parser generated from rz-grammar"
"#include <compile.h>"
"#include <parse.h>"
"extern int pv;"

pass = dcl pass | tkEOF %

// declaration is
//   - function definition    f(arg){ body }
//   - variable declaration   a, b, c[12] ... ;
//   - define constant        def name value ;
//   - define macro           def f(arg){ body }

dcl = 
  tkIDEN "pusht(tokstring);" dcl2 | 
  tkDEF tkIDEN "pusht(tokstring);" def %

def = 
  tkNUMBER "doconst();" tkSEMI |
  tkLPAREN "pv=0;" formal tkRPAREN "setfun(popt());" stmt "domac();" %

dcl2 [ n ] =
  tkLPAREN "pv=0;" formal tkRPAREN "setfun(popt());" stmt "dofun();" |
  tkLBRACKET tkNUMBER "n=atoi(tokstring);" tkRBRACKET "putvec(popt(),n);" dcl3 |
  tkCOMMA "putvar(popt());" |
  tkSEMI "putvar(popt());" %

dcl3 = tkCOMMA | tkSEMI % 

formal = tkIDEN "doLocal();" formals | nil %
formals = tkCOMMA formal | nil %

stmt = block | stmt1 %
stmts = stmt1 stmts | nil "doblock();" %
block = tkLBRACE "ypush(MARK);" stmts tkRBRACE %

//  statement is 
//    - ;
//    - if( expr ) stmt else_stmt optional
//    - while( expr ) stmt
//    - return expr ;
//    - print( ... ) ;
//    - syscall( num , expr ) ;
//    - *name = expr ;
//    - name = expr ;
//    - name[ expr ] = expr ; 
//    - name( ... ) ;    function call

stmt1 [ n ] =
  tkSEMI "ypush(NIL);" |
  tkIF tkLPAREN expr tkRPAREN stmt elsest |
  tkWHILE tkLPAREN expr tkRPAREN stmt "dowhile();" |
  tkRETURN returnst |
  tkPRINT tkLPAREN "ypush(MARK);" prlist tkRPAREN tkSEMI "doprint();" |
  tkSYSCALL tkLPAREN tkNUMBER "n = atoi(tokstring);" 
    tkCOMMA expr tkRPAREN tkSEMI "dosys(n);" |
  tkSTAR tkIDEN "dovar(tokstring);douop(tkDEREF);" tkEQ expr tkSEMI "doset();" |
  tkIDEN "pusht(tokstring);" stmt2 %

elsest = 
  tkELSE stmt "doifelse();" | 
  nil "doif();" %
returnst =
  tkSEMI "ypush(NIL); doreturn();" |
  expr tkSEMI "doreturn();" %

prlist = 
  tkSTRING "dostring();" prlists |
  expr prlists %
prlists = tkCOMMA prlist | nil %

stmt2 =
  tkEQ "dovar(popt());" expr tkSEMI "doset();" |
  tkLBRACKET expr tkRBRACKET tkEQ "dovec(popt());" expr tkSEMI "doset();" |
  tkLPAREN "ypush(MARK);" param tkRPAREN tkSEMI "docall(popt());" %

param = expr params | nil %
params = tkCOMMA param | nil %

//  an expression is
//   - term op term op . . . term
//   - unary: - ! * &
//   - term: number, name, name[expr], name(...)
//   - ( expr ) parenthesis has highest precedence

expr = term "zpush(tkBOT);" exprs %
exprs = bop term exprs | nil "zclean();" %

bop = 
  tkOROR "zop(tok);" | tkANDAND "zop(tok);" | 
  tkLT "zop(tok);"   | tkLE "zop(tok);" | 
  tkEQEQ "zop(tok);" | tkNE "zop(tok);" |
  tkGE "zop(tok);"   | tkGT "zop(tok);" | 
  tkPLUS "zop(tok);" | tkMINUS "zop(tok);" | 
  tkSTAR "zop(tok);" | tkSLASH "zop(tok);" |
  tkLTLT "zop(tok);" | tkGTGT "zop(tok);" |  
  tkMOD "zop(tok);" %

// do uop first
term =
  tkMINUS term1 "douop(tkMINUS);" |
  tkNOT term1 "douop(tkUNOT);" |
  tkSTAR term1 "douop(tkDEREF);" |
  tkAND tkIDEN "pusht(tokstring);" index "douop(tkADS);" |  
  term1 %

term1 =
  tkIDEN "pusht(tokstring);" mod |
  tkNUMBER "donum(tokstring);" |
  tkSTRING "dostring();" |
  tkLPAREN expr tkRPAREN %

// function call or vector
mod =
  tkLPAREN "ypush(MARK);" param tkRPAREN "docall(popt());" |
  index %

index =
  tkLBRACKET expr tkRBRACKET "dovec(popt());" |
  nil "dovar(popt());" %

// end 