/* MiniJava+ Compiler Stage 2b and 2c: Choosing and Using Abstract Syntax For an abstract syntax representation for MiniJava+, you have two choices: the one on the textbook website, and the one I provide below. My version uses more recent Java language features, in particular the parameterized visitor pattern. Beyond that however, I honestly cannot say why my version is better. ***** No matter which version you choose however, you will have to extend it with new classes representing MiniJava+ constructs (see casn2.txt for descriptions of these extra features). You will need a new class, for example, for String constant expressions. ***** --------------------- The abstract syntax classes are organized as follows. You really need to study them carefully first before proceeding. Please spend some time to think about them carefully. interface absyn : call classes implement this interface, which also means that all classes must accept visitors interfaces exp, typ and stat : subinterfaces of absyn for each type of program element class baseinfo : This standalone class can be "extend"ed by any class and carries information that can be useful later exp classes : andexp, orexp, callexp, varexp etc ... stat classes : ifstat, whilestat, vardecstat, etc ... typ classes : inttype, vartype, etc ... list classes : explist, statlist, vdeclist, mdeclist , etc ... These classes all contain an ArrayList called "list". The curious thing about this class is that the "accept" method has a loop in it. Some of these loops run backwards, such as for explist, because of the order in which the list was built by the parsing actions. structural classes : program, mainclass, classdec, methoddec, formal etc ... interface visitor : visitor interface, all visitors must be able to visit all absyn classes EXCEPT for the list classes, which is why the accept mthods of the list clasess are written differently. ------------------- In general there is one class for each production rule of the grammar. However, this is only *in general*. For example, for the two cases of if: Statement -> if (Expression) Statement | if (Expression) Statement else Statement You really only need one class, something like: class ifexp implements exp { exp e1; // exp is the interface for expressions stat s1, s2; // stat is the interface for statements ... } The second statement pointer can just be null when there's no "else" clause. When you have decided which abstract syntax set to use, and have added the necessary MiniJava+ extensions, you should rewrite your .cup file to build abstract syntax trees. This will complete parts 2b and 2c of the compiler. You are also required to finish the "visitor pattern warmup assignment", posted on the web, so that you're familiar with the technique. */ /* Interfaces and superclasses for minijava abstract syntax - Chuck Liang's version You must add the MiniJava+ extensions */ import java.util.*; // The baseinfo class contains information such as types, and error-checking // information such as line numbers. This class can be modified // without affecting existing code. It should be safe for any class // to inherit from this class. class baseinfo { String mjtype = "void"; // type will be determined by type checker String currentclass = "GLOBAL"; // might be useful int line; // line number where construct ends. public baseinfo() { line = Global.line; } // more stuff may be added... } // baseinfo /// Parameterized Visitor Pattern Interfaces: interface absyn { public R accept(visitor v); } interface stat extends absyn {} // statements interface exp extends absyn {} // expressions interface typ extends absyn {} // type expressions // absyn lists (see below) interface visitor { public T visit(blockstat x); // { s1; s2; ... } public T visit(ifstat x); // if (e1) s1; optional [else s2;] public T visit(whilestat x); // while (e1) s1; public T visit(printlnstat x); // System.out.println(string or int) public T visit(vardecstat x); // int x; or int x = 1; public T visit(assignstat x); // x = x+1; public T visit(arrayasnstat x); // A[e1] = e2; public T visit(returnstat x); // return e1; public T visit(andexp x); // e1 && e2 public T visit(minusexp x); // e1 - e2 public T visit(plusexp x); // e1 + e2 public T visit(multexp x); // e1 * e2 public T visit(lessthanexp x); // e1 < e2 public T visit(arrayexp x); // A[e1] public T visit(arraylengthexp x); // A.length public T visit(callexp x); // A.f(...) public T visit(intexp x); // 2 public T visit(boolexp x); // true, false public T visit(varexp x); // x public T visit(thisexp x); // this public T visit(newarrayexp x); // new int[size] public T visit(newobjectexp x); // new bankaccount() public T visit(inttype x); // int public T visit(booltype x); // boolean public T visit(intarraytype x); // int[] public T visit(vartype x); // bankaccount (user defined type) public T visit(program x); // root class public T visit(mainclass x); // special main class public T visit(classdec x); // class account { ... } public T visit(methoddec x); // int f(int x, int y) { ... } public T visit(formal x); // formal parameter (int x, int y) } // visitor interface ////////////////// Abstract syntax classes //////////////////// /// statements class blockstat extends baseinfo implements stat { statlist slist; public blockstat(statlist s) {slist=s;} public R accept(visitor v) { return v.visit(this); } } // else-if will use nop statement class ifstat extends baseinfo implements stat { exp cond; // boolean condition stat s1, s2; // if and else cases, s2 can be null public ifstat(exp c, stat a, stat b) {cond=c; s1=a; s2=b; } public R accept(visitor v) { return v.visit(this); } } class whilestat extends baseinfo implements stat { exp cond; stat st; public whilestat(exp c, stat s) {cond=c; st=s;} public R accept(visitor v) { return v.visit(this); } } class printlnstat extends baseinfo implements stat { exp e; public printlnstat(exp a) {e=a;} public R accept(visitor v) { return v.visit(this); } } class vardecstat extends baseinfo implements stat { typ t; String v; exp init = null; public vardecstat(typ a, String b) {t=a; v=b;} public vardecstat(typ a, String b, exp c) {t=a; v=b; init=c;} public R accept(visitor v) { return v.visit(this); } } class returnstat extends baseinfo implements stat { exp e; public returnstat(exp a) {e=a;} public R accept(visitor v) { return v.visit(this); } } class assignstat extends baseinfo implements stat { varexp ve; exp val; public assignstat(varexp a, exp b) {ve=a; val=b;} public R accept(visitor v) { return v.visit(this); } } class arrayasnstat extends baseinfo implements stat { varexp ve; exp index; exp val; public arrayasnstat(varexp a, exp b, exp c) {ve=a; index=b; val=c;} public R accept(visitor v) { return v.visit(this); } } ///////////////////////////////////////////////////////////////// /// expressions class andexp extends baseinfo implements exp { exp e1, e2; public andexp(exp a, exp b) { e1=a; e2=b; } public R accept(visitor v) { return v.visit(this); } } class minusexp extends baseinfo implements exp { exp e1, e2; public minusexp(exp a, exp b) { e1=a; e2=b; } public R accept(visitor v) { return v.visit(this); } } class plusexp extends baseinfo implements exp { exp e1, e2; public plusexp(exp a, exp b) { e1=a; e2=b; } public R accept(visitor v) { return v.visit(this); } } class multexp extends baseinfo implements exp { exp e1, e2; public multexp(exp a, exp b) { e1=a; e2=b; } public R accept(visitor v) { return v.visit(this); } } class lessthanexp extends baseinfo implements exp { exp e1, e2; public lessthanexp(exp a, exp b) { e1=a; e2=b; } public R accept(visitor v) { return v.visit(this); } } class arrayexp extends baseinfo implements exp { exp e1; exp index; public arrayexp(exp a, exp b) {e1=a; index=b;} public R accept(visitor v) { return v.visit(this); } } class arraylengthexp extends baseinfo implements exp { exp aexp; // the array expression public arraylengthexp(exp a) {aexp=a;} public R accept(visitor v) { return v.visit(this); } } class callexp extends baseinfo implements exp { exp e1; String fname; explist args; public callexp(exp a, String b, explist c) {e1=a; fname=b; args=c;} public R accept(visitor v) { return v.visit(this); } } class intexp extends baseinfo implements exp { int val; public intexp(int x) {val=x;} public R accept(visitor v) { return v.visit(this); } } class boolexp extends baseinfo implements exp { boolean val; public boolexp(boolean b) {val=b;} public R accept(visitor v) { return v.visit(this); } } class varexp extends baseinfo implements exp { String name; public varexp(String v) {name=v;} public R accept(visitor v) { return v.visit(this); } } class thisexp extends baseinfo implements exp { public R accept(visitor v) { return v.visit(this); } // might want info pertaining to current class } class newarrayexp extends baseinfo implements exp { // limited to only intarrays exp size; public newarrayexp(exp s) {size=s;} public R accept(visitor v) { return v.visit(this); } } class newobjectexp extends baseinfo implements exp { String classname; public newobjectexp(String s) {classname=s;} public R accept(visitor v) { return v.visit(this); } } //// type expressions class vartype extends baseinfo implements typ { String classname; public vartype(String s) {classname=s;} public R accept(visitor v) { return v.visit(this); } } class inttype extends baseinfo implements typ { public R accept(visitor v) { return v.visit(this); } } class booltype extends baseinfo implements typ { public R accept(visitor v) { return v.visit(this); } } class intarraytype extends baseinfo implements typ { public R accept(visitor v) { return v.visit(this); } } ///////// others class program extends baseinfo implements absyn { mainclass mc; cdeclist cl; public program(mainclass a, cdeclist b) {mc=a; cl=b;} public R accept(visitor v) { return v.visit(this); } } class mainclass extends baseinfo implements absyn { String classname; String argname; statlist body; public mainclass(String a, String b, statlist c) { classname=a; argname=b; body=c; } public R accept(visitor v) { return v.visit(this); } } // not distinguishing between simple and extends class classdec extends baseinfo implements absyn { String superclass = "Object"; String classname; vdeclist vars; mdeclist methods; public classdec(String a, vdeclist b, mdeclist c) {classname=a; vars=b; methods=c;} public classdec(String a, String a2, vdeclist b, mdeclist c) {classname=a; vars=b; methods=c; superclass=a2; } public R accept(visitor v) { return v.visit(this); } } class methoddec extends baseinfo implements absyn { typ rettype; // return type String mname; formallist args; statlist body; public methoddec(typ r, String m, formallist a, statlist b) { rettype=r; mname=m; args=a; body=b; } public R accept(visitor v) { return v.visit(this); } } class formal extends baseinfo implements absyn { typ ty; String name; public formal(typ a, String b) {ty=a; name=b;} public R accept(visitor v) { return v.visit(this); } } ///////// list classes. Note that the accept methods are different. // visitors cannot visit these classes directly, but these // classes can accept visitors class statlist implements absyn // list of statements { ArrayList list = new ArrayList(); public R accept(visitor v) { for (stat s : list) s.accept(v); return null; } } class explist implements absyn // list of expressions (actual params) { ArrayList list = new ArrayList(); public R accept(visitor v) { // for (exp s : list) s.accept(v); need reverse loop int i; int n = list.size(); for(i=n-1;i>=0;i--) list.get(i).accept(v); return null; } } // variable declaration list class vdeclist implements absyn { ArrayList list = new ArrayList(); public R accept(visitor v) { for (vardecstat s : list) s.accept(v); return null; } } // method declaration list class mdeclist implements absyn { ArrayList list = new ArrayList(); public R accept(visitor v) { for (methoddec s : list) s.accept(v); return null; } } // class declaration list class cdeclist implements absyn { ArrayList list = new ArrayList(); public R accept(visitor v) { for (classdec s : list) s.accept(v); return null; } } // formal parameter list class formallist implements absyn { ArrayList list = new ArrayList(); public R accept(visitor v) { // for (formal s : list) s.accept(v); need reverse loop int i; int n = list.size(); for(i=n-1;i>=0;i--) list.get(i).accept(v); return null; } } //////////////////////////////////////////////////////////////////// /// The following "null visitor" can be inherited from, in case // you want to define a visitor that visits some but not all of the // absyn classes. In such a case, you'll simply override the cases // that the visitor is really intended to visit class nullvisitor implements visitor { public T visit(blockstat x) { return null; } public T visit(ifstat x) { return null; } public T visit(whilestat x) { return null; } public T visit(printlnstat x) { return null; } public T visit(vardecstat x) { return null; } public T visit(returnstat x) { return null; } public T visit(assignstat x) { return null; } public T visit(arrayasnstat x) { return null; } public T visit(andexp x) { return null; } public T visit(minusexp x) { return null; } public T visit(plusexp x) { return null; } public T visit(multexp x) { return null; } public T visit(lessthanexp x) { return null; } public T visit(arrayexp x) { return null; } public T visit(arraylengthexp x) { return null; } public T visit(callexp x) { return null; } public T visit(intexp x) { return null; } public T visit(boolexp x) { return null; } public T visit(varexp x) { return null; } public T visit(thisexp x) { return null; } public T visit(newarrayexp x) { return null; } public T visit(newobjectexp x) { return null; } public T visit(vartype x) { return null; } public T visit(inttype x) { return null; } public T visit(booltype x) { return null; } public T visit(intarraytype x) { return null; } public T visit(program x) { return null; } public T visit(mainclass x) { return null; } public T visit(classdec x) { return null; } public T visit(methoddec x) { return null; } public T visit(formal x) { return null; } } // nullvisitor