-(* L3 Compiler
- * L3 grammar
+(* L4 Compiler
+ * L4 grammar
* Author: Kaustuv Chaudhuri <kaustuv+@cs.cmu.edu>
* Modified: Frank Pfenning <fp@cs.cmu.edu>
* Modified: Joshua Wise <jwise@andrew.cmu.edu>
*)
structure A = Ast
+structure AU = AstUtils
+structure AUP = AstUtils.Program
(* for simplicity, we only mark expressions, not statements *)
(* mark e with region (left, right) in source file *)
fun mark (e, (left, right)) = A.Marked (Mark.mark' (e, ParseState.ext (left, right)))
fun markstm (e, (left, right)) = A.MarkedStm (Mark.mark' (e, ParseState.ext (left, right)))
+fun markfunction (e, (left, right)) = A.MarkedFunction (Mark.mark' (e, ParseState.ext (left, right)))
+fun marktypedef (e, (left, right)) = A.MarkedTypedef (Mark.mark' (e, ParseState.ext (left, right)))
(* create lval from expression; here just an id *)
(* generates error if not an identifier *)
| make_lval _ ext = ( ErrorMsg.error ext "not a variable" ;
Symbol.bogus )
-(* expand_asnop (exp1, "op=", exp2) region = "exp1 = exp1 op exps"
- * or = "exp1 = exp2" if asnop is "="
- * generates error if exp1 is an lval (identifier)
- * syntactically expands a compound assignment operator
- *)
-fun expand_asnop (exp1, NONE, exp2) (left, right) =
- A.Assign(make_lval exp1 NONE, exp2)
- | expand_asnop (exp1, SOME(oper), exp2) (left, right) =
- A.Assign(make_lval exp1 NONE,
- mark(A.OpExp(oper, [exp1, exp2]), (left, right)))
-
%%
-%header (functor L3LrValsFn (structure Token : TOKEN))
+%header (functor L4LrValsFn (structure Token : TOKEN))
%term
EOF
| LBRACE | RBRACE
| LPAREN | RPAREN
| UNARY | ASNOP (* dummy *)
- | EXTERN | VAR | INT | COLON | COMMA
+ | EXTERN | VAR | INT | COLON | COMMA | STRUCT | NULL | LBRACKET | RBRACKET | ARROW | DOT | NEW
%nonterm
program of A.program
+ | programx of A.program
| stms of A.stm list
| stm of A.stm
| simp of A.stm
| exp of A.exp
| explist of A.exp list
| control of A.stm
- | asnop of A.oper option
+ | asnop of A.oper
| block of A.stm list
| simpoption of A.stm option
| elseoption of A.stm list option
| idents of A.ident list
| vtype of A.vtype
- | extdecls of A.function list
- | extdecl of A.function
+ | decls of A.program
+ | extdecl of A.ident * A.function
| paramlist of A.variable list
| param of A.variable
- | functions of A.function list
- | function of A.function
+ | typedecl of A.ident * A.typedef
+ | memberlist of (A.ident * A.vtype) list
+ | member of (A.ident * A.vtype)
+ | function of A.ident * A.function
| vardecl of A.variable list
| vardecls of A.variable list
%eop EOF
%noshift EOF
-%name L3
+%name L4
%left LOGOR
%left LOGAND
%left PLUS MINUS
%left STAR SLASH PERCENT
%right UNARY
-%left LPAREN
+%left LPAREN LBRACKET ARROW DOT
%%
-program : extdecls functions (extdecls @ functions)
+program : programx (programx)
+
+programx : decls (decls)
+ | programx function (AUP.append_function programx function)
vtype : INT (A.Int)
+ | IDENT (A.Typedef IDENT)
+ | vtype STAR (A.Pointer vtype)
+ | vtype LBRACKET RBRACKET
+ (A.Array vtype)
-extdecls : ([])
- | extdecl extdecls (extdecl :: extdecls)
+decls : (Symbol.empty, Symbol.empty)
+ | typedecl decls (AUP.append_typedef decls typedecl)
+ | extdecl decls (AUP.append_function decls extdecl)
extdecl : EXTERN vtype IDENT LPAREN RPAREN SEMI
- (A.Extern (vtype, IDENT, []))
- | EXTERN vtype IDENT LPAREN param RPAREN SEMI
- (A.Extern (vtype, IDENT, [param]))
+ (IDENT, markfunction (A.Extern (vtype, []), (EXTERNleft, SEMIright)))
| EXTERN vtype IDENT LPAREN paramlist RPAREN SEMI
- (A.Extern (vtype, IDENT, paramlist))
+ (IDENT, markfunction (A.Extern (vtype, paramlist), (EXTERNleft, SEMIright)))
paramlist : param COMMA paramlist (param :: paramlist)
| param ([param])
param : IDENT COLON vtype (IDENT, vtype)
-functions : ([])
- | function functions (function :: functions)
+typedecl : STRUCT IDENT LBRACE RBRACE SEMI
+ (IDENT, marktypedef (A.Struct ([]), (STRUCTleft, SEMIright)))
+ | STRUCT IDENT LBRACE memberlist RBRACE SEMI
+ (IDENT, marktypedef (A.Struct (memberlist), (STRUCTleft, SEMIright)))
+
+memberlist : member memberlist (member :: memberlist)
+ | member ([member])
+
+member : IDENT COLON vtype SEMI (IDENT, vtype)
-function : vtype IDENT LPAREN RPAREN LBRACE vardecls stms RBRACE
- (A.Function (vtype, IDENT, [], vardecls, stms))
- | vtype IDENT LPAREN paramlist RPAREN LBRACE vardecls stms RBRACE
- (A.Function (vtype, IDENT, paramlist, vardecls, stms))
+function : vtype IDENT LPAREN paramlist RPAREN LBRACE vardecls stms RBRACE
+ (IDENT, markfunction (A.Function (vtype, paramlist, vardecls, stms), (vtypeleft, RBRACEright)))
+ | vtype IDENT LPAREN RPAREN LBRACE vardecls stms RBRACE
+ (IDENT, markfunction (A.Function (vtype, [], vardecls, stms), (vtypeleft, RBRACEright)))
vardecls : ([])
| vardecl vardecls (vardecl @ vardecls)
| control (control)
| SEMI (A.Nop)
-simp : exp asnop exp %prec ASNOP
- (expand_asnop (exp1, asnop, exp2) (exp1left, exp2right))
+simp : exp ASSIGN exp %prec ASNOP
+ (A.Assign(exp1, exp2))
+ | exp asnop exp %prec ASNOP
+ (A.AsnOp(asnop, exp1, exp2))
+ | exp (markstm (A.Effect (exp), (expleft, expright)))
control : IF LPAREN exp RPAREN block elseoption
(markstm ((A.If (exp, block, elseoption)), (IFleft, elseoptionright)))
exp : LPAREN exp RPAREN (exp)
| INTNUM (mark (A.ConstExp(INTNUM),(INTNUMleft,INTNUMright)))
| IDENT (mark (A.Var(IDENT), (IDENTleft,IDENTright)))
+ | exp DOT IDENT (mark (A.Member(exp, IDENT), (expleft, IDENTright)))
+ | exp ARROW IDENT (mark (A.DerefMember(exp, IDENT), (expleft, IDENTright)))
+ | STAR exp %prec UNARY (mark (A.Dereference(exp), (STARleft, expright)))
+ | exp LBRACKET exp RBRACKET
+ (mark (A.ArrIndex(exp1, exp2), (exp1left, exp2right)))
| exp PLUS exp (mark (A.OpExp (A.PLUS, [exp1,exp2]), (exp1left,exp2right)))
| exp MINUS exp (mark (A.OpExp (A.MINUS, [exp1,exp2]), (exp1left,exp2right)))
| exp STAR exp (mark (A.OpExp (A.TIMES, [exp1,exp2]), (exp1left,exp2right)))
| exp LE exp (mark (A.OpExp (A.LE, [exp1,exp2]), (exp1left,exp2right)))
| exp GT exp (mark (A.OpExp (A.GT, [exp1,exp2]), (exp1left,exp2right)))
| exp GE exp (mark (A.OpExp (A.GE, [exp1,exp2]), (exp1left,exp2right)))
+ | NULL (mark (A.Null, (NULLleft, NULLright)))
| IDENT LPAREN RPAREN (mark (A.FuncCall(IDENT, []), (IDENTleft, RPARENright)))
- | IDENT LPAREN exp RPAREN
- (mark (A.FuncCall(IDENT, [exp]), (IDENTleft, RPARENright)))
| IDENT LPAREN explist RPAREN
(mark (A.FuncCall(IDENT, explist), (IDENTleft, RPARENright)))
+ | NEW LPAREN vtype RPAREN
+ (mark (A.New (vtype), (NEWleft, RPARENright)))
+ | NEW LPAREN vtype LBRACKET exp RBRACKET RPAREN
+ (mark (A.NewArr (vtype, exp), (NEWleft, RPARENright)))
| MINUS exp %prec UNARY (mark (A.OpExp (A.NEGATIVE, [exp]), (MINUSleft,expright)))
| BITNOT exp %prec UNARY (mark (A.OpExp (A.BITNOT, [exp]), (BITNOTleft,expright)))
| BANG exp %prec UNARY (mark (A.OpExp (A.BANG, [exp]), (BANGleft,expright)))
explist : exp ([exp])
| exp COMMA explist (exp :: explist)
-asnop : ASSIGN (NONE)
- | PLUSEQ (SOME(A.PLUS))
- | MINUSEQ (SOME(A.MINUS))
- | STAREQ (SOME(A.TIMES))
- | SLASHEQ (SOME(A.DIVIDEDBY))
- | PERCENTEQ (SOME(A.MODULO))
- | LSHEQ (SOME(A.LSH))
- | RSHEQ (SOME(A.RSH))
- | BITOREQ (SOME(A.BITOR))
- | BITANDEQ (SOME(A.BITAND))
- | BITXOREQ (SOME(A.BITXOR))
+asnop : PLUSEQ (A.PLUS)
+ | MINUSEQ (A.MINUS)
+ | STAREQ (A.TIMES)
+ | SLASHEQ (A.DIVIDEDBY)
+ | PERCENTEQ (A.MODULO)
+ | LSHEQ (A.LSH)
+ | RSHEQ (A.RSH)
+ | BITOREQ (A.BITOR)
+ | BITANDEQ (A.BITAND)
+ | BITXOREQ (A.BITXOR)