                                                               
// This is LL(1) grammar for RZ language    1 May 2001
// fix bug if in stmt, unary minus in item, change symtab  23 Dec 2001
// change to one pass  3 Jan 2002
// change syntax for variable declare name, 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
  
"// parser generated from rz-grammar 17 Oct 2010"
"#include <compile.h>"
"#include <parse.h>"
"extern int lv, CP;"
"extern int DS;"
"int pv;"

pass = dcl pass | tkEOF %

// declaration is
//   - function definition    f(arg){ body }
//   - variable declaration   a, b, c[12] ... ;

dcl = tkIDEN "pusht(tokstring);" dcl2 %
dcl2 [ n ] =
  tkLPAREN "pv=0;" formal tkRPAREN "setFunc(popt(),pv);" stmt "dofun();" |
  tkLBRACKET tkNUMBER "n=atoi(tokstring);" tkRBRACKET 
    "putSym(popt(),tyVECTOR,DS,n); DS+=n;" dcl3 | 
  tkCOMMA "putSym(popt(),tySCALAR,DS,1); DS++;" |
  tkSEMI "putSym(popt(),tySCALAR,DS,1); DS++;" %

dcl3 = tkCOMMA | tkSEMI % 

formal = tkIDEN "doLocal(); pv++;" 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( ... ) ;
//    - *name = expr ;
//    - name = expr ;
//    - name[ expr ] = expr ; 
//    - name( ... ) ;    function call

stmt1 =
  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();" |
//  tkSTAR tkIDEN "doRval(tokstring);" tkEQ expr tkSEMI "out(icSet);" |
  tkIDEN "pusht(tokstring);" stmt2 %

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

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

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 %
params = tkCOMMA param | nil %

//  an expression is
//   - term op term op . . . term
//   - precedence of op: (highest) unary * / + - compare && ||
//   - compare: lt le eq neq ge gt
//   - unary: - ! * &
//   - term: number, name, name[expr], name(...)
//   - ( expr )    parenthesis has highest precedence

expr = f4 exprs %
exprs = 
  tkOROR "ypush(tok);" f4 "dobop();" exprs |
  tkANDAND "ypush(tok);" f4 "dobop();" exprs |
  nil %

f4 = f3 logic %
logic =  
  tkLT "ypush(tok);" f3 "dobop();" logic |
  tkLE "ypush(tok);" f3 "dobop();" logic |
  tkEQEQ "ypush(tok);" f3 "dobop();" logic |
  tkNE "ypush(tok);" f3 "dobop();" logic |
  tkGE "ypush(tok);" f3 "dobop();" logic |
  tkGT "ypush(tok);" f3 "dobop();" logic |
  nil %

f3 = f2 addsub %
addsub =
  tkPLUS "ypush(tok);" f2 "dobop();" addsub |
  tkMINUS "ypush(tok);" f2 "dobop();" addsub |
  nil %

f2 = f1 muldiv %
muldiv = 
  tkSTAR "ypush(tok);" f1 "dobop();" muldiv |
  tkSLASH "ypush(tok);" f1 "dobop();" muldiv |
  nil %

// cannot do -fun(.)
f1 =
  tkMINUS "ypush(tok);" term "domuop();" |
  tkNOT "ypush(tok);" term "douop();" |
  tkSTAR "ypush(tok);" term "douop();" |
  tkAND "ypush(tok);" tkIDEN "pusht(tokstring);" mod2 |  
  term %

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

mod =
  tkLBRACKET expr tkRBRACKET "dovec(popt());" |
  tkLPAREN "ypush(MARK);" param tkRPAREN "docall(popt());" |
  nil "dovar(popt());" %

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

// end 