248 lines
7.3 KiB
Plaintext
248 lines
7.3 KiB
Plaintext
%parser Tiger.lexer
|
|
// expect 1 shift-reduce conflict
|
|
%namespace Absyn
|
|
|
|
%symbol Var;
|
|
%node SimpleVar : Var {
|
|
public Symbol.Symbol name;
|
|
public SimpleVar(Symbol.Symbol n) { name=n; }
|
|
}
|
|
%node FieldVar : Var {
|
|
public Var var;
|
|
public Symbol.Symbol field;
|
|
public FieldVar(Var v,Symbol.Symbol f){ var=v; field=f; }
|
|
}
|
|
%node SubscriptVar : Var {
|
|
public Var var;
|
|
public Exp index;
|
|
public SubscriptVar(Var v,Exp i) { var=v; index=i; }
|
|
}
|
|
|
|
%symbol Exp;
|
|
%node VarExp : Exp {
|
|
public Var var;
|
|
public VarExp(Var v) { var=v; }
|
|
}
|
|
%node NilExp : Exp {
|
|
}
|
|
%node IntExp : Exp {
|
|
public int value;
|
|
public IntExp(int i) { value=i; }
|
|
}
|
|
%node StringExp : Exp {
|
|
public string value;
|
|
public StringExp(string v) { value=v; }
|
|
}
|
|
%node CallExp : Exp {
|
|
public Symbol.Symbol func;
|
|
public ExpList args;
|
|
public CallExp(Symbol.Symbol f,ExpList a) { func=f; args=a; }
|
|
}
|
|
%node OpExp : Exp {
|
|
public Exp left, right;
|
|
public enum Oper { PLUS,MINUS,MUL,DIV,EQ,NE,LT,LE,GT,GE }
|
|
public Oper oper;
|
|
public OpExp(Exp l, Oper o, Exp r) { left=l; oper=o; right=r; }
|
|
}
|
|
%node RecordExp : Exp {
|
|
public Symbol.Symbol typ;
|
|
public FieldExpList fields;
|
|
public RecordExp(Symbol.Symbol t,FieldExpList f) { typ=t; fields=f; }
|
|
}
|
|
%node SeqExp : Exp {
|
|
public ExpList list;
|
|
public SeqExp(ExpList e) { list=e; }
|
|
}
|
|
%node AssignExp : Exp {
|
|
public Var var;
|
|
public Exp exp;
|
|
public AssignExp(Var v,Exp e) { var=v; exp=e; }
|
|
}
|
|
%node IfExp : Exp {
|
|
public Exp test, thenClause, elseClause; // elseClause may be null
|
|
public IfExp(Exp t,Exp tc,Exp ec) { test=t; thenClause=tc; elseClause=ec; }
|
|
}
|
|
%node WhileExp : Exp {
|
|
public Exp test, body;
|
|
public WhileExp(Exp t,Exp b) { test=t; body=b; }
|
|
}
|
|
%node ForExp : Exp {
|
|
public VarDec var;
|
|
public Exp hi, body;
|
|
public ForExp(VarDec v,Exp h,Exp b) { var=v; hi=h; body=b; }
|
|
}
|
|
%node BreakExp : Exp {
|
|
}
|
|
%node LetExp : Exp {
|
|
public DecList decs;
|
|
public Exp body;
|
|
public LetExp(DecList d,Exp b) { decs=d; body=b; }
|
|
}
|
|
%node ArrayExp : Exp {
|
|
public Symbol.Symbol typ;
|
|
public Exp size,init;
|
|
public ArrayExp(Var v,Exp s,Exp i) {
|
|
Symbol.Symbol t = null;
|
|
if (v is SimpleVar)
|
|
t = ((SimpleVar)v).name;
|
|
else
|
|
Tiger.error(this,"bad array exp");
|
|
typ=t; size=s; init=i;
|
|
}
|
|
}
|
|
|
|
%symbol Dec {
|
|
public Symbol.Symbol name;
|
|
public Dec next = null; // only used within possibly recursive groups of type or function declarations
|
|
public bool Clash(Dec d) {
|
|
if (d==null)
|
|
return false;
|
|
if (name==d.name)
|
|
return true;
|
|
return Clash(d.next);
|
|
}
|
|
}
|
|
|
|
%node FunctionDec : Dec {
|
|
public FieldList parms;
|
|
public NameTy result; // result may be null
|
|
public Exp body;
|
|
public FunctionDec(Symbol.Symbol n,FieldList p,NameTy r,Exp b) {
|
|
name=n; parms=p; result=r; body=b;
|
|
}
|
|
}
|
|
%node VarDec : Dec {
|
|
public NameTy typ; // typ may be null
|
|
public Exp init;
|
|
public bool escape;
|
|
public VarDec(Symbol.Symbol n,NameTy t,Exp i) { name=n; typ=t; init=i; }
|
|
}
|
|
%node TypeDec : Dec {
|
|
public Ty ty;
|
|
public TypeDec(Symbol.Symbol n,Ty t) { name=n; ty=t; }
|
|
}
|
|
|
|
%symbol DecVar {
|
|
public Symbol.Symbol name;
|
|
public NameTy typ; // typ may be null
|
|
public Exp init;
|
|
public DecVar(Symbol.Symbol n,NameTy t,Exp i) { name=n; typ=t; init=i; }
|
|
}
|
|
|
|
%symbol Ty;
|
|
|
|
%node NameTy : Ty {
|
|
public Symbol.Symbol name;
|
|
public NameTy(Symbol.Symbol n) { name=n; }
|
|
}
|
|
%node RecordTy : Ty {
|
|
public FieldList fields;
|
|
public RecordTy(FieldList f) { fields=f; }
|
|
}
|
|
%node ArrayTy : Ty {
|
|
public Symbol.Symbol typ;
|
|
public ArrayTy(Symbol.Symbol t) { typ=t; }
|
|
}
|
|
|
|
%symbol DecList {
|
|
public Dec head;
|
|
public DecList tail;
|
|
public DecList(Dec d,DecList t) { head=d; tail=t; }
|
|
public virtual bool IsEmpty() { return false; }
|
|
}
|
|
|
|
%symbol ExpList {
|
|
public Exp head;
|
|
public ExpList tail;
|
|
public ExpList(Exp h,ExpList t) { head=h; tail=t; }
|
|
}
|
|
|
|
%symbol FieldList {
|
|
public Symbol.Symbol name, typ;
|
|
public FieldList tail;
|
|
public bool escape;
|
|
public FieldList(Symbol.Symbol n,Symbol.Symbol t,FieldList f) { name=n; typ=t; tail=f; }
|
|
public Util.BoolList escList { get {
|
|
Util.BoolList t = null;
|
|
if (tail!=null)
|
|
t = tail.escList;
|
|
return new Util.BoolList(escape,t);
|
|
}}
|
|
}
|
|
|
|
%symbol FieldExpList {
|
|
public Symbol.Symbol name;
|
|
public Exp init;
|
|
public FieldExpList tail;
|
|
public FieldExpList(Symbol.Symbol n,Exp i,FieldExpList t) { name=n; init=i; tail=t; }
|
|
}
|
|
|
|
%symbol ParamList : ExpList {
|
|
public ParamList(Exp h,ParamList t) : base(h,t) {}
|
|
}
|
|
|
|
%left AND OR
|
|
%nonassoc EQ NEQ GT GE LT LE
|
|
%left PLUS MINUS
|
|
%left TIMES DIVIDE
|
|
%before MINUS
|
|
%start Exp
|
|
|
|
DecList : %null
|
|
| Dec:h DecList:t %DecList(h,t);
|
|
Ty : ID:n %NameTy(n.id)
|
|
| LBRACE RBRACE %RecordTy(null)
|
|
| LBRACE FieldList:f RBRACE %RecordTy(f)
|
|
| ARRAY OF ID:t %ArrayTy(t.id);
|
|
FieldList : ID:n COLON ID:type %FieldList(n.id,type.id,null)
|
|
| ID:n COLON ID:type COMMA FieldList:t %FieldList(n.id,type.id,t);
|
|
DecVar : ID:n ASSIGN Exp:e %DecVar(n.id,null,e)
|
|
| ID:n COLON ID:type ASSIGN Exp:e %DecVar(n.id,new NameTy(yyp,type.id),e);
|
|
Dec : VAR DecVar:v %VarDec(v.name,v.typ,v.init)
|
|
| TYPE ID:i EQ Ty:t %TypeDec(i.id,t)
|
|
| FUNCTION ID:n LPAREN FieldList:f RPAREN EQ Exp:e %FunctionDec(n.id,f,null,e)
|
|
| FUNCTION ID:n LPAREN FieldList:f RPAREN COLON ID:type EQ Exp:e %FunctionDec(n.id,f,new NameTy(yyp,type.id),e)
|
|
| FUNCTION ID:n LPAREN RPAREN EQ Exp:e %FunctionDec(n.id,null,null,e)
|
|
| FUNCTION ID:n LPAREN RPAREN COLON ID:type EQ Exp:e %FunctionDec(n.id,null,new NameTy(yyp,type.id),e);
|
|
Var : ID:n %SimpleVar(n.id)
|
|
| Var:v DOT ID:f %FieldVar(v,f.id)
|
|
| Var:a LBRACK Exp:s RBRACK %SubscriptVar(a,s);
|
|
ExpList : Exp:e %ExpList(e,null)
|
|
| Exp:e SEMICOLON ExpList:t %ExpList(e,t);
|
|
ParamList : Exp:e %ParamList(e,null)
|
|
| Exp:e COMMA ParamList:t %ParamList(e,t);
|
|
FieldExpList : ID:n EQ Exp:e %FieldExpList(n.id,e,null)
|
|
| ID:n EQ Exp:e COMMA FieldExpList:f %FieldExpList(n.id,e,f);
|
|
Exp : Var:v %VarExp(v)
|
|
| NIL %NilExp
|
|
| LPAREN RPAREN %SeqExp(null)
|
|
| LPAREN ExpList:e RPAREN %SeqExp(e)
|
|
| INT:i %IntExp(i.val)
|
|
| STRING:s %StringExp(s.yytext)
|
|
| MINUS Exp:e %OpExp(new IntExp(yyp,0),OpExp.Oper.MINUS,e)
|
|
| ID:f LPAREN RPAREN %CallExp(f.id,null)
|
|
| ID:f LPAREN ParamList:p RPAREN %CallExp(f.id,p)
|
|
| Exp:a PLUS Exp:b %OpExp(a,OpExp.Oper.PLUS,b)
|
|
| Exp:a MINUS Exp:b %OpExp(a,OpExp.Oper.MINUS,b)
|
|
| Exp:a TIMES Exp:b %OpExp(a,OpExp.Oper.MUL,b)
|
|
| Exp:a DIVIDE Exp:b %OpExp(a,OpExp.Oper.DIV,b)
|
|
| Exp:a EQ Exp:b %OpExp(a,OpExp.Oper.EQ,b)
|
|
| Exp:a NEQ Exp:b %OpExp(a,OpExp.Oper.NE,b)
|
|
| Exp:a LT Exp:b %OpExp(a,OpExp.Oper.LT,b)
|
|
| Exp:a LE Exp:b %OpExp(a,OpExp.Oper.LE,b)
|
|
| Exp:a GT Exp:b %OpExp(a,OpExp.Oper.GT,b)
|
|
| Exp:a GE Exp:b %OpExp(a,OpExp.Oper.GE,b)
|
|
| Exp:a AND Exp:b %IfExp(a,b,new IntExp(yyp,0))
|
|
| Exp:a OR Exp:b %IfExp(a,new IntExp(yyp,1),b)
|
|
| ID:type LBRACE FieldExpList:f RBRACE %RecordExp(type.id,f)
|
|
| Var:a LBRACK Exp:s RBRACK OF Exp:e %ArrayExp(a,s,e) // a should be ID:type
|
|
| Var:v ASSIGN Exp:e %AssignExp(v,e)
|
|
| IF Exp:c THEN Exp:t ELSE Exp:e %IfExp(c,t,e)
|
|
| IF Exp:c THEN Exp:t %IfExp(c,t,null)
|
|
| WHILE Exp:c DO Exp:b %WhileExp(c,b)
|
|
| FOR DecVar:d TO Exp:h DO Exp:b %ForExp(new VarDec(yyp,d.name,d.typ,d.init),h,b)
|
|
| BREAK %BreakExp
|
|
| LET DecList:d IN END %LetExp(d,null)
|
|
| LET DecList:d IN ExpList:b END %LetExp(d,new SeqExp(yyp,b))
|
|
;
|