├── .gitignore ├── README.md ├── programs ├── BinarySearch.java ├── BinaryTree.java ├── BinopExp.java ├── BubbleSort.java ├── Factorial.java ├── FactorialErrors.java ├── LexerInput ├── LinearSearch.java ├── LinkedList.java ├── QuickSort.java └── TreeVisitor.java ├── src ├── ast │ ├── And.java │ ├── ArrayAssign.java │ ├── ArrayLength.java │ ├── ArrayLookup.java │ ├── Assign.java │ ├── Block.java │ ├── BooleanType.java │ ├── Call.java │ ├── ClassDecl.java │ ├── ClassDeclExtends.java │ ├── ClassDeclList.java │ ├── ClassDeclSimple.java │ ├── Exp.java │ ├── ExpList.java │ ├── False.java │ ├── Formal.java │ ├── FormalList.java │ ├── Identifier.java │ ├── IdentifierExp.java │ ├── IdentifierType.java │ ├── If.java │ ├── IntArrayType.java │ ├── IntegerLiteral.java │ ├── IntegerType.java │ ├── LessThan.java │ ├── MainClass.java │ ├── MethodDecl.java │ ├── MethodDeclList.java │ ├── Minus.java │ ├── NewArray.java │ ├── NewObject.java │ ├── Not.java │ ├── Plus.java │ ├── Print.java │ ├── Program.java │ ├── Statement.java │ ├── StatementList.java │ ├── This.java │ ├── Times.java │ ├── True.java │ ├── Type.java │ ├── VarDecl.java │ ├── VarDeclList.java │ └── While.java ├── parser │ ├── Lexer.java │ ├── Parser.java │ ├── Token.java │ └── TokenType.java └── visitor │ ├── PrettyPrintVisitor.java │ └── Visitor.java └── test ├── TestLexer.java └── TestParser.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | 8 | # Project Files # 9 | *.classpath 10 | *.project 11 | *.settings 12 | 13 | # Other Files # 14 | notes 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MiniJava 2 | ======== 3 | 4 | A compiler for a subset of the Java programming language. 5 | 6 | This project is based off of the readings from "Modern Compiler Implementation in Java (2nd Ed.)" by Andrew Appel. 7 | 8 | For the MiniJava language reference manual, please consult: http://alumni.cs.ucr.edu/~weesan/cs152/MiniJava.html. 9 | -------------------------------------------------------------------------------- /programs/BinarySearch.java: -------------------------------------------------------------------------------- 1 | class BinarySearch{ 2 | public static void main(String[] a){ 3 | System.out.println(new BS().Start(20)); 4 | } 5 | } 6 | // This class contains an array of integers and 7 | // methods to initialize, print and search the array 8 | // using Binary Search 9 | 10 | class BS{ 11 | int[] number ; 12 | int size ; 13 | 14 | // Invoke methods to initialize, print and search 15 | // for elements on the array 16 | public int Start(int sz){ 17 | int aux01 ; 18 | int aux02 ; 19 | aux01 = this.Init(sz); 20 | aux02 = this.Print(); 21 | if (this.Search(8)) System.out.println(1) ; 22 | else System.out.println(0) ; 23 | if (this.Search(19)) System.out.println(1) ; 24 | else System.out.println(0) ; 25 | if (this.Search(20)) System.out.println(1) ; 26 | else System.out.println(0) ; 27 | if (this.Search(21)) System.out.println(1) ; 28 | else System.out.println(0) ; 29 | if (this.Search(37)) System.out.println(1) ; 30 | else System.out.println(0) ; 31 | if (this.Search(38)) System.out.println(1) ; 32 | else System.out.println(0) ; 33 | if (this.Search(39)) System.out.println(1) ; 34 | else System.out.println(0) ; 35 | if (this.Search(50)) System.out.println(1) ; 36 | else System.out.println(0) ; 37 | 38 | return 999 ; 39 | } 40 | 41 | 42 | // Search for a specific value (num) using 43 | // binary search 44 | public boolean Search(int num){ 45 | boolean bs01 ; 46 | int right ; 47 | int left ; 48 | boolean var_cont ; 49 | int medium ; 50 | int aux01 ; 51 | int nt ; 52 | 53 | aux01 = 0 ; 54 | bs01 = false ; 55 | right = number.length ; 56 | right = right - 1 ; 57 | left = 0 ; 58 | var_cont = true ; 59 | while (var_cont){ 60 | medium = left + right ; 61 | medium = this.Div(medium); 62 | aux01 = number[medium] ; 63 | if (num < aux01) right = medium - 1 ; 64 | else left = medium + 1 ; 65 | if (this.Compare(aux01,num)) var_cont = false ; 66 | else var_cont = true ; 67 | if (right < left) var_cont = false ; 68 | else nt = 0 ; 69 | } 70 | 71 | if (this.Compare(aux01,num)) bs01 = true ; 72 | else bs01 = false ; 73 | return bs01 ; 74 | } 75 | 76 | // This method computes and returns the 77 | // integer division of a number (num) by 2 78 | public int Div(int num){ 79 | int count01 ; 80 | int count02 ; 81 | int aux03 ; 82 | 83 | count01 = 0 ; 84 | count02 = 0 ; 85 | aux03 = num - 1 ; 86 | while (count02 < aux03) { 87 | count01 = count01 + 1 ; 88 | count02 = count02 + 2 ; 89 | } 90 | return count01 ; 91 | } 92 | 93 | 94 | // This method compares two integers and 95 | // returns true if they are equal and false 96 | // otherwise 97 | public boolean Compare(int num1 , int num2){ 98 | boolean retval ; 99 | int aux02 ; 100 | 101 | retval = false ; 102 | aux02 = num2 + 1 ; 103 | if (num1 < num2) retval = false ; 104 | else if (!(num1 < aux02)) retval = false ; 105 | else retval = true ; 106 | return retval ; 107 | } 108 | 109 | // Print the integer array 110 | public int Print(){ 111 | int j ; 112 | 113 | j = 1 ; 114 | while (j < (size)) { 115 | System.out.println(number[j]); 116 | j = j + 1 ; 117 | } 118 | System.out.println(99999); 119 | return 0 ; 120 | } 121 | 122 | 123 | // Initialize the integer array 124 | public int Init(int sz){ 125 | int j ; 126 | int k ; 127 | int aux02 ; 128 | int aux01 ; 129 | 130 | size = sz ; 131 | number = new int[sz] ; 132 | 133 | j = 1 ; 134 | k = size + 1 ; 135 | while (j < (size)) { 136 | aux01 = 2 * j ; 137 | aux02 = k - 3 ; 138 | number[j] = aux01 + aux02 ; 139 | j = j + 1 ; 140 | k = k - 1 ; 141 | } 142 | return 0 ; 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /programs/BinaryTree.java: -------------------------------------------------------------------------------- 1 | class BinaryTree{ 2 | public static void main(String[] a){ 3 | System.out.println(new BT().Start()); 4 | } 5 | } 6 | 7 | 8 | // This class invokes the methods to create a tree, 9 | // insert, delete and serach for elements on it 10 | class BT { 11 | 12 | public int Start(){ 13 | Tree root ; 14 | boolean ntb ; 15 | int nti ; 16 | 17 | root = new Tree(); 18 | ntb = root.Init(16); 19 | ntb = root.Print(); 20 | System.out.println(100000000); 21 | ntb = root.Insert(8) ; 22 | ntb = root.Print(); 23 | ntb = root.Insert(24) ; 24 | ntb = root.Insert(4) ; 25 | ntb = root.Insert(12) ; 26 | ntb = root.Insert(20) ; 27 | ntb = root.Insert(28) ; 28 | ntb = root.Insert(14) ; 29 | ntb = root.Print(); 30 | System.out.println(root.Search(24)); 31 | System.out.println(root.Search(12)); 32 | System.out.println(root.Search(16)); 33 | System.out.println(root.Search(50)); 34 | System.out.println(root.Search(12)); 35 | ntb = root.Delete(12); 36 | ntb = root.Print(); 37 | System.out.println(root.Search(12)); 38 | 39 | return 0 ; 40 | } 41 | 42 | } 43 | 44 | class Tree{ 45 | Tree left ; 46 | Tree right; 47 | int key ; 48 | boolean has_left ; 49 | boolean has_right ; 50 | Tree my_null ; 51 | 52 | // Initialize a node with a key value and no children 53 | public boolean Init(int v_key){ 54 | key = v_key ; 55 | has_left = false ; 56 | has_right = false ; 57 | return true ; 58 | } 59 | 60 | // Update the right child with rn 61 | public boolean SetRight(Tree rn){ 62 | right = rn ; 63 | return true ; 64 | } 65 | 66 | // Update the left child with ln 67 | public boolean SetLeft(Tree ln){ 68 | left = ln ; 69 | return true ; 70 | } 71 | 72 | public Tree GetRight(){ 73 | return right ; 74 | } 75 | 76 | public Tree GetLeft(){ 77 | return left; 78 | } 79 | 80 | public int GetKey(){ 81 | return key ; 82 | } 83 | 84 | public boolean SetKey(int v_key){ 85 | key = v_key ; 86 | return true ; 87 | } 88 | 89 | public boolean GetHas_Right(){ 90 | return has_right ; 91 | } 92 | 93 | public boolean GetHas_Left(){ 94 | return has_left ; 95 | } 96 | 97 | public boolean SetHas_Left(boolean val){ 98 | has_left = val ; 99 | return true ; 100 | } 101 | 102 | public boolean SetHas_Right(boolean val){ 103 | has_right = val ; 104 | return true ; 105 | } 106 | 107 | // This method compares two integers and 108 | // returns true if they are equal and false 109 | // otherwise 110 | public boolean Compare(int num1 , int num2){ 111 | boolean ntb ; 112 | int nti ; 113 | 114 | ntb = false ; 115 | nti = num2 + 1 ; 116 | if (num1 < num2) ntb = false ; 117 | else if (!(num1 < nti)) ntb = false ; 118 | else ntb = true ; 119 | return ntb ; 120 | } 121 | 122 | 123 | // Insert a new element in the tree 124 | public boolean Insert(int v_key){ 125 | Tree new_node ; 126 | boolean ntb ; 127 | boolean cont ; 128 | int key_aux ; 129 | Tree current_node ; 130 | 131 | new_node = new Tree(); 132 | ntb = new_node.Init(v_key) ; 133 | current_node = this ; 134 | cont = true ; 135 | while (cont){ 136 | key_aux = current_node.GetKey(); 137 | if (v_key < key_aux){ 138 | if (current_node.GetHas_Left()) 139 | current_node = current_node.GetLeft() ; 140 | else { 141 | cont = false ; 142 | ntb = current_node.SetHas_Left(true); 143 | ntb = current_node.SetLeft(new_node); 144 | } 145 | } 146 | else{ 147 | if (current_node.GetHas_Right()) 148 | current_node = current_node.GetRight() ; 149 | else { 150 | cont = false ; 151 | ntb = current_node.SetHas_Right(true); 152 | ntb = current_node.SetRight(new_node); 153 | } 154 | } 155 | } 156 | return true ; 157 | } 158 | 159 | 160 | // Delete an element from the tree 161 | public boolean Delete(int v_key){ 162 | Tree current_node ; 163 | Tree parent_node ; 164 | boolean cont ; 165 | boolean found ; 166 | boolean is_root ; 167 | int key_aux ; 168 | boolean ntb ; 169 | 170 | current_node = this ; 171 | parent_node = this ; 172 | cont = true ; 173 | found = false ; 174 | is_root = true ; 175 | while (cont){ 176 | key_aux = current_node.GetKey(); 177 | if (v_key < key_aux) 178 | if (current_node.GetHas_Left()){ 179 | parent_node = current_node ; 180 | current_node = current_node.GetLeft() ; 181 | } 182 | else cont = false ; 183 | else 184 | if (key_aux < v_key) 185 | if (current_node.GetHas_Right()){ 186 | parent_node = current_node ; 187 | current_node = current_node.GetRight() ; 188 | } 189 | else cont = false ; 190 | else { 191 | if (is_root) 192 | if ((!current_node.GetHas_Right()) && 193 | (!current_node.GetHas_Left()) ) 194 | ntb = true ; 195 | else 196 | ntb = this.Remove(parent_node,current_node); 197 | else ntb = this.Remove(parent_node,current_node); 198 | found = true ; 199 | cont = false ; 200 | } 201 | is_root = false ; 202 | } 203 | return found ; 204 | } 205 | 206 | 207 | // Check if the element to be removed will use the 208 | // righ or left subtree if one exists 209 | public boolean Remove(Tree p_node, Tree c_node){ 210 | boolean ntb ; 211 | int auxkey1 ; 212 | int auxkey2 ; 213 | 214 | if (c_node.GetHas_Left()) 215 | ntb = this.RemoveLeft(p_node,c_node) ; 216 | else 217 | if (c_node.GetHas_Right()) 218 | ntb = this.RemoveRight(p_node,c_node) ; 219 | else { 220 | auxkey1 = c_node.GetKey(); 221 | //auxtree01 = p_node.GetLeft() ; 222 | //auxkey2 = auxtree01.GetKey() ; 223 | auxkey2 = (p_node.GetLeft()).GetKey() ; 224 | if (this.Compare(auxkey1,auxkey2)) { 225 | ntb = p_node.SetLeft(my_null); 226 | ntb = p_node.SetHas_Left(false); 227 | } 228 | else { 229 | ntb = p_node.SetRight(my_null); 230 | ntb = p_node.SetHas_Right(false); 231 | } 232 | } 233 | return true ; 234 | } 235 | 236 | 237 | // Copy the child key to the parent until a leaf is 238 | // found and remove the leaf. This is done with the 239 | // right subtree 240 | public boolean RemoveRight(Tree p_node, Tree c_node){ 241 | boolean ntb ; 242 | 243 | while (c_node.GetHas_Right()){ 244 | //auxtree01 = c_node.GetRight() ; 245 | //auxint02 = auxtree01.GetKey(); 246 | //ntb = c_node.SetKey(auxint02); 247 | ntb = c_node.SetKey((c_node.GetRight()).GetKey()); 248 | p_node = c_node ; 249 | c_node = c_node.GetRight() ; 250 | } 251 | ntb = p_node.SetRight(my_null); 252 | ntb = p_node.SetHas_Right(false); 253 | return true ; 254 | } 255 | 256 | 257 | // Copy the child key to the parent until a leaf is 258 | // found and remove the leaf. This is done with the 259 | // left subtree 260 | public boolean RemoveLeft(Tree p_node, Tree c_node){ 261 | boolean ntb ; 262 | 263 | while (c_node.GetHas_Left()){ 264 | //auxtree01 = c_node.GetLeft() ; 265 | //auxint02 = auxtree01.GetKey(); 266 | //ntb = c_node.SetKey(auxint02); 267 | ntb = c_node.SetKey((c_node.GetLeft()).GetKey()); 268 | p_node = c_node ; 269 | c_node = c_node.GetLeft() ; 270 | } 271 | ntb = p_node.SetLeft(my_null); 272 | ntb = p_node.SetHas_Left(false); 273 | return true ; 274 | } 275 | 276 | // Search for an elemnt in the tree 277 | public int Search(int v_key){ 278 | boolean cont ; 279 | int ifound ; 280 | Tree current_node; 281 | int key_aux ; 282 | 283 | current_node = this ; 284 | cont = true ; 285 | ifound = 0 ; 286 | while (cont){ 287 | key_aux = current_node.GetKey(); 288 | if (v_key < key_aux) 289 | if (current_node.GetHas_Left()) 290 | current_node = current_node.GetLeft() ; 291 | else cont = false ; 292 | else 293 | if (key_aux < v_key) 294 | if (current_node.GetHas_Right()) 295 | current_node = current_node.GetRight() ; 296 | else cont = false ; 297 | else { 298 | ifound = 1 ; 299 | cont = false ; 300 | } 301 | } 302 | return ifound ; 303 | } 304 | 305 | // Invoke the method to really print the tree elements 306 | public boolean Print(){ 307 | Tree current_node; 308 | boolean ntb ; 309 | 310 | current_node = this ; 311 | ntb = this.RecPrint(current_node); 312 | return true ; 313 | } 314 | 315 | // Print the elements of the tree 316 | public boolean RecPrint(Tree node){ 317 | boolean ntb ; 318 | 319 | if (node.GetHas_Left()){ 320 | //auxtree01 = node.GetLeft() ; 321 | //ntb = this.RecPrint(auxtree01); 322 | ntb = this.RecPrint(node.GetLeft()); 323 | } else ntb = true ; 324 | System.out.println(node.GetKey()); 325 | if (node.GetHas_Right()){ 326 | //auxtree01 = node.GetRight() ; 327 | //ntb = this.RecPrint(auxtree01); 328 | ntb = this.RecPrint(node.GetRight()); 329 | } else ntb = true ; 330 | return true ; 331 | } 332 | 333 | } 334 | 335 | -------------------------------------------------------------------------------- /programs/BinopExp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * A small program to test the parsing of an expression according to the 4 | * binary operator precedence levels. 5 | * 6 | * From lowest to highest: 7 | * && 8 | * < 9 | * +, - 10 | * * 11 | * [], . 12 | * 13 | */ 14 | 15 | class BinopExp { 16 | public static void main(String[] args) { 17 | // should parenthesize as (args[(1-2+2)]<5) && ((4+(5*3))<(args.length)) 18 | System.out.println(args[(1-1+2)] < 5 && 4 + 5 * 3 < args.length); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /programs/BubbleSort.java: -------------------------------------------------------------------------------- 1 | class BubbleSort{ 2 | public static void main(String[] a){ 3 | System.out.println(new BBS().Start(10)); 4 | } 5 | } 6 | 7 | 8 | // This class contains the array of integers and 9 | // methods to initialize, print and sort the array 10 | // using Bublesort 11 | class BBS{ 12 | 13 | int[] number ; 14 | int size ; 15 | 16 | // Invoke the Initialization, Sort and Printing 17 | // Methods 18 | public int Start(int sz){ 19 | int aux01 ; 20 | aux01 = this.Init(sz); 21 | aux01 = this.Print(); 22 | System.out.println(99999); 23 | aux01 = this.Sort(); 24 | aux01 = this.Print(); 25 | return 0 ; 26 | } 27 | 28 | 29 | // Sort array of integers using Bublesort method 30 | public int Sort(){ 31 | int nt ; 32 | int i ; 33 | int aux02 ; 34 | int aux04 ; 35 | int aux05 ; 36 | int aux06 ; 37 | int aux07 ; 38 | int j ; 39 | int t ; 40 | i = size - 1 ; 41 | aux02 = 0 - 1 ; 42 | while (aux02 < i) { 43 | j = 1 ; 44 | //aux03 = i+1 ; 45 | while (j < (i+1)){ 46 | aux07 = j - 1 ; 47 | aux04 = number[aux07] ; 48 | aux05 = number[j] ; 49 | if (aux05 < aux04) { 50 | aux06 = j - 1 ; 51 | t = number[aux06] ; 52 | number[aux06] = number[j] ; 53 | number[j] = t; 54 | } 55 | else nt = 0 ; 56 | j = j + 1 ; 57 | } 58 | i = i - 1 ; 59 | } 60 | return 0 ; 61 | } 62 | 63 | // Printing method 64 | public int Print(){ 65 | int j ; 66 | j = 0 ; 67 | while (j < (size)) { 68 | System.out.println(number[j]); 69 | j = j + 1 ; 70 | } 71 | return 0 ; 72 | } 73 | 74 | // Initialize array of integers 75 | public int Init(int sz){ 76 | size = sz ; 77 | number = new int[sz] ; 78 | 79 | number[0] = 20 ; 80 | number[1] = 7 ; 81 | number[2] = 12 ; 82 | number[3] = 18 ; 83 | number[4] = 2 ; 84 | number[5] = 11 ; 85 | number[6] = 6 ; 86 | number[7] = 9 ; 87 | number[8] = 19 ; 88 | number[9] = 5 ; 89 | 90 | return 0 ; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /programs/Factorial.java: -------------------------------------------------------------------------------- 1 | class Factorial{ 2 | public static void main(String[] a){ 3 | System.out.println(new Fac().ComputeFac(10)); 4 | } 5 | } 6 | 7 | class Fac { 8 | 9 | public int ComputeFac(int num){ 10 | int num_aux ; 11 | if (num < 1) 12 | num_aux = 1 ; 13 | else 14 | num_aux = num * (this.ComputeFac(num-1)) ; 15 | return num_aux ; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /programs/FactorialErrors.java: -------------------------------------------------------------------------------- 1 | class Factorial{ 2 | public Static void main(String[] a){ 3 | System.out.println(new Fac().ComputeFac(10)); 4 | } 5 | } 6 | 7 | class Fac { 8 | 9 | public int ComputeFac(int num { 10 | int num_aux 11 | if (num < 1) 12 | num_aux = 1 ; 13 | else 14 | num_aux = num * (this.ComputeFac(num-1)) ; 15 | return num_aux ; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /programs/LexerInput: -------------------------------------------------------------------------------- 1 | abc123 2 | 456+789 3 | &&<+-*& 4 | ()[]{};,.=! 5 | class 6 | public static void main 7 | String 8 | extends 9 | return 10 | int boolean 11 | if else 12 | while 13 | true false 14 | this 15 | new 16 | NEW / // if 17 | / /* */ abc /**/ 18 | /* /* /* abc */ /* */ */ 123 */ else 19 | ; 20 | -------------------------------------------------------------------------------- /programs/LinearSearch.java: -------------------------------------------------------------------------------- 1 | class LinearSearch{ 2 | public static void main(String[] a){ 3 | System.out.println(new LS().Start(10)); 4 | } 5 | } 6 | 7 | 8 | // This class contains an array of integers and 9 | // methods to initialize, print and search the array 10 | // using Linear Search 11 | class LS { 12 | int[] number ; 13 | int size ; 14 | 15 | // Invoke methods to initialize, print and search 16 | // for elements on the array 17 | public int Start(int sz){ 18 | int aux01 ; 19 | int aux02 ; 20 | 21 | aux01 = this.Init(sz); 22 | aux02 = this.Print(); 23 | System.out.println(9999); 24 | System.out.println(this.Search(8)); 25 | System.out.println(this.Search(12)) ; 26 | System.out.println(this.Search(17)) ; 27 | System.out.println(this.Search(50)) ; 28 | return 55 ; 29 | } 30 | 31 | // Print array of integers 32 | public int Print(){ 33 | int j ; 34 | 35 | j = 1 ; 36 | while (j < (size)) { 37 | System.out.println(number[j]); 38 | j = j + 1 ; 39 | } 40 | return 0 ; 41 | } 42 | 43 | // Search for a specific value (num) using 44 | // linear search 45 | public int Search(int num){ 46 | int j ; 47 | boolean ls01 ; 48 | int ifound ; 49 | int aux01 ; 50 | int aux02 ; 51 | int nt ; 52 | 53 | j = 1 ; 54 | ls01 = false ; 55 | ifound = 0 ; 56 | 57 | //System.out.println(num); 58 | while (j < (size)) { 59 | aux01 = number[j] ; 60 | aux02 = num + 1 ; 61 | if (aux01 < num) nt = 0 ; 62 | else if (!(aux01 < aux02)) nt = 0 ; 63 | else { 64 | ls01 = true ; 65 | ifound = 1 ; 66 | j = size ; 67 | } 68 | j = j + 1 ; 69 | } 70 | 71 | return ifound ; 72 | } 73 | 74 | 75 | 76 | // initialize array of integers with some 77 | // some sequence 78 | public int Init(int sz){ 79 | int j ; 80 | int k ; 81 | int aux01 ; 82 | int aux02 ; 83 | 84 | size = sz ; 85 | number = new int[sz] ; 86 | 87 | j = 1 ; 88 | k = size + 1 ; 89 | while (j < (size)) { 90 | aux01 = 2 * j ; 91 | aux02 = k - 3 ; 92 | number[j] = aux01 + aux02 ; 93 | j = j + 1 ; 94 | k = k - 1 ; 95 | } 96 | return 0 ; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /programs/LinkedList.java: -------------------------------------------------------------------------------- 1 | class LinkedList{ 2 | public static void main(String[] a){ 3 | System.out.println(new LL().Start()); 4 | } 5 | } 6 | 7 | class Element { 8 | int Age ; 9 | int Salary ; 10 | boolean Married ; 11 | 12 | // Initialize some class variables 13 | public boolean Init(int v_Age, int v_Salary, boolean v_Married){ 14 | Age = v_Age ; 15 | Salary = v_Salary ; 16 | Married = v_Married ; 17 | return true ; 18 | } 19 | 20 | public int GetAge(){ 21 | return Age ; 22 | } 23 | 24 | public int GetSalary(){ 25 | return Salary ; 26 | } 27 | 28 | public boolean GetMarried(){ 29 | return Married ; 30 | } 31 | 32 | // This method returns true if the object "other" 33 | // has the same values for age, salary and 34 | public boolean Equal(Element other){ 35 | boolean ret_val ; 36 | int aux01 ; 37 | int aux02 ; 38 | int nt ; 39 | ret_val = true ; 40 | 41 | aux01 = other.GetAge(); 42 | if (!this.Compare(aux01,Age)) ret_val = false ; 43 | else { 44 | aux02 = other.GetSalary(); 45 | if (!this.Compare(aux02,Salary)) ret_val = false ; 46 | else 47 | if (Married) 48 | if (!other.GetMarried()) ret_val = false; 49 | else nt = 0 ; 50 | else 51 | if (other.GetMarried()) ret_val = false; 52 | else nt = 0 ; 53 | } 54 | 55 | return ret_val ; 56 | } 57 | 58 | // This method compares two integers and 59 | // returns true if they are equal and false 60 | // otherwise 61 | public boolean Compare(int num1 , int num2){ 62 | boolean retval ; 63 | int aux02 ; 64 | retval = false ; 65 | aux02 = num2 + 1 ; 66 | if (num1 < num2) retval = false ; 67 | else if (!(num1 < aux02)) retval = false ; 68 | else retval = true ; 69 | return retval ; 70 | } 71 | 72 | } 73 | 74 | class List{ 75 | Element elem ; 76 | List next ; 77 | boolean end ; 78 | 79 | // Initialize the node list as the last node 80 | public boolean Init(){ 81 | end = true ; 82 | return true ; 83 | } 84 | 85 | // Initialize the values of a new node 86 | public boolean InitNew(Element v_elem, List v_next, boolean v_end){ 87 | end = v_end ; 88 | elem = v_elem ; 89 | next = v_next ; 90 | return true ; 91 | } 92 | 93 | // Insert a new node at the beginning of the list 94 | public List Insert(Element new_elem){ 95 | boolean ret_val ; 96 | List aux03 ; 97 | List aux02 ; 98 | aux03 = this ; 99 | aux02 = new List(); 100 | ret_val = aux02.InitNew(new_elem,aux03,false); 101 | return aux02 ; 102 | } 103 | 104 | 105 | // Update the the pointer to the next node 106 | public boolean SetNext(List v_next){ 107 | next = v_next ; 108 | return true ; 109 | } 110 | 111 | // Delete an element e from the list 112 | public List Delete(Element e){ 113 | List my_head ; 114 | boolean ret_val ; 115 | boolean aux05; 116 | List aux01 ; 117 | List prev ; 118 | boolean var_end ; 119 | Element var_elem ; 120 | int aux04 ; 121 | int nt ; 122 | 123 | 124 | my_head = this ; 125 | ret_val = false ; 126 | aux04 = 0 - 1 ; 127 | aux01 = this ; 128 | prev = this ; 129 | var_end = end; 130 | var_elem = elem ; 131 | while ((!var_end) && (!ret_val)){ 132 | if (e.Equal(var_elem)){ 133 | ret_val = true ; 134 | if (aux04 < 0) { 135 | // delete first element 136 | my_head = aux01.GetNext() ; 137 | } 138 | else{ // delete a non first element 139 | System.out.println(0-555); 140 | aux05 = prev.SetNext(aux01.GetNext()); 141 | System.out.println(0-555); 142 | 143 | } 144 | } else nt = 0 ; 145 | if (!ret_val){ 146 | prev = aux01 ; 147 | aux01 = aux01.GetNext() ; 148 | var_end = aux01.GetEnd(); 149 | var_elem = aux01.GetElem(); 150 | aux04 = 1 ; 151 | } else nt = 0 ; 152 | } 153 | return my_head ; 154 | } 155 | 156 | 157 | // Search for an element e on the list 158 | public int Search(Element e){ 159 | int int_ret_val ; 160 | List aux01 ; 161 | Element var_elem ; 162 | boolean var_end ; 163 | int nt ; 164 | 165 | int_ret_val = 0 ; 166 | aux01 = this ; 167 | var_end = end; 168 | var_elem = elem ; 169 | while (!var_end){ 170 | if (e.Equal(var_elem)){ 171 | int_ret_val = 1 ; 172 | } 173 | else nt = 0 ; 174 | aux01 = aux01.GetNext() ; 175 | var_end = aux01.GetEnd(); 176 | var_elem = aux01.GetElem(); 177 | } 178 | return int_ret_val ; 179 | } 180 | 181 | public boolean GetEnd(){ 182 | return end ; 183 | } 184 | 185 | public Element GetElem(){ 186 | return elem ; 187 | } 188 | 189 | public List GetNext(){ 190 | return next ; 191 | } 192 | 193 | 194 | // Print the linked list 195 | public boolean Print(){ 196 | List aux01 ; 197 | boolean var_end ; 198 | Element var_elem ; 199 | 200 | aux01 = this ; 201 | var_end = end ; 202 | var_elem = elem ; 203 | while (!var_end){ 204 | System.out.println(var_elem.GetAge()); 205 | aux01 = aux01.GetNext() ; 206 | var_end = aux01.GetEnd(); 207 | var_elem = aux01.GetElem(); 208 | } 209 | 210 | return true ; 211 | } 212 | } 213 | 214 | 215 | // this class invokes the methods to insert, delete, 216 | // search and print the linked list 217 | class LL{ 218 | 219 | public int Start(){ 220 | 221 | List head ; 222 | List last_elem ; 223 | boolean aux01 ; 224 | Element el01 ; 225 | Element el02 ; 226 | Element el03 ; 227 | 228 | last_elem = new List(); 229 | aux01 = last_elem.Init(); 230 | head = last_elem ; 231 | aux01 = head.Init(); 232 | aux01 = head.Print(); 233 | 234 | // inserting first element 235 | el01 = new Element(); 236 | aux01 = el01.Init(25,37000,false); 237 | head = head.Insert(el01); 238 | aux01 = head.Print(); 239 | System.out.println(10000000); 240 | // inserting second element 241 | el01 = new Element(); 242 | aux01 = el01.Init(39,42000,true); 243 | el02 = el01 ; 244 | head = head.Insert(el01); 245 | aux01 = head.Print(); 246 | System.out.println(10000000); 247 | // inserting third element 248 | el01 = new Element(); 249 | aux01 = el01.Init(22,34000,false); 250 | head = head.Insert(el01); 251 | aux01 = head.Print(); 252 | el03 = new Element(); 253 | aux01 = el03.Init(27,34000,false); 254 | System.out.println(head.Search(el02)); 255 | System.out.println(head.Search(el03)); 256 | System.out.println(10000000); 257 | // inserting fourth element 258 | el01 = new Element(); 259 | aux01 = el01.Init(28,35000,false); 260 | head = head.Insert(el01); 261 | aux01 = head.Print(); 262 | System.out.println(2220000); 263 | 264 | head = head.Delete(el02); 265 | aux01 = head.Print(); 266 | System.out.println(33300000); 267 | 268 | 269 | head = head.Delete(el01); 270 | aux01 = head.Print(); 271 | System.out.println(44440000); 272 | 273 | return 0 ; 274 | 275 | 276 | } 277 | 278 | } 279 | -------------------------------------------------------------------------------- /programs/QuickSort.java: -------------------------------------------------------------------------------- 1 | class QuickSort{ 2 | public static void main(String[] a){ 3 | System.out.println(new QS().Start(10)); 4 | } 5 | } 6 | 7 | 8 | // This class contains the array of integers and 9 | // methods to initialize, print and sort the array 10 | // using Quicksort 11 | class QS{ 12 | 13 | int[] number ; 14 | int size ; 15 | 16 | // Invoke the Initialization, Sort and Printing 17 | // Methods 18 | public int Start(int sz){ 19 | int aux01 ; 20 | aux01 = this.Init(sz); 21 | aux01 = this.Print(); 22 | System.out.println(9999); 23 | aux01 = size - 1 ; 24 | aux01 = this.Sort(0,aux01); 25 | aux01 = this.Print(); 26 | return 0 ; 27 | } 28 | 29 | 30 | // Sort array of integers using Quicksort method 31 | public int Sort(int left, int right){ 32 | int v ; 33 | int i ; 34 | int j ; 35 | int nt; 36 | int t ; 37 | boolean cont01; 38 | boolean cont02; 39 | int aux03 ; 40 | t = 0 ; 41 | if (left < right){ 42 | v = number[right] ; 43 | i = left - 1 ; 44 | j = right ; 45 | cont01 = true ; 46 | while (cont01){ 47 | cont02 = true ; 48 | while (cont02){ 49 | i = i + 1 ; 50 | aux03 = number[i] ; 51 | if (!(aux03 list; 8 | 9 | public ClassDeclList() { 10 | list = new ArrayList(); 11 | } 12 | 13 | public void addElement(ClassDecl classDecl) { 14 | list.add(classDecl); 15 | } 16 | 17 | public ClassDecl elementAt(int index) { 18 | return list.get(index); 19 | } 20 | 21 | public int size() { 22 | return list.size(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ast/ClassDeclSimple.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class ClassDeclSimple implements ClassDecl { 6 | private Identifier classId; 7 | private VarDeclList fields; 8 | private MethodDeclList methods; 9 | 10 | public ClassDeclSimple(Identifier classId, VarDeclList fields, MethodDeclList methods) { 11 | this.classId = classId; 12 | this.fields = fields; 13 | this.methods = methods; 14 | } 15 | 16 | public Identifier getClassId() { 17 | return classId; 18 | } 19 | 20 | public VarDeclList getFields() { 21 | return fields; 22 | } 23 | 24 | public MethodDeclList getMethods() { 25 | return methods; 26 | } 27 | 28 | public void accept(Visitor v) { 29 | v.visit(this); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/ast/Exp.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public interface Exp { 6 | public void accept(Visitor v); 7 | } 8 | -------------------------------------------------------------------------------- /src/ast/ExpList.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class ExpList { 7 | private List list; 8 | 9 | public ExpList() { 10 | list = new ArrayList(); 11 | } 12 | 13 | public void addElement(Exp exp) { 14 | list.add(exp); 15 | } 16 | 17 | public Exp elementAt(int index) { 18 | return list.get(index); 19 | } 20 | 21 | public int size() { 22 | return list.size(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ast/False.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class False implements Exp { 6 | public void accept(Visitor v) { 7 | v.visit(this); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/ast/Formal.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class Formal { 6 | private Type type; 7 | private Identifier id; 8 | 9 | public Formal(Type type, Identifier id) { 10 | this.type = type; 11 | this.id = id; 12 | } 13 | 14 | public Type getType() { 15 | return type; 16 | } 17 | 18 | public Identifier getId() { 19 | return id; 20 | } 21 | 22 | public void accept(Visitor v) { 23 | v.visit(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/ast/FormalList.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class FormalList { 7 | private List list; 8 | 9 | public FormalList() { 10 | list = new ArrayList(); 11 | } 12 | 13 | public void addElement(Formal param) { 14 | list.add(param); 15 | } 16 | 17 | public Formal elementAt(int index) { 18 | return list.get(index); 19 | } 20 | 21 | public int size() { 22 | return list.size(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ast/Identifier.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class Identifier { 6 | private String name; 7 | 8 | public Identifier(String name) { 9 | this.name = name; 10 | } 11 | 12 | public String getName() { 13 | return name; 14 | } 15 | 16 | public void accept(Visitor v) { 17 | v.visit(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ast/IdentifierExp.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class IdentifierExp implements Exp { 6 | private String name; 7 | 8 | public IdentifierExp(String name) { 9 | this.name = name; 10 | } 11 | 12 | public String getName() { 13 | return name; 14 | } 15 | 16 | public void accept(Visitor v) { 17 | v.visit(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ast/IdentifierType.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class IdentifierType implements Type { 6 | private String name; 7 | 8 | public IdentifierType(String name) { 9 | this.name = name; 10 | } 11 | 12 | public String getName() { 13 | return name; 14 | } 15 | 16 | public void accept(Visitor v) { 17 | v.visit(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ast/If.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class If implements Statement { 6 | private Exp condExp; 7 | private Statement trueStm, falseStm; 8 | 9 | public If(Exp condExp, Statement trueStm, Statement falseStm) { 10 | this.condExp = condExp; 11 | this.trueStm = trueStm; 12 | this.falseStm = falseStm; 13 | } 14 | 15 | public Exp getCondExp() { 16 | return condExp; 17 | } 18 | 19 | public Statement getTrueStm() { 20 | return trueStm; 21 | } 22 | 23 | public Statement getFalseStm() { 24 | return falseStm; 25 | } 26 | 27 | public void accept(Visitor v) { 28 | v.visit(this); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/ast/IntArrayType.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class IntArrayType implements Type { 6 | public void accept(Visitor v) { 7 | v.visit(this); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/ast/IntegerLiteral.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class IntegerLiteral implements Exp { 6 | private int value; 7 | 8 | public IntegerLiteral(int value) { 9 | this.value = value; 10 | } 11 | 12 | public int getValue() { 13 | return value; 14 | } 15 | 16 | public void accept(Visitor v) { 17 | v.visit(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ast/IntegerType.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class IntegerType implements Type { 6 | public void accept(Visitor v) { 7 | v.visit(this); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/ast/LessThan.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class LessThan implements Exp { 6 | private Exp lhs, rhs; 7 | 8 | public LessThan(Exp lhs, Exp rhs) { 9 | this.lhs = lhs; 10 | this.rhs = rhs; 11 | } 12 | 13 | public Exp getLHS() { 14 | return lhs; 15 | } 16 | 17 | public Exp getRHS() { 18 | return rhs; 19 | } 20 | 21 | public void accept(Visitor v) { 22 | v.visit(this); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ast/MainClass.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class MainClass { 6 | private Identifier classId, argId; 7 | private Statement stm; 8 | 9 | public MainClass(Identifier classId, Identifier argId, Statement stm) { 10 | this.classId = classId; 11 | this.argId = argId; 12 | this.stm = stm; 13 | } 14 | 15 | public Identifier getClassId() { 16 | return classId; 17 | } 18 | 19 | public Identifier getArgId() { 20 | return argId; 21 | } 22 | 23 | public Statement getStm() { 24 | return stm; 25 | } 26 | 27 | public void accept(Visitor v) { 28 | v.visit(this); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/ast/MethodDecl.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class MethodDecl { 6 | private Type returnType; 7 | private Identifier id; 8 | private FormalList params; 9 | private VarDeclList vars; 10 | private StatementList stms; 11 | private Exp returnExp; 12 | 13 | public MethodDecl(Type returnType, Identifier id, FormalList params, 14 | VarDeclList vars, StatementList stms, Exp returnExp) { 15 | 16 | this.returnType = returnType; 17 | this.id = id; 18 | this.params = params; 19 | this.vars = vars; 20 | this.stms = stms; 21 | this.returnExp = returnExp; 22 | } 23 | 24 | public Type getReturnType() { 25 | return returnType; 26 | } 27 | 28 | public Identifier getId() { 29 | return id; 30 | } 31 | 32 | public FormalList getParams() { 33 | return params; 34 | } 35 | 36 | public VarDeclList getVars() { 37 | return vars; 38 | } 39 | 40 | public StatementList getStms() { 41 | return stms; 42 | } 43 | 44 | public Exp getReturnExp() { 45 | return returnExp; 46 | } 47 | 48 | public void accept(Visitor v) { 49 | v.visit(this); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/ast/MethodDeclList.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class MethodDeclList { 7 | private List list; 8 | 9 | public MethodDeclList() { 10 | list = new ArrayList(); 11 | } 12 | 13 | public void addElement(MethodDecl methodDecl) { 14 | list.add(methodDecl); 15 | } 16 | 17 | public MethodDecl elementAt(int index) { 18 | return list.get(index); 19 | } 20 | 21 | public int size() { 22 | return list.size(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ast/Minus.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class Minus implements Exp { 6 | private Exp lhs, rhs; 7 | 8 | public Minus(Exp lhs, Exp rhs) { 9 | this.lhs = lhs; 10 | this.rhs = rhs; 11 | } 12 | 13 | public Exp getLHS() { 14 | return lhs; 15 | } 16 | 17 | public Exp getRHS() { 18 | return rhs; 19 | } 20 | 21 | public void accept(Visitor v) { 22 | v.visit(this); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ast/NewArray.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class NewArray implements Exp { 6 | private Exp arraySize; 7 | 8 | public NewArray(Exp arraySize) { 9 | this.arraySize = arraySize; 10 | } 11 | 12 | public Exp getArraySize() { 13 | return arraySize; 14 | } 15 | 16 | public void accept(Visitor v) { 17 | v.visit(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ast/NewObject.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class NewObject implements Exp { 6 | private Identifier id; 7 | 8 | public NewObject(Identifier id) { 9 | this.id = id; 10 | } 11 | 12 | public Identifier getId() { 13 | return id; 14 | } 15 | 16 | public void accept(Visitor v) { 17 | v.visit(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ast/Not.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class Not implements Exp { 6 | private Exp exp; 7 | 8 | public Not(Exp exp) { 9 | this.exp = exp; 10 | } 11 | 12 | public Exp getExp() { 13 | return exp; 14 | } 15 | 16 | public void accept(Visitor v) { 17 | v.visit(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ast/Plus.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class Plus implements Exp { 6 | private Exp lhs, rhs; 7 | 8 | public Plus(Exp lhs, Exp rhs) { 9 | this.lhs = lhs; 10 | this.rhs = rhs; 11 | } 12 | 13 | public Exp getLHS() { 14 | return lhs; 15 | } 16 | 17 | public Exp getRHS() { 18 | return rhs; 19 | } 20 | 21 | public void accept(Visitor v) { 22 | v.visit(this); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ast/Print.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class Print implements Statement { 6 | private Exp exp; 7 | 8 | public Print(Exp exp) { 9 | this.exp = exp; 10 | } 11 | 12 | public Exp getExp() { 13 | return exp; 14 | } 15 | 16 | public void accept(Visitor v) { 17 | v.visit(this); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ast/Program.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class Program { 6 | private MainClass main; 7 | private ClassDeclList classList; 8 | 9 | public Program(MainClass main, ClassDeclList classList) { 10 | this.main = main; 11 | this.classList = classList; 12 | } 13 | 14 | public MainClass getMainClass() { 15 | return main; 16 | } 17 | 18 | public ClassDeclList getClassDeclList() { 19 | return classList; 20 | } 21 | 22 | public void accept(Visitor v) { 23 | v.visit(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/ast/Statement.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public interface Statement { 6 | public void accept(Visitor v); 7 | } 8 | -------------------------------------------------------------------------------- /src/ast/StatementList.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class StatementList { 7 | private List list; 8 | 9 | public StatementList() { 10 | list = new ArrayList(); 11 | } 12 | 13 | public void addElement(Statement stm) { 14 | list.add(stm); 15 | } 16 | 17 | public Statement elementAt(int index) { 18 | return list.get(index); 19 | } 20 | 21 | public int size() { 22 | return list.size(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ast/This.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class This implements Exp { 6 | public void accept(Visitor v) { 7 | v.visit(this); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/ast/Times.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class Times implements Exp { 6 | private Exp lhs, rhs; 7 | 8 | public Times(Exp lhs, Exp rhs) { 9 | this.lhs = lhs; 10 | this.rhs = rhs; 11 | } 12 | 13 | public Exp getLHS() { 14 | return lhs; 15 | } 16 | 17 | public Exp getRHS() { 18 | return rhs; 19 | } 20 | 21 | public void accept(Visitor v) { 22 | v.visit(this); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ast/True.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class True implements Exp { 6 | public void accept(Visitor v) { 7 | v.visit(this); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/ast/Type.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public interface Type { 6 | public void accept(Visitor v); 7 | } 8 | -------------------------------------------------------------------------------- /src/ast/VarDecl.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class VarDecl { 6 | private Type type; 7 | private Identifier id; 8 | 9 | public VarDecl(Type type, Identifier id) { 10 | this.type = type; 11 | this.id = id; 12 | } 13 | 14 | public Type getType() { 15 | return type; 16 | } 17 | 18 | public Identifier getId() { 19 | return id; 20 | } 21 | 22 | public void accept(Visitor v) { 23 | v.visit(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/ast/VarDeclList.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class VarDeclList { 7 | private List list; 8 | 9 | public VarDeclList() { 10 | list = new ArrayList(); 11 | } 12 | 13 | public void addElement(VarDecl varDecl) { 14 | list.add(varDecl); 15 | } 16 | 17 | public VarDecl elementAt(int index) { 18 | return list.get(index); 19 | } 20 | 21 | public int size() { 22 | return list.size(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ast/While.java: -------------------------------------------------------------------------------- 1 | package ast; 2 | 3 | import visitor.Visitor; 4 | 5 | public class While implements Statement { 6 | private Exp condExp; 7 | private Statement stm; 8 | 9 | public While(Exp condExp, Statement stm) { 10 | this.condExp = condExp; 11 | this.stm = stm; 12 | } 13 | 14 | public Exp getCondExp() { 15 | return condExp; 16 | } 17 | 18 | public Statement getStm() { 19 | return stm; 20 | } 21 | 22 | public void accept(Visitor v) { 23 | v.visit(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/parser/Lexer.java: -------------------------------------------------------------------------------- 1 | package parser; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.FileReader; 5 | import java.io.IOException; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /* 10 | * 11 | * Lexer is given a file and returns the next token from the character stream. 12 | * The token is grabbed from the getToken() method. This is used by the parser 13 | * during the next phase of compilation. If a token is unrecognizable, then it 14 | * is returned with a type of UNKNOWN. A token of type EOF is returned by the 15 | * lexer when the character stream has been entirely consumed. The lexer also 16 | * records the semantic values for token types ID (idVal) and INT_CONST 17 | * (intVal). Line and column numbers are calculated and stored with each token. 18 | * 19 | */ 20 | 21 | public class Lexer { 22 | private BufferedReader stream; // stream of characters to be processed 23 | private String idVal; // semantic value for ID token types 24 | private int intVal; // semantic value for INT_CONST token types 25 | private int nextChar; 26 | private int lineNum = 1, colNum = 1; // current line and column numbers 27 | private Token next; // used by peek() 28 | 29 | // hash tables for fast lookup 30 | private final static Map reservedWords; 31 | private final static Map punctuation; 32 | 33 | // initialize hash tables statically 34 | static { 35 | reservedWords = new HashMap(); 36 | reservedWords.put("boolean", TokenType.BOOLEAN); 37 | reservedWords.put("class", TokenType.CLASS); 38 | reservedWords.put("else", TokenType.ELSE); 39 | reservedWords.put("extends", TokenType.EXTENDS); 40 | reservedWords.put("false", TokenType.FALSE); 41 | reservedWords.put("if", TokenType.IF); 42 | reservedWords.put("int", TokenType.INT); 43 | reservedWords.put("main", TokenType.MAIN); 44 | reservedWords.put("new", TokenType.NEW); 45 | reservedWords.put("public", TokenType.PUBLIC); 46 | reservedWords.put("return", TokenType.RETURN); 47 | reservedWords.put("static", TokenType.STATIC); 48 | reservedWords.put("String", TokenType.STRING); 49 | reservedWords.put("this", TokenType.THIS); 50 | reservedWords.put("true", TokenType.TRUE); 51 | reservedWords.put("void", TokenType.VOID); 52 | reservedWords.put("while", TokenType.WHILE); 53 | 54 | punctuation = new HashMap(); 55 | punctuation.put('(', TokenType.LPAREN); 56 | punctuation.put(')', TokenType.RPAREN); 57 | punctuation.put('[', TokenType.LBRACKET); 58 | punctuation.put(']', TokenType.RBRACKET); 59 | punctuation.put('{', TokenType.LBRACE); 60 | punctuation.put('}', TokenType.RBRACE); 61 | punctuation.put(';', TokenType.SEMI); 62 | punctuation.put(',', TokenType.COMMA); 63 | punctuation.put('.', TokenType.DOT); 64 | punctuation.put('=', TokenType.ASSIGN); 65 | punctuation.put('!', TokenType.BANG); 66 | } 67 | 68 | public Lexer(FileReader file) { 69 | this.stream = new BufferedReader(file); 70 | nextChar = getChar(); 71 | } 72 | 73 | // called by parser when token type is ID 74 | public String getIdVal() { 75 | return idVal; 76 | } 77 | 78 | // called by parser when token type is INT_CONST 79 | public int getIntVal() { 80 | return intVal; 81 | } 82 | 83 | // handles I/O for char stream 84 | private int getChar() { 85 | try { 86 | return stream.read(); 87 | } catch (IOException e) { 88 | System.err.println("IOException occured in Lexer::getChar()"); 89 | return -1; 90 | } 91 | } 92 | 93 | // detect and skip possible '\n', '\r' and '\rn' line breaks 94 | private boolean skipNewline() { 95 | if (nextChar == '\n') { 96 | lineNum++; 97 | colNum = 1; 98 | nextChar = getChar(); 99 | 100 | return true; 101 | } 102 | 103 | if (nextChar == '\r') { 104 | lineNum++; 105 | colNum = 1; 106 | nextChar = getChar(); 107 | 108 | // skip over next char if '\n' 109 | if (nextChar == '\n') 110 | nextChar = getChar(); 111 | 112 | return true; 113 | } 114 | 115 | // newline char not found 116 | return false; 117 | } 118 | 119 | // return the next token without "consuming" it 120 | public Token peek() { 121 | // advance token only if its been reset by getToken() 122 | if (next == null) 123 | next = getToken(); 124 | 125 | return next; 126 | } 127 | 128 | // retrieves the next token in the input stream (EOF signals end of input) 129 | public Token getToken() { 130 | // check if peek() was called 131 | if (next != null) { 132 | Token token = next; 133 | next = null; // allow peek to call for next token 134 | return token; 135 | } 136 | 137 | // skip whitespace 138 | while (Character.isWhitespace(nextChar)) { 139 | // check if whitespace char is a newline 140 | if (!skipNewline()) { 141 | colNum++; 142 | nextChar = getChar(); 143 | } 144 | 145 | // offset colNum for tab chars 146 | if (nextChar == '\t') 147 | colNum += 3; 148 | } 149 | 150 | // identifier or reserved word ([a-zA-Z][a-zA-Z0-9_]*) 151 | if (Character.isLetter(nextChar)) { 152 | // create new idVal starting with first char of identifier 153 | idVal = Character.toString((char) nextChar); 154 | colNum++; 155 | nextChar = getChar(); 156 | 157 | // include remaining seq. of chars that are letters, digits, or _ 158 | while (Character.isLetterOrDigit(nextChar) || nextChar == '_') { 159 | idVal += (char) nextChar; 160 | colNum++; 161 | nextChar = getChar(); 162 | } 163 | 164 | // check if identifier is a reserved word 165 | TokenType type = reservedWords.get(idVal); 166 | if (type != null) 167 | return new Token(type, lineNum, colNum - idVal.length()); 168 | 169 | // token is an identifier 170 | return new Token(TokenType.ID, lineNum, colNum - idVal.length()); 171 | } 172 | 173 | // integer literal ([0-9]+) 174 | if (Character.isDigit(nextChar)) { 175 | // create string representation of number 176 | String numString = Character.toString((char) nextChar); 177 | colNum++; 178 | nextChar = getChar(); 179 | 180 | // concatenate remaining seq. of digits 181 | while (Character.isDigit(nextChar)) { 182 | numString += (char) nextChar; 183 | colNum++; 184 | nextChar = getChar(); 185 | } 186 | 187 | // convert string representation to integer value 188 | intVal = Integer.parseInt(numString); 189 | 190 | return new Token(TokenType.INT_CONST, lineNum, colNum - numString.length()); 191 | } 192 | 193 | // check for start of comment 194 | if (nextChar == '/') { 195 | colNum++; 196 | nextChar = getChar(); 197 | 198 | // single-line comment (skip to the next line) 199 | if (nextChar == '/') { 200 | do { 201 | colNum++; 202 | nextChar = getChar(); 203 | } while (!skipNewline() && nextChar != -1); 204 | 205 | // grab next token 206 | return getToken(); 207 | } 208 | 209 | // multi-line comment (skip input until matching '*/' is found) 210 | if (nextChar == '*') { 211 | colNum++; 212 | nextChar = getChar(); 213 | 214 | // keep track of nesting level 215 | int nestingLevel = 1; 216 | while (nestingLevel > 0) { 217 | if (nextChar == '*') { 218 | // check if it closes a comment 219 | colNum++; 220 | nextChar = getChar(); 221 | 222 | if (nextChar == '/') { 223 | nestingLevel--; 224 | colNum++; 225 | nextChar = getChar(); 226 | } 227 | 228 | } else if (nextChar == '/') { 229 | // check if it starts a nested comment 230 | colNum++; 231 | nextChar = getChar(); 232 | 233 | if (nextChar == '*') { 234 | nestingLevel++; 235 | colNum++; 236 | nextChar = getChar(); 237 | } 238 | 239 | } else { 240 | // check if EOF is reached before comment is terminated 241 | if (nextChar == -1) 242 | break; 243 | 244 | // process newline chars 245 | if (!skipNewline()) { 246 | colNum++; 247 | nextChar = getChar(); 248 | } 249 | 250 | } 251 | } 252 | 253 | // grab next token 254 | return getToken(); 255 | } 256 | 257 | // neither single-line nor multi-line comment 258 | return new Token(TokenType.UNKNOWN, lineNum, colNum - 1); 259 | } 260 | 261 | // EOF reached 262 | if (nextChar == -1) 263 | return new Token(TokenType.EOF, lineNum, colNum); 264 | 265 | // check for binops 266 | switch (nextChar) { 267 | 268 | case '&': 269 | colNum++; 270 | nextChar = getChar(); 271 | 272 | // check if next char is '&' to match '&&' binop 273 | if (nextChar == '&') { 274 | nextChar = getChar(); 275 | return new Token(TokenType.AND, lineNum, colNum - 2); 276 | } else 277 | return new Token(TokenType.UNKNOWN, lineNum, colNum - 1); 278 | 279 | case '<': 280 | colNum++; 281 | nextChar = getChar(); 282 | return new Token(TokenType.LT, lineNum, colNum - 1); 283 | 284 | case '+': 285 | colNum++; 286 | nextChar = getChar(); 287 | return new Token(TokenType.PLUS, lineNum, colNum - 1); 288 | 289 | case '-': 290 | colNum++; 291 | nextChar = getChar(); 292 | return new Token(TokenType.MINUS, lineNum, colNum - 1); 293 | 294 | case '*': 295 | colNum++; 296 | nextChar = getChar(); 297 | return new Token(TokenType.TIMES, lineNum, colNum - 1); 298 | } 299 | 300 | // check for punctuation 301 | TokenType type = punctuation.get((char) nextChar); 302 | colNum++; 303 | nextChar = getChar(); 304 | 305 | // found punctuation token 306 | if (type != null) 307 | return new Token(type, lineNum, colNum - 1); 308 | 309 | // token type is unknown 310 | return new Token(TokenType.UNKNOWN, lineNum, colNum - 1); 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /src/parser/Parser.java: -------------------------------------------------------------------------------- 1 | package parser; 2 | 3 | import java.io.FileReader; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import ast.*; 8 | 9 | /* 10 | * 11 | * Parser passes on a file to the lexer to be tokenized. The parser uses a 12 | * recursive-descent method of parsing and also integrates the idea of 13 | * operator-precedence parsing to correctly deal with parsing binary operator 14 | * expressions. Syntactic errors are reported by the parser to the console and 15 | * proper error recovery is implemented (eventually) to minimize the cascading 16 | * of errors. ASTs are produced by the parser for use in the semantic analysis 17 | * phase and for generating the IR. 18 | * 19 | */ 20 | 21 | public class Parser { 22 | private Lexer lexer; 23 | private Token token; 24 | private Exp objectMethodCall; // used for parsing exps with dot operator 25 | private int errors; 26 | private Token errorToken; 27 | 28 | // hash table for operator precedence levels 29 | private final static Map binopLevels; 30 | 31 | static { 32 | binopLevels = new HashMap(); 33 | binopLevels.put(TokenType.AND, 10); 34 | binopLevels.put(TokenType.LT, 20); 35 | binopLevels.put(TokenType.PLUS, 30); 36 | binopLevels.put(TokenType.MINUS, 30); 37 | binopLevels.put(TokenType.TIMES, 40); 38 | binopLevels.put(TokenType.DOT, 50); // method calls 39 | binopLevels.put(TokenType.LBRACKET, 50); // array look-up 40 | } 41 | 42 | public Parser(FileReader file) { 43 | lexer = new Lexer(file); 44 | token = lexer.getToken(); // prime the pump 45 | } 46 | 47 | // verifies current token type and grabs next token or reports error 48 | private boolean eat(TokenType type) { 49 | if (token.getType() == type) { 50 | token = lexer.getToken(); 51 | return true; 52 | } else { 53 | error(type); 54 | return false; 55 | } 56 | } 57 | 58 | // skip tokens until match in follow set for error recovery 59 | private void skipTo(TokenType... follow) { 60 | while (token.getType() != TokenType.EOF) { 61 | for (TokenType skip : follow) { 62 | if (token.getType() == skip) 63 | return; 64 | } 65 | token = lexer.getToken(); 66 | } 67 | } 68 | 69 | // reports an error to the console 70 | private void error(TokenType type) { 71 | // only report error once per erroneous token 72 | if (token == errorToken) 73 | return; 74 | 75 | // print error report 76 | System.err.print("ERROR: " + token.getType()); 77 | System.err.print(" at line " + token.getLineNum() + ", column " + token.getColNum()); 78 | System.err.println("; Expected " + type); 79 | 80 | errorToken = token; // set error token to prevent cascading 81 | errors++; // increment error counter 82 | } 83 | 84 | // number of reported syntax errors 85 | public int getErrorCount() { 86 | return errors; 87 | } 88 | 89 | // a helper method for parsing an identifier 90 | private Identifier parseIdentifier() { 91 | Identifier id = null; 92 | 93 | // grab ID value if token type is ID 94 | if (token.getType() == TokenType.ID) 95 | id = new Identifier(lexer.getIdVal()); 96 | 97 | eat(TokenType.ID); 98 | 99 | return id; 100 | } 101 | 102 | // top-level parsing method: MainClass ClassDecl* 103 | public Program parseProgram() { 104 | MainClass main = parseMainClass(); 105 | 106 | ClassDeclList classList = new ClassDeclList(); 107 | while (token.getType() != TokenType.EOF) 108 | classList.addElement(parseClassDecl()); 109 | 110 | return new Program(main, classList); 111 | } 112 | 113 | // Class w/ main method: 114 | // class id { public static void main ( String [] id ) { Statement } } 115 | private MainClass parseMainClass() { 116 | if (!eat(TokenType.CLASS)) 117 | skipTo(TokenType.ID, TokenType.LBRACE, TokenType.RBRACE); 118 | 119 | // check for class identifier name 120 | Identifier className = parseIdentifier(); 121 | 122 | if (!eat(TokenType.LBRACE)) 123 | skipTo(TokenType.PUBLIC, TokenType.STATIC, TokenType.VOID, 124 | TokenType.MAIN, TokenType.LPAREN, TokenType.RPAREN); 125 | 126 | if (!eat(TokenType.PUBLIC)) 127 | skipTo(TokenType.STATIC, TokenType.VOID, TokenType.MAIN, 128 | TokenType.LPAREN, TokenType.RPAREN); 129 | 130 | if (!eat(TokenType.STATIC)) 131 | skipTo(TokenType.VOID, TokenType.MAIN, TokenType.LPAREN, 132 | TokenType.RPAREN); 133 | 134 | if (!eat(TokenType.VOID)) 135 | skipTo(TokenType.MAIN, TokenType.LPAREN, TokenType.RPAREN); 136 | 137 | if (!eat(TokenType.MAIN)) 138 | skipTo(TokenType.LPAREN, TokenType.RPAREN); 139 | 140 | if (!eat(TokenType.LPAREN)) 141 | skipTo(TokenType.STRING, TokenType.LBRACKET, TokenType.ID, 142 | TokenType.RPAREN, TokenType.LBRACE, TokenType.RBRACE); 143 | 144 | if (!eat(TokenType.STRING)) 145 | skipTo(TokenType.LBRACKET, TokenType.ID, TokenType.RPAREN, 146 | TokenType.LBRACE, TokenType.RBRACE); 147 | 148 | if (!eat(TokenType.LBRACKET)) 149 | skipTo(TokenType.RBRACKET, TokenType.ID, TokenType.RPAREN, 150 | TokenType.LBRACE, TokenType.RBRACE); 151 | 152 | if (!eat(TokenType.RBRACKET)) 153 | skipTo(TokenType.ID, TokenType.RPAREN, TokenType.LBRACE, 154 | TokenType.RBRACE); 155 | 156 | Identifier argName = parseIdentifier(); 157 | 158 | if (!eat(TokenType.RPAREN)) 159 | skipTo(TokenType.LBRACE, TokenType.RBRACE); 160 | 161 | if (!eat(TokenType.LBRACE)) 162 | skipTo(TokenType.RBRACE); 163 | 164 | Statement stm = parseStatement(); 165 | 166 | if (!eat(TokenType.RBRACE)) 167 | skipTo(TokenType.RBRACE, TokenType.CLASS); 168 | 169 | if (!eat(TokenType.RBRACE)) 170 | skipTo(TokenType.CLASS); 171 | 172 | return new MainClass(className, argName, stm); 173 | } 174 | 175 | /* 176 | * Class declaration w/out main method: 177 | * class id { VarDecl* MethodDecl* } 178 | * class id extends id { VarDecl* MethodDecl* } 179 | */ 180 | private ClassDecl parseClassDecl() { 181 | eat(TokenType.CLASS); 182 | 183 | Identifier className = parseIdentifier(); 184 | 185 | VarDeclList fields = new VarDeclList(); 186 | MethodDeclList methods = new MethodDeclList(); 187 | 188 | // check whether class extends a superclass or not 189 | if (token.getType() == TokenType.EXTENDS) { 190 | eat(TokenType.EXTENDS); 191 | 192 | // check for superclass identifier name 193 | Identifier superName = parseIdentifier(); 194 | 195 | if (!eat(TokenType.LBRACE)) skipTo(TokenType.RBRACE); 196 | 197 | // parse entire class body 198 | while (token.getType() != TokenType.RBRACE && token.getType() != TokenType.EOF) { 199 | // parse method or field 200 | if (token.getType() == TokenType.PUBLIC) 201 | methods.addElement(parseMethodDecl()); 202 | else 203 | fields.addElement(parseVarDecl()); 204 | } 205 | if (!eat(TokenType.RBRACE)) skipTo(TokenType.CLASS); 206 | 207 | return new ClassDeclExtends(className, superName, fields, methods); 208 | 209 | } else { 210 | if (!eat(TokenType.LBRACE)) 211 | skipTo(TokenType.RBRACE); 212 | 213 | // parse entire class body 214 | while (token.getType() != TokenType.RBRACE && token.getType() != TokenType.EOF) { 215 | // parse method or field 216 | if (token.getType() == TokenType.PUBLIC) 217 | methods.addElement(parseMethodDecl()); 218 | else 219 | fields.addElement(parseVarDecl()); 220 | } 221 | if (!eat(TokenType.RBRACE)) skipTo(TokenType.CLASS); 222 | 223 | return new ClassDeclSimple(className, fields, methods); 224 | 225 | } 226 | } 227 | 228 | private Statement parseStatement() { 229 | // Statement block: { Statement* } 230 | if (token.getType() == TokenType.LBRACE) { 231 | eat(TokenType.LBRACE); 232 | 233 | // recursively call parseStatement() until closing brace 234 | StatementList stms = new StatementList(); 235 | while (token.getType() != TokenType.RBRACE && token.getType() != TokenType.EOF) 236 | stms.addElement(parseStatement()); 237 | 238 | if (!eat(TokenType.RBRACE)) 239 | skipTo(TokenType.RBRACE, TokenType.SEMI); 240 | 241 | return new Block(stms); 242 | } 243 | 244 | // If statement: if ( Exp ) Statement else Statement 245 | if (token.getType() == TokenType.IF) { 246 | eat(TokenType.IF); 247 | 248 | // parse conditional expression 249 | if (!eat(TokenType.LPAREN)) 250 | skipTo(TokenType.RPAREN, TokenType.LBRACE, TokenType.RBRACE); 251 | 252 | Exp condExp = parseExp(); 253 | 254 | if (!eat(TokenType.RPAREN)) 255 | skipTo(TokenType.LBRACE, TokenType.SEMI, TokenType.RBRACE); 256 | 257 | // parse true and false statements 258 | Statement trueStm = parseStatement(); 259 | 260 | if (!eat(TokenType.ELSE)) 261 | skipTo(TokenType.LBRACE, TokenType.SEMI, TokenType.RBRACE); 262 | 263 | Statement falseStm = parseStatement(); 264 | 265 | return new If(condExp, trueStm, falseStm); 266 | } 267 | 268 | // While statement: while ( Exp ) Statement 269 | if (token.getType() == TokenType.WHILE) { 270 | eat(TokenType.WHILE); 271 | 272 | // parse looping condition 273 | if (!eat(TokenType.LPAREN)) 274 | skipTo(TokenType.RPAREN, TokenType.LBRACE, TokenType.RBRACE); 275 | 276 | Exp condExp = parseExp(); 277 | 278 | if (!eat(TokenType.RPAREN)) 279 | skipTo(TokenType.LBRACE, TokenType.SEMI, TokenType.RBRACE); 280 | 281 | // parse looping statement 282 | Statement loopStm = parseStatement(); 283 | 284 | return new While(condExp, loopStm); 285 | } 286 | 287 | // Identifier statement 288 | if (token.getType() == TokenType.ID) { 289 | Identifier id = new Identifier(lexer.getIdVal()); 290 | eat(TokenType.ID); 291 | 292 | // Parse potential print statement: System.out.println ( Exp ) ; 293 | if (id.getName().equals("System") && token.getType() == TokenType.DOT) { 294 | eat(TokenType.DOT); 295 | 296 | if (token.getType() == TokenType.ID && lexer.getIdVal().equals("out")) 297 | eat(TokenType.ID); 298 | else { 299 | eat(TokenType.STATEMENT); 300 | return null; 301 | } 302 | 303 | if (!eat(TokenType.DOT)) { 304 | eat(TokenType.STATEMENT); 305 | return null; 306 | } 307 | 308 | if (token.getType() == TokenType.ID && lexer.getIdVal().equals("println")) 309 | eat(TokenType.ID); 310 | else { 311 | eat(TokenType.STATEMENT); 312 | return null; 313 | } 314 | 315 | if (!eat(TokenType.LPAREN)) 316 | skipTo(TokenType.RPAREN, TokenType.SEMI); 317 | 318 | Exp printExp = parseExp(); 319 | 320 | if (!eat(TokenType.RPAREN)) 321 | skipTo(TokenType.SEMI); 322 | 323 | eat(TokenType.SEMI); 324 | 325 | return new Print(printExp); 326 | } 327 | 328 | // Assignment statement: id = Exp ; 329 | if (token.getType() == TokenType.ASSIGN) { 330 | eat(TokenType.ASSIGN); 331 | Exp value = parseExp(); 332 | eat(TokenType.SEMI); 333 | 334 | return new Assign(id, value); 335 | } 336 | 337 | // Array value assignment statement: id [ Exp ] = Exp ; 338 | if (token.getType() == TokenType.LBRACKET) { 339 | eat(TokenType.LBRACKET); 340 | Exp index = parseExp(); 341 | 342 | if (!eat(TokenType.RBRACKET)) 343 | skipTo(TokenType.ASSIGN, TokenType.SEMI); 344 | 345 | if (!eat(TokenType.ASSIGN)) 346 | skipTo(TokenType.SEMI); 347 | 348 | Exp value = parseExp(); 349 | eat(TokenType.SEMI); 350 | 351 | return new ArrayAssign(id, index, value); 352 | } 353 | } 354 | 355 | // statement type unknown 356 | eat(TokenType.STATEMENT); 357 | token = lexer.getToken(); 358 | return null; 359 | } 360 | 361 | // top-level parsing function for an expression 362 | private Exp parseExp() { 363 | Exp lhs = parsePrimaryExp(); 364 | return parseBinopRHS(0, lhs); // check for binops following exp 365 | } 366 | 367 | // parse exp before any binop 368 | private Exp parsePrimaryExp() { 369 | switch (token.getType()) { 370 | 371 | case INT_CONST: 372 | int value = lexer.getIntVal(); 373 | eat(TokenType.INT_CONST); 374 | return new IntegerLiteral(value); 375 | 376 | case TRUE: 377 | eat(TokenType.TRUE); 378 | return new True(); 379 | 380 | case FALSE: 381 | eat(TokenType.FALSE); 382 | return new False(); 383 | 384 | case ID: 385 | Identifier id = parseIdentifier(); 386 | 387 | // the dot operator preceded current exp 388 | if (objectMethodCall != null) { 389 | // save exp before dot operator and reset for future parsing 390 | Exp obj = objectMethodCall; 391 | objectMethodCall = null; 392 | 393 | // check if its an array length lookup or an object method call 394 | if (id.getName().equals("length")) 395 | return new ArrayLength(obj); 396 | else { 397 | if (!eat(TokenType.LPAREN)) 398 | skipTo(TokenType.RPAREN); 399 | 400 | // collect arguments to method call 401 | ExpList args = new ExpList(); 402 | if (token.getType() != TokenType.RPAREN) { 403 | args.addElement(parseExp()); 404 | 405 | while (token.getType() == TokenType.COMMA) { 406 | eat(TokenType.COMMA); 407 | args.addElement(parseExp()); 408 | } 409 | } 410 | eat(TokenType.RPAREN); 411 | 412 | return new Call(obj, id, args); 413 | } 414 | } 415 | 416 | // if not preceded by dot operator, it is a simple id exp 417 | return new IdentifierExp(id.getName()); 418 | 419 | case THIS: 420 | eat(TokenType.THIS); 421 | return new This(); 422 | 423 | case BANG: 424 | eat(TokenType.BANG); 425 | return new Not(parseExp()); 426 | 427 | case LPAREN: 428 | eat(TokenType.LPAREN); 429 | Exp exp = parseExp(); 430 | eat(TokenType.RPAREN); 431 | return exp; 432 | 433 | case NEW: 434 | eat(TokenType.NEW); 435 | 436 | // check whether it is a new array or a new object instance 437 | if (token.getType() == TokenType.INT) { 438 | eat(TokenType.INT); 439 | eat(TokenType.LBRACKET); 440 | Exp arraySize = parseExp(); 441 | eat(TokenType.RBRACKET); 442 | return new NewArray(arraySize); 443 | } else { 444 | Identifier objectType = parseIdentifier(); 445 | eat(TokenType.LPAREN); 446 | eat(TokenType.RPAREN); 447 | return new NewObject(objectType); 448 | } 449 | 450 | default: 451 | // unrecognizable expression 452 | eat(TokenType.EXPRESSION); 453 | token = lexer.getToken(); 454 | return null; 455 | 456 | } 457 | } 458 | 459 | // parse expressions according to operator precedence levels 460 | private Exp parseBinopRHS(int level, Exp lhs) { 461 | // continuously parse exp until a lower order operator comes up 462 | while (true) { 463 | // grab operator precedence (-1 for non-operator token) 464 | Integer val = binopLevels.get(token.getType()); 465 | int tokenLevel = (val != null) ? val.intValue() : -1; 466 | 467 | // either op precedence is lower than prev op or token is not an op 468 | if (tokenLevel < level) 469 | return lhs; 470 | 471 | // save binop before parsing rhs of exp 472 | TokenType binop = token.getType(); 473 | eat(binop); 474 | 475 | // set objectMethodCall to lhs to deal with ambiguity of dot op 476 | if (binop == TokenType.DOT) 477 | objectMethodCall = lhs; 478 | 479 | Exp rhs = parsePrimaryExp(); // parse rhs of exp 480 | 481 | // grab operator precedence (-1 for non-operator token) 482 | val = binopLevels.get(token.getType()); 483 | int nextLevel = (val != null) ? val.intValue() : -1; 484 | 485 | // if next op has higher precedence than prev op, make recursive call 486 | if (tokenLevel < nextLevel) 487 | rhs = parseBinopRHS(tokenLevel + 1, rhs); 488 | 489 | // build AST for exp 490 | switch (binop) { 491 | case AND: 492 | lhs = new And(lhs, rhs); 493 | break; 494 | case LT: 495 | lhs = new LessThan(lhs, rhs); 496 | break; 497 | case PLUS: 498 | lhs = new Plus(lhs, rhs); 499 | break; 500 | case MINUS: 501 | lhs = new Minus(lhs, rhs); 502 | break; 503 | case TIMES: 504 | lhs = new Times(lhs, rhs); 505 | break; 506 | case LBRACKET: 507 | lhs = new ArrayLookup(lhs, rhs); 508 | eat(TokenType.RBRACKET); 509 | break; 510 | case DOT: 511 | lhs = rhs; 512 | break; 513 | default: 514 | eat(TokenType.OPERATOR); 515 | break; 516 | } 517 | } 518 | } 519 | 520 | // Variable declaration: Type id ; 521 | private VarDecl parseVarDecl() { 522 | Type type = parseType(); 523 | Identifier id = parseIdentifier(); 524 | eat(TokenType.SEMI); 525 | 526 | return new VarDecl(type, id); 527 | } 528 | 529 | // Method declaration: public Type id ( FormalList ) { VarDecl* Statement* return Exp ; } 530 | private MethodDecl parseMethodDecl() { 531 | if (!eat(TokenType.PUBLIC)) 532 | skipTo(TokenType.INT, TokenType.BOOLEAN, TokenType.ID, TokenType. 533 | LPAREN, TokenType.RPAREN, TokenType.LBRACE, TokenType.RBRACE); 534 | 535 | Type returnType = parseType(); 536 | Identifier methodName = parseIdentifier(); 537 | 538 | if (!eat(TokenType.LPAREN)) 539 | skipTo(TokenType.RPAREN, TokenType.LBRACE, TokenType.RBRACE); 540 | 541 | // collect formal params 542 | FormalList params = new FormalList(); 543 | if (token.getType() != TokenType.RPAREN) { 544 | params.addElement(parseFormal()); 545 | 546 | // check for additional params 547 | while (token.getType() == TokenType.COMMA) { 548 | eat(TokenType.COMMA); 549 | params.addElement(parseFormal()); 550 | } 551 | } 552 | 553 | if (!eat(TokenType.RPAREN)) 554 | skipTo(TokenType.LBRACE, TokenType.RBRACE); 555 | 556 | if (!eat(TokenType.LBRACE)) 557 | skipTo(TokenType.RBRACE); 558 | 559 | VarDeclList vars = new VarDeclList(); 560 | StatementList stms = new StatementList(); 561 | 562 | /* collect all var declarations and statements */ 563 | while (token.getType() != TokenType.RETURN && token.getType() != TokenType.EOF) { 564 | 565 | switch (token.getType()) { 566 | 567 | // int and boolean signals start of var declaration 568 | case INT: 569 | case BOOLEAN: 570 | vars.addElement(parseVarDecl()); 571 | break; 572 | 573 | // identifier requires peeking at next token to determine if 574 | // it's a var declaration or a statement in the method 575 | case ID: 576 | // id followed by another id is a var declaration 577 | if (lexer.peek().getType() == TokenType.ID) { 578 | vars.addElement(parseVarDecl()); 579 | break; 580 | } 581 | 582 | // otherwise it is a statement, fall through 583 | default: 584 | stms.addElement(parseStatement()); 585 | } 586 | } 587 | 588 | if (!eat(TokenType.RETURN)) 589 | skipTo(TokenType.SEMI, TokenType.RBRACE); 590 | 591 | Exp returnExp = parseExp(); 592 | 593 | if (!eat(TokenType.SEMI)) 594 | skipTo(TokenType.RBRACE); 595 | 596 | eat(TokenType.RBRACE); 597 | 598 | return new MethodDecl(returnType, methodName, params, vars, stms, returnExp); 599 | } 600 | 601 | /* 602 | * Type: 603 | * int (IntegerType) 604 | * int [] (IntArrayType) 605 | * boolean (BooleanType) 606 | * id (IdentifierType) 607 | */ 608 | private Type parseType() { 609 | switch (token.getType()) { 610 | 611 | case INT: 612 | eat(TokenType.INT); 613 | 614 | // check for integer array type 615 | if (token.getType() == TokenType.LBRACKET) { 616 | eat(TokenType.LBRACKET); 617 | 618 | if (token.getType() == TokenType.RBRACKET) { 619 | eat(TokenType.RBRACKET); 620 | return new IntArrayType(); 621 | } 622 | 623 | // invalid integer type declaration 624 | eat(TokenType.TYPE); 625 | return null; 626 | } 627 | 628 | return new IntegerType(); 629 | 630 | case BOOLEAN: 631 | eat(TokenType.BOOLEAN); 632 | return new BooleanType(); 633 | 634 | case ID: 635 | String id = lexer.getIdVal(); 636 | eat(TokenType.ID); 637 | return new IdentifierType(id); 638 | 639 | default: 640 | // unknown type 641 | eat(TokenType.TYPE); 642 | return null; 643 | 644 | } 645 | } 646 | 647 | // Formal method parameter: Type id 648 | private Formal parseFormal() { 649 | Type type = parseType(); 650 | Identifier id = parseIdentifier(); 651 | 652 | return new Formal(type, id); 653 | } 654 | } 655 | -------------------------------------------------------------------------------- /src/parser/Token.java: -------------------------------------------------------------------------------- 1 | package parser; 2 | 3 | /* 4 | * 5 | * A token has a type as well as line and column numbers for error reporting 6 | * during the syntax and semantic analysis phase of compilation. Tokens with 7 | * the types ID or INT_CONST will have an associating lexeme (semantic value) 8 | * that is recorded by the lexer. 9 | * 10 | */ 11 | 12 | public class Token { 13 | private TokenType type; 14 | private int lineNum, colNum; // for error reporting 15 | 16 | public Token(TokenType type, int lineNum, int colNum) { 17 | this.type = type; 18 | this.lineNum = lineNum; 19 | this.colNum = colNum; 20 | } 21 | 22 | public TokenType getType() { 23 | return type; 24 | } 25 | 26 | public int getLineNum() { 27 | return lineNum; 28 | } 29 | 30 | public int getColNum() { 31 | return colNum; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/parser/TokenType.java: -------------------------------------------------------------------------------- 1 | package parser; 2 | 3 | /* 4 | * 5 | * A token type is an attribute of a token, which includes identifiers, integer 6 | * constants, binary operators, reserved words, and punctuation. Only ID and 7 | * INT_CONST token types require an associating lexeme or semantic value that 8 | * is managed by the lexer. 9 | * 10 | */ 11 | 12 | public enum TokenType { 13 | // basic types 14 | ID, // [a-zA-Z][a-zA-Z0-9_]* 15 | INT_CONST, // [0-9]+ 16 | EOF, // input stream has been consumed 17 | UNKNOWN, // character/token could not be processed 18 | 19 | // binary operators 20 | AND, // && 21 | LT, // < 22 | PLUS, // + 23 | MINUS, // - 24 | TIMES, // * 25 | 26 | // reserved words (case-sensitive) 27 | CLASS, // class 28 | PUBLIC, // public 29 | STATIC, // static 30 | VOID, // void 31 | MAIN, // main - relegate as ID (?) 32 | STRING, // String - relegate as ID (?) 33 | EXTENDS, // extends 34 | RETURN, // return 35 | INT, // int 36 | BOOLEAN, // boolean 37 | IF, // if 38 | ELSE, // else 39 | WHILE, // while 40 | TRUE, // true 41 | FALSE, // false 42 | THIS, // this 43 | NEW, // new 44 | 45 | // punctuation 46 | LPAREN, // ( 47 | RPAREN, // ) 48 | LBRACKET, // [ 49 | RBRACKET, // ] 50 | LBRACE, // { 51 | RBRACE, // } 52 | SEMI, // ; 53 | COMMA, // , 54 | DOT, // . 55 | ASSIGN, // = 56 | BANG, // ! 57 | 58 | // for error reporting 59 | STATEMENT, 60 | EXPRESSION, 61 | OPERATOR, 62 | TYPE 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/visitor/PrettyPrintVisitor.java: -------------------------------------------------------------------------------- 1 | package visitor; 2 | 3 | import ast.*; 4 | 5 | /* 6 | * 7 | * Pretty printing for abstract syntax trees. Allows verification that the 8 | * trees for a program's syntax were properly constructed during the parsing 9 | * stage. It is utilized by the TestParser class in MiniJava/test. 10 | * 11 | */ 12 | 13 | public class PrettyPrintVisitor implements Visitor { 14 | 15 | @Override 16 | public void visit(Program prog) { 17 | if (prog == null) return; 18 | 19 | if (prog.getMainClass() != null) prog.getMainClass().accept(this); 20 | 21 | if (prog.getClassDeclList() == null) return; 22 | for (int i = 0; i < prog.getClassDeclList().size(); i++) { 23 | if (prog.getClassDeclList().elementAt(i) == null) 24 | continue; 25 | 26 | System.out.println(); 27 | prog.getClassDeclList().elementAt(i).accept(this); 28 | } 29 | } 30 | 31 | @Override 32 | public void visit(MainClass main) { 33 | System.out.print("class "); 34 | if (main.getClassId() != null) main.getClassId().accept(this); 35 | System.out.println(" {"); 36 | 37 | System.out.print("\tpublic static void main(String[] "); 38 | if (main.getArgId() != null) main.getArgId().accept(this); 39 | System.out.println(") {"); 40 | 41 | System.out.print("\t\t"); 42 | if (main.getStm() != null) main.getStm().accept(this); 43 | System.out.println(); 44 | System.out.println("\t}"); 45 | System.out.println("}"); 46 | } 47 | 48 | @Override 49 | public void visit(ClassDeclSimple simpleClass) { 50 | System.out.print("class "); 51 | if (simpleClass.getClassId() != null) simpleClass.getClassId().accept(this); 52 | System.out.println(" {"); 53 | 54 | if (simpleClass.getFields() != null) { 55 | for (int i = 0; i < simpleClass.getFields().size(); i++) { 56 | if (simpleClass.getFields().elementAt(i) == null) 57 | continue; 58 | 59 | System.out.print("\t"); 60 | simpleClass.getFields().elementAt(i).accept(this); 61 | System.out.println(); 62 | } 63 | } 64 | 65 | if (simpleClass.getMethods() != null) { 66 | for (int i = 0; i < simpleClass.getMethods().size(); i++) { 67 | if (simpleClass.getMethods().elementAt(i) == null) 68 | continue; 69 | 70 | System.out.print("\t"); 71 | simpleClass.getMethods().elementAt(i).accept(this); 72 | System.out.println(); 73 | } 74 | } 75 | 76 | System.out.println("}"); 77 | } 78 | 79 | @Override 80 | public void visit(ClassDeclExtends extendsClass) { 81 | System.out.print("class "); 82 | if (extendsClass.getClassId() != null) extendsClass.getClassId().accept(this); 83 | System.out.print(" extends "); 84 | if (extendsClass.getSuperId() != null) extendsClass.getSuperId().accept(this); 85 | System.out.println(" {"); 86 | 87 | if (extendsClass.getFields() != null) { 88 | for (int i = 0; i < extendsClass.getFields().size(); i++) { 89 | if (extendsClass.getFields().elementAt(i) == null) 90 | continue; 91 | 92 | System.out.print("\t"); 93 | extendsClass.getFields().elementAt(i).accept(this); 94 | System.out.println(); 95 | } 96 | } 97 | 98 | if (extendsClass.getMethods() != null) { 99 | for (int i = 0; i < extendsClass.getMethods().size(); i++) { 100 | if (extendsClass.getMethods().elementAt(i) == null) 101 | continue; 102 | 103 | System.out.print("\t"); 104 | extendsClass.getMethods().elementAt(i).accept(this); 105 | System.out.println(); 106 | } 107 | } 108 | 109 | System.out.println("}"); 110 | } 111 | 112 | @Override 113 | public void visit(VarDecl var) { 114 | if (var.getType() != null) var.getType().accept(this); 115 | System.out.print(" "); 116 | if (var.getId() != null) var.getId().accept(this); 117 | System.out.print(";"); 118 | } 119 | 120 | @Override 121 | public void visit(MethodDecl method) { 122 | System.out.print("public "); 123 | if (method.getReturnType() != null) method.getReturnType().accept(this); 124 | System.out.print(" "); 125 | if (method.getId() != null) method.getId().accept(this); 126 | System.out.print(" ("); 127 | 128 | if (method.getParams() != null) { 129 | for (int i = 0; i < method.getParams().size(); i++) { 130 | if (method.getParams().elementAt(i) == null) 131 | continue; 132 | 133 | method.getParams().elementAt(i).accept(this); 134 | if (i < method.getParams().size() - 1) 135 | System.out.print(", "); 136 | } 137 | } 138 | 139 | System.out.println(") {"); 140 | 141 | if (method.getVars() != null) { 142 | for (int i = 0; i < method.getVars().size(); i++) { 143 | if (method.getVars().elementAt(i) == null) 144 | continue; 145 | 146 | System.out.print("\t\t"); 147 | method.getVars().elementAt(i).accept(this); 148 | System.out.println(); 149 | } 150 | } 151 | 152 | if (method.getStms() != null) { 153 | for (int i = 0; i < method.getStms().size(); i++) { 154 | if (method.getStms().elementAt(i) == null) 155 | continue; 156 | 157 | System.out.print("\t\t"); 158 | method.getStms().elementAt(i).accept(this); 159 | System.out.println(); 160 | } 161 | } 162 | 163 | System.out.print("\t\treturn "); 164 | if (method.getReturnExp() != null) method.getReturnExp().accept(this); 165 | System.out.println(";"); 166 | System.out.println("\t}"); 167 | } 168 | 169 | @Override 170 | public void visit(Formal param) { 171 | if (param.getType() != null) param.getType().accept(this); 172 | System.out.print(" "); 173 | if (param.getId() != null) param.getId().accept(this); 174 | } 175 | 176 | @Override 177 | public void visit(IntArrayType intArrayT) { 178 | System.out.print("int[]"); 179 | } 180 | 181 | @Override 182 | public void visit(BooleanType boolT) { 183 | System.out.print("boolean"); 184 | } 185 | 186 | @Override 187 | public void visit(IntegerType intT) { 188 | System.out.print("int"); 189 | } 190 | 191 | @Override 192 | public void visit(IdentifierType idT) { 193 | if (idT.getName() != null) 194 | System.out.print(idT.getName()); 195 | } 196 | 197 | @Override 198 | public void visit(Block blockStm) { 199 | System.out.println("{"); 200 | 201 | if (blockStm.getStms() != null) { 202 | for (int i = 0; i < blockStm.getStms().size(); i++) { 203 | if (blockStm.getStms().elementAt(i) == null) 204 | continue; 205 | 206 | System.out.print("\t\t\t"); 207 | blockStm.getStms().elementAt(i).accept(this); 208 | System.out.println(); 209 | } 210 | } 211 | 212 | System.out.println("\t\t}"); 213 | } 214 | 215 | @Override 216 | public void visit(If ifStm) { 217 | System.out.print("if ("); 218 | if (ifStm.getCondExp() != null) ifStm.getCondExp().accept(this); 219 | System.out.println(")"); 220 | 221 | System.out.print("\t\t\t"); 222 | if (ifStm.getTrueStm() != null) ifStm.getTrueStm().accept(this); 223 | System.out.println(); 224 | 225 | System.out.println("\t\telse"); 226 | System.out.print("\t\t\t"); 227 | if (ifStm.getFalseStm() != null) ifStm.getFalseStm().accept(this); 228 | } 229 | 230 | @Override 231 | public void visit(While whileStm) { 232 | System.out.print("while ("); 233 | if (whileStm.getCondExp() != null) whileStm.getCondExp().accept(this); 234 | System.out.print(")"); 235 | if (whileStm.getStm() != null) whileStm.getStm().accept(this); 236 | } 237 | 238 | @Override 239 | public void visit(Print printStm) { 240 | System.out.print("System.out.println("); 241 | if (printStm.getExp() != null) printStm.getExp().accept(this); 242 | System.out.print(");"); 243 | } 244 | 245 | @Override 246 | public void visit(Assign assignStm) { 247 | if (assignStm.getId() != null) assignStm.getId().accept(this); 248 | System.out.print(" = "); 249 | if (assignStm.getValue() != null) assignStm.getValue().accept(this); 250 | System.out.print(";"); 251 | } 252 | 253 | @Override 254 | public void visit(ArrayAssign arrayAssignStm) { 255 | if (arrayAssignStm.getId() != null) arrayAssignStm.getId().accept(this); 256 | System.out.print("["); 257 | if (arrayAssignStm.getIndex() != null) arrayAssignStm.getIndex().accept(this); 258 | System.out.print("] = "); 259 | if (arrayAssignStm.getValue() != null) arrayAssignStm.getValue().accept(this); 260 | System.out.print(";"); 261 | } 262 | 263 | @Override 264 | public void visit(And andExp) { 265 | System.out.print("("); 266 | if (andExp.getLHS() != null) andExp.getLHS().accept(this); 267 | System.out.print(" && "); 268 | if (andExp.getRHS() != null) andExp.getRHS().accept(this); 269 | System.out.print(")"); 270 | } 271 | 272 | @Override 273 | public void visit(LessThan lessThanExp) { 274 | System.out.print("("); 275 | if (lessThanExp.getLHS() != null) lessThanExp.getLHS().accept(this); 276 | System.out.print(" < "); 277 | if (lessThanExp.getRHS() != null) lessThanExp.getRHS().accept(this); 278 | System.out.print(")"); 279 | } 280 | 281 | @Override 282 | public void visit(Plus plusExp) { 283 | System.out.print("("); 284 | if (plusExp.getLHS() != null) plusExp.getLHS().accept(this); 285 | System.out.print(" + "); 286 | if (plusExp.getRHS() != null) plusExp.getRHS().accept(this); 287 | System.out.print(")"); 288 | } 289 | 290 | @Override 291 | public void visit(Minus minusExp) { 292 | System.out.print("("); 293 | if (minusExp.getLHS() != null) minusExp.getLHS().accept(this); 294 | System.out.print(" - "); 295 | if (minusExp.getRHS() != null) minusExp.getRHS().accept(this); 296 | System.out.print(")"); 297 | } 298 | 299 | @Override 300 | public void visit(Times timesExp) { 301 | System.out.print("("); 302 | if (timesExp.getLHS() != null) timesExp.getLHS().accept(this); 303 | System.out.print(" * "); 304 | if (timesExp.getRHS() != null) timesExp.getRHS().accept(this); 305 | System.out.print(")"); 306 | } 307 | 308 | @Override 309 | public void visit(ArrayLookup arrayLookup) { 310 | if (arrayLookup.getArray() != null) arrayLookup.getArray().accept(this); 311 | System.out.print("["); 312 | if (arrayLookup.getIndex() != null) arrayLookup.getIndex().accept(this); 313 | } 314 | 315 | @Override 316 | public void visit(ArrayLength length) { 317 | if (length.getArray() != null) length.getArray().accept(this); 318 | System.out.print(".length"); 319 | } 320 | 321 | @Override 322 | public void visit(Call callExp) { 323 | if (callExp.getCallee() != null) callExp.getCallee().accept(this); 324 | System.out.print("."); 325 | if (callExp.getMethodName() != null) callExp.getMethodName().accept(this); 326 | System.out.print("("); 327 | 328 | if (callExp.getArgs() != null) { 329 | for (int i = 0; i < callExp.getArgs().size(); i++) { 330 | if (callExp.getArgs().elementAt(i) == null) 331 | continue; 332 | 333 | callExp.getArgs().elementAt(i).accept(this); 334 | if (i < callExp.getArgs().size() - 1) 335 | System.out.print(", "); 336 | } 337 | } 338 | 339 | System.out.print(")"); 340 | } 341 | 342 | @Override 343 | public void visit(IntegerLiteral intLiteral) { 344 | System.out.print(intLiteral.getValue()); 345 | } 346 | 347 | @Override 348 | public void visit(True trueLiteral) { 349 | System.out.print("true"); 350 | } 351 | 352 | @Override 353 | public void visit(False falseLiteral) { 354 | System.out.print("false"); 355 | } 356 | 357 | @Override 358 | public void visit(IdentifierExp identExp) { 359 | if (identExp.getName() != null) 360 | System.out.print(identExp.getName()); 361 | } 362 | 363 | @Override 364 | public void visit(This thisLiteral) { 365 | System.out.print("this"); 366 | } 367 | 368 | @Override 369 | public void visit(NewArray array) { 370 | System.out.print("new int ["); 371 | if (array.getArraySize() != null) array.getArraySize().accept(this); 372 | System.out.print("]"); 373 | } 374 | 375 | @Override 376 | public void visit(NewObject object) { 377 | System.out.print("new "); 378 | if (object.getId() != null) object.getId().accept(this); 379 | System.out.print("()"); 380 | } 381 | 382 | @Override 383 | public void visit(Not notExp) { 384 | System.out.print("!"); 385 | if (notExp.getExp() != null) notExp.getExp().accept(this); 386 | } 387 | 388 | @Override 389 | public void visit(Identifier id) { 390 | if (id.getName() != null) 391 | System.out.print(id.getName()); 392 | } 393 | 394 | } 395 | -------------------------------------------------------------------------------- /src/visitor/Visitor.java: -------------------------------------------------------------------------------- 1 | package visitor; 2 | 3 | import ast.*; 4 | 5 | public interface Visitor { 6 | public void visit(Program prog); 7 | public void visit(MainClass main); 8 | public void visit(ClassDeclSimple simpleClass); 9 | public void visit(ClassDeclExtends extendsClass); 10 | public void visit(VarDecl var); 11 | public void visit(MethodDecl method); 12 | public void visit(Formal param); 13 | public void visit(IntArrayType intArrayT); 14 | public void visit(BooleanType boolT); 15 | public void visit(IntegerType intT); 16 | public void visit(IdentifierType idT); 17 | public void visit(Block blockStm); 18 | public void visit(If ifStm); 19 | public void visit(While whileStm); 20 | public void visit(Print printStm); 21 | public void visit(Assign assignStm); 22 | public void visit(ArrayAssign arrayAssignStm); 23 | public void visit(And andExp); 24 | public void visit(LessThan lessThanExp); 25 | public void visit(Plus plusExp); 26 | public void visit(Minus minusExp); 27 | public void visit(Times timesExp); 28 | public void visit(ArrayLookup arrayLookup); 29 | public void visit(ArrayLength length); 30 | public void visit(Call callExp); 31 | public void visit(IntegerLiteral intLiteral); 32 | public void visit(True trueLiteral); 33 | public void visit(False falseLiteral); 34 | public void visit(IdentifierExp identExp); 35 | public void visit(This thisLiteral); 36 | public void visit(NewArray array); 37 | public void visit(NewObject object); 38 | public void visit(Not notExp); 39 | public void visit(Identifier id); 40 | } 41 | -------------------------------------------------------------------------------- /test/TestLexer.java: -------------------------------------------------------------------------------- 1 | import java.io.FileNotFoundException; 2 | import java.io.FileReader; 3 | 4 | import parser.Lexer; 5 | import parser.Token; 6 | import parser.TokenType; 7 | 8 | public class TestLexer { 9 | public static void main(String[] args) { 10 | if (args.length == 0) 11 | System.err.println("No file arguments given"); 12 | else { 13 | // parse each file argument given 14 | for (int i = 0; i < args.length; i++) { 15 | FileReader file; 16 | 17 | // attempt to open file 18 | try { 19 | file = new FileReader("programs/" + args[i]); 20 | } catch (FileNotFoundException e) { 21 | System.err.println(args[i] + " was not found in MiniJava/programs"); 22 | continue; // try next file 23 | } 24 | 25 | // create lexer 26 | Lexer lexer = new Lexer(file); 27 | 28 | // start tokenizing file 29 | System.out.println("Tokenizing " + args[i] + "..."); 30 | long startTime = System.currentTimeMillis(); 31 | int numTokens = 0; 32 | Token token; 33 | do { 34 | token = lexer.getToken(); 35 | numTokens++; 36 | 37 | // print token type and location 38 | System.out.print(token.getType()); 39 | System.out.print(" (" + token.getLineNum() + "," + token.getColNum() + ")"); 40 | 41 | // print out semantic values for ID and INT_CONST tokens 42 | if (token.getType() == TokenType.ID) 43 | System.out.println(": " + lexer.getIdVal()); 44 | else if (token.getType() == TokenType.INT_CONST) 45 | System.out.println(": " + lexer.getIntVal()); 46 | else 47 | System.out.println(); 48 | 49 | } while (token.getType() != TokenType.EOF); 50 | 51 | long endTime = System.currentTimeMillis(); 52 | 53 | // print out statistics 54 | System.out.println("---"); 55 | System.out.println("Number of tokens: " + numTokens); 56 | System.out.println("Execution time: " + (endTime - startTime) + "ms"); 57 | System.out.println(); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /test/TestParser.java: -------------------------------------------------------------------------------- 1 | import java.io.FileNotFoundException; 2 | import java.io.FileReader; 3 | 4 | import ast.Program; 5 | import parser.Parser; 6 | import visitor.PrettyPrintVisitor; 7 | 8 | public class TestParser { 9 | public static void main(String[] args) throws FileNotFoundException { 10 | if (args.length == 0) 11 | System.err.println("No file arguments givens"); 12 | else { 13 | // parse each file argument given 14 | for (int i = 0; i < args.length; i++) { 15 | FileReader file; 16 | 17 | // attempt to open file 18 | try { 19 | file = new FileReader("programs/" + args[i]); 20 | } catch (FileNotFoundException e) { 21 | System.err.println(args[i] + " was not found in MiniJava/programs"); 22 | continue; // try next file 23 | } 24 | 25 | // create parser 26 | Parser parser = new Parser(file); 27 | System.out.println("Parsing " + args[i] + "..."); 28 | 29 | // initiate parse and clock time 30 | long startTime = System.currentTimeMillis(); 31 | Program prog = parser.parseProgram(); 32 | long endTime = System.currentTimeMillis(); 33 | 34 | // print out statistics 35 | System.out.println("File has finished parsing!"); 36 | System.out.println("Execution time: " + (endTime - startTime) + "ms"); 37 | System.out.println(parser.getErrorCount() + " errors reported"); 38 | System.out.println("---"); 39 | 40 | // print out ASTs 41 | PrettyPrintVisitor printer = new PrettyPrintVisitor(); 42 | printer.visit(prog); 43 | System.out.println(); 44 | } 45 | } 46 | } 47 | } 48 | --------------------------------------------------------------------------------