1/*@bgen(jjtree) Generated By:JJTree: Do not edit this line. Mini.jj */ 2/*@egen*/ 3 4PARSER_BEGIN(MiniParser) 5package Mini; 6 7public class MiniParser/*@bgen(jjtree)*/implements MiniParserTreeConstants/*@egen*/ {/*@bgen(jjtree)*/ 8 protected static JJTMiniParserState jjtree = new JJTMiniParserState(); 9 10/*@egen*/ 11 private static Token expr_token; 12 13 final static void jjtreeOpenNodeScope(Node n) {} 14 final static void jjtreeCloseNodeScope(Node n) {((SimpleNode)n).closeNode();} 15} 16 17PARSER_END(MiniParser) 18 19SKIP : /* WHITE SPACE */ 20{ 21 " " 22| "\t" 23| "\n" 24| "\r" 25| "\f" 26} 27 28/* Single-line Comments 29 */ 30MORE : 31{ 32 "--" : SINGLE_LINE_COMMENT_STATE 33} 34 35<SINGLE_LINE_COMMENT_STATE> SPECIAL_TOKEN : 36{ 37 <SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" > : DEFAULT 38} 39 40<SINGLE_LINE_COMMENT_STATE> MORE : 41{ 42 < ~[] > 43} 44 45/* A program consists of a number of function declarations with a 46 * distinguished function `main' that starts the program. 47 */ 48void Program() : {/*@bgen(jjtree) Program */ 49 ASTProgram jjtn000 = new ASTProgram(JJTPROGRAM); 50 boolean jjtc000 = true; 51 jjtree.openNodeScope(jjtn000); 52 jjtreeOpenNodeScope(jjtn000); 53/*@egen*/} 54{/*@bgen(jjtree) Program */ 55 try { 56/*@egen*/ 57 (FunDecl())* 58 <EOF>/*@bgen(jjtree)*/ 59 } catch (Throwable jjte000) { 60 if (jjtc000) { 61 jjtree.clearNodeScope(jjtn000); 62 jjtc000 = false; 63 } else { 64 jjtree.popNode(); 65 } 66 if (jjte000 instanceof ParseException) { 67 throw (ParseException)jjte000; 68 } 69 if (jjte000 instanceof RuntimeException) { 70 throw (RuntimeException)jjte000; 71 } 72 throw (Error)jjte000; 73 } finally { 74 if (jjtc000) { 75 jjtree.closeNodeScope(jjtn000, true); 76 jjtreeCloseNodeScope(jjtn000); 77 } 78 } 79/*@egen*/ 80} 81 82/* "FUN" Ident() "(" NameList() ")" = Expr() 83 */ 84void FunDecl() : 85{/*@bgen(jjtree) FunDecl */ 86 ASTFunDecl jjtn000 = new ASTFunDecl(JJTFUNDECL); 87 boolean jjtc000 = true; 88 jjtree.openNodeScope(jjtn000); 89 jjtreeOpenNodeScope(jjtn000); 90/*@egen*/ 91 String s; 92 Token t; 93} 94{/*@bgen(jjtree) FunDecl */ 95 try { 96/*@egen*/ 97 t = "FUN" { jjtn000.setPosition(t.beginLine, t.beginColumn); } 98 99 Ident() 100 101 <LPAREN> 102 [ 103 Ident() (<COMMA> Ident())* 104 ] 105 <RPAREN> 106 107 <ASSIGN> 108 109 Expr()/*@bgen(jjtree)*/ 110 } catch (Throwable jjte000) { 111 if (jjtc000) { 112 jjtree.clearNodeScope(jjtn000); 113 jjtc000 = false; 114 } else { 115 jjtree.popNode(); 116 } 117 if (jjte000 instanceof ParseException) { 118 throw (ParseException)jjte000; 119 } 120 if (jjte000 instanceof RuntimeException) { 121 throw (RuntimeException)jjte000; 122 } 123 throw (Error)jjte000; 124 } finally { 125 if (jjtc000) { 126 jjtree.closeNodeScope(jjtn000, true); 127 jjtreeCloseNodeScope(jjtn000); 128 } 129 } 130/*@egen*/ /* Body expression */ 131} 132 133void Expr() : 134{/*@bgen(jjtree) Expr */ 135 ASTExpr jjtn000 = new ASTExpr(JJTEXPR); 136 boolean jjtc000 = true; 137 jjtree.openNodeScope(jjtn000); 138 jjtreeOpenNodeScope(jjtn000); 139/*@egen*/ 140 int kind=-1; 141 int un_op=-1; 142} 143{/*@bgen(jjtree) Expr */ 144 try { 145/*@egen*/ 146 IfExpr() 147| 148 LetExpr() 149| 150 Term() [kind = AddOp() Expr() { jjtn000.setKind(kind); }] 151| 152 un_op = UnOp() { jjtn000.setUnOp(un_op); } Expr()/*@bgen(jjtree)*/ 153 } catch (Throwable jjte000) { 154 if (jjtc000) { 155 jjtree.clearNodeScope(jjtn000); 156 jjtc000 = false; 157 } else { 158 jjtree.popNode(); 159 } 160 if (jjte000 instanceof ParseException) { 161 throw (ParseException)jjte000; 162 } 163 if (jjte000 instanceof RuntimeException) { 164 throw (RuntimeException)jjte000; 165 } 166 throw (Error)jjte000; 167 } finally { 168 if (jjtc000) { 169 jjtree.closeNodeScope(jjtn000, true); 170 jjtreeCloseNodeScope(jjtn000); 171 } 172 } 173/*@egen*/ 174} 175 176/* 177 * The disambiguating algorithm of JavaCC automatically binds dangling 178 * else's to the innermost if statement. The LOOKAHEAD specification 179 * is to tell JavaCC that we know what we are doing. 180 */ 181void IfExpr() : 182{/*@bgen(jjtree) IfExpr */ 183 ASTIfExpr jjtn000 = new ASTIfExpr(JJTIFEXPR); 184 boolean jjtc000 = true; 185 jjtree.openNodeScope(jjtn000); 186 jjtreeOpenNodeScope(jjtn000); 187/*@egen*/ 188 Token t=null; 189} 190{/*@bgen(jjtree) IfExpr */ 191 try { 192/*@egen*/ 193 t = "IF" { jjtn000.setPosition(t.beginLine, t.beginColumn); } 194 Expr() "THEN" Expr() [ LOOKAHEAD(1) "ELSE" Expr() ] "FI"/*@bgen(jjtree)*/ 195 } catch (Throwable jjte000) { 196 if (jjtc000) { 197 jjtree.clearNodeScope(jjtn000); 198 jjtc000 = false; 199 } else { 200 jjtree.popNode(); 201 } 202 if (jjte000 instanceof ParseException) { 203 throw (ParseException)jjte000; 204 } 205 if (jjte000 instanceof RuntimeException) { 206 throw (RuntimeException)jjte000; 207 } 208 throw (Error)jjte000; 209 } finally { 210 if (jjtc000) { 211 jjtree.closeNodeScope(jjtn000, true); 212 jjtreeCloseNodeScope(jjtn000); 213 } 214 } 215/*@egen*/ 216} 217 218void LetExpr() : 219{/*@bgen(jjtree) LetExpr */ 220 ASTLetExpr jjtn000 = new ASTLetExpr(JJTLETEXPR); 221 boolean jjtc000 = true; 222 jjtree.openNodeScope(jjtn000); 223 jjtreeOpenNodeScope(jjtn000); 224/*@egen*/ 225 Token t=null; 226} 227{/*@bgen(jjtree) LetExpr */ 228 try { 229/*@egen*/ 230 t = "LET" { jjtn000.setPosition(t.beginLine, t.beginColumn); } 231 (Ident() <ASSIGN> Expr())+ "IN" Expr()/*@bgen(jjtree)*/ 232 } catch (Throwable jjte000) { 233 if (jjtc000) { 234 jjtree.clearNodeScope(jjtn000); 235 jjtc000 = false; 236 } else { 237 jjtree.popNode(); 238 } 239 if (jjte000 instanceof ParseException) { 240 throw (ParseException)jjte000; 241 } 242 if (jjte000 instanceof RuntimeException) { 243 throw (RuntimeException)jjte000; 244 } 245 throw (Error)jjte000; 246 } finally { 247 if (jjtc000) { 248 jjtree.closeNodeScope(jjtn000, true); 249 jjtreeCloseNodeScope(jjtn000); 250 } 251 } 252/*@egen*/ 253} 254 255Token FunAppl() : 256{/*@bgen(jjtree) FunAppl */ 257 ASTFunAppl jjtn000 = new ASTFunAppl(JJTFUNAPPL); 258 boolean jjtc000 = true; 259 jjtree.openNodeScope(jjtn000); 260 jjtreeOpenNodeScope(jjtn000); 261/*@egen*/ 262 Token t=null; 263} 264{/*@bgen(jjtree) FunAppl */ 265 try { 266/*@egen*/ 267 t = Ident() { jjtn000.setPosition(t.beginLine, t.beginColumn); } 268 <LPAREN> 269 [Expr() (<COMMA> Expr())*] <RPAREN>/*@bgen(jjtree)*/ 270 { 271 jjtree.closeNodeScope(jjtn000, true); 272 jjtc000 = false; 273 jjtreeCloseNodeScope(jjtn000); 274 } 275/*@egen*/ 276 { return t; }/*@bgen(jjtree)*/ 277 } catch (Throwable jjte000) { 278 if (jjtc000) { 279 jjtree.clearNodeScope(jjtn000); 280 jjtc000 = false; 281 } else { 282 jjtree.popNode(); 283 } 284 if (jjte000 instanceof ParseException) { 285 throw (ParseException)jjte000; 286 } 287 if (jjte000 instanceof RuntimeException) { 288 throw (RuntimeException)jjte000; 289 } 290 throw (Error)jjte000; 291 } finally { 292 if (jjtc000) { 293 jjtree.closeNodeScope(jjtn000, true); 294 jjtreeCloseNodeScope(jjtn000); 295 } 296 } 297/*@egen*/ 298 299} 300 301void Term(): 302{/*@bgen(jjtree) Term */ 303 ASTTerm jjtn000 = new ASTTerm(JJTTERM); 304 boolean jjtc000 = true; 305 jjtree.openNodeScope(jjtn000); 306 jjtreeOpenNodeScope(jjtn000); 307/*@egen*/ 308 int kind=-1; 309} 310{/*@bgen(jjtree) Term */ 311 try { 312/*@egen*/ 313 Factor() [kind = MultOp() { jjtn000.setKind(kind); } Term()]/*@bgen(jjtree)*/ 314 { 315 jjtree.closeNodeScope(jjtn000, true); 316 jjtc000 = false; 317 jjtreeCloseNodeScope(jjtn000); 318 } 319/*@egen*/ 320 { jjtn000.setPosition(expr_token.beginLine, expr_token.beginColumn); }/*@bgen(jjtree)*/ 321 } catch (Throwable jjte000) { 322 if (jjtc000) { 323 jjtree.clearNodeScope(jjtn000); 324 jjtc000 = false; 325 } else { 326 jjtree.popNode(); 327 } 328 if (jjte000 instanceof ParseException) { 329 throw (ParseException)jjte000; 330 } 331 if (jjte000 instanceof RuntimeException) { 332 throw (RuntimeException)jjte000; 333 } 334 throw (Error)jjte000; 335 } finally { 336 if (jjtc000) { 337 jjtree.closeNodeScope(jjtn000, true); 338 jjtreeCloseNodeScope(jjtn000); 339 } 340 } 341/*@egen*/ 342} 343 344void Factor() : 345{/*@bgen(jjtree) Factor */ 346 ASTFactor jjtn000 = new ASTFactor(JJTFACTOR); 347 boolean jjtc000 = true; 348 jjtree.openNodeScope(jjtn000); 349 jjtreeOpenNodeScope(jjtn000); 350/*@egen*/ 351 int kind=-1; 352} 353{/*@bgen(jjtree) Factor */ 354 try { 355/*@egen*/ 356 Element() [kind = CmpOp() { jjtn000.setKind(kind); } Factor()]/*@bgen(jjtree)*/ 357 { 358 jjtree.closeNodeScope(jjtn000, true); 359 jjtc000 = false; 360 jjtreeCloseNodeScope(jjtn000); 361 } 362/*@egen*/ 363 { jjtn000.setPosition(expr_token.beginLine, expr_token.beginColumn); }/*@bgen(jjtree)*/ 364 } catch (Throwable jjte000) { 365 if (jjtc000) { 366 jjtree.clearNodeScope(jjtn000); 367 jjtc000 = false; 368 } else { 369 jjtree.popNode(); 370 } 371 if (jjte000 instanceof ParseException) { 372 throw (ParseException)jjte000; 373 } 374 if (jjte000 instanceof RuntimeException) { 375 throw (RuntimeException)jjte000; 376 } 377 throw (Error)jjte000; 378 } finally { 379 if (jjtc000) { 380 jjtree.closeNodeScope(jjtn000, true); 381 jjtreeCloseNodeScope(jjtn000); 382 } 383 } 384/*@egen*/ 385} 386 387void Element() : {} 388{ 389/* expr_token is a global variable used to remember the position of an Expr() node 390*/ 391 LOOKAHEAD(2) 392 expr_token = FunAppl() 393| 394 expr_token = Ident() 395| 396 expr_token = Integer() 397| 398 expr_token = <LPAREN> Expr() <RPAREN> 399} 400 401Token Integer() : 402{/*@bgen(jjtree) Integer */ 403 ASTInteger jjtn000 = new ASTInteger(JJTINTEGER); 404 boolean jjtc000 = true; 405 jjtree.openNodeScope(jjtn000); 406 jjtreeOpenNodeScope(jjtn000); 407/*@egen*/ 408 int num; 409 Token t; // Contains lexem and line/column number 410} 411{/*@bgen(jjtree) Integer */ 412 try { 413/*@egen*/ 414 t = <INTEGER>/*@bgen(jjtree)*/ 415 { 416 jjtree.closeNodeScope(jjtn000, true); 417 jjtc000 = false; 418 jjtreeCloseNodeScope(jjtn000); 419 } 420/*@egen*/ 421 { 422 jjtn000.setValue(Integer.parseInt(t.image)); 423 jjtn000.setPosition(t.beginLine, t.beginColumn); 424 return t; 425 }/*@bgen(jjtree)*/ 426 } finally { 427 if (jjtc000) { 428 jjtree.closeNodeScope(jjtn000, true); 429 jjtreeCloseNodeScope(jjtn000); 430 } 431 } 432/*@egen*/ 433} 434 435Token Ident() : 436{/*@bgen(jjtree) Ident */ 437 ASTIdent jjtn000 = new ASTIdent(JJTIDENT); 438 boolean jjtc000 = true; 439 jjtree.openNodeScope(jjtn000); 440 jjtreeOpenNodeScope(jjtn000); 441/*@egen*/ 442 String name; 443 Token t; // Contains lexem and line/column number 444} 445{/*@bgen(jjtree) Ident */ 446 try { 447/*@egen*/ 448 (t = <TRUE> | t = <FALSE> | t = <READ> | t = <WRITE> | 449 t = <IDENT>)/*@bgen(jjtree)*/ 450 { 451 jjtree.closeNodeScope(jjtn000, true); 452 jjtc000 = false; 453 jjtreeCloseNodeScope(jjtn000); 454 } 455/*@egen*/ 456 { 457 jjtn000.setName(t.image); 458 jjtn000.setPosition(t.beginLine, t.beginColumn); 459 return t; 460 }/*@bgen(jjtree)*/ 461 } finally { 462 if (jjtc000) { 463 jjtree.closeNodeScope(jjtn000, true); 464 jjtreeCloseNodeScope(jjtn000); 465 } 466 } 467/*@egen*/ 468} 469 470int AddOp() : 471{ 472 Token t=null; 473} 474{ 475 (t = <PLUS> | t = <MINUS> | t = <OR>) 476 { 477 return t.kind; 478 } 479} 480 481int MultOp() : 482{ 483 Token t=null; 484} 485{ 486 (t = <MULT> | t = <DIV> | t = <MOD> | t = <AND>) 487 { 488 return t.kind; 489 } 490} 491 492int CmpOp() : 493{ 494 Token t=null; 495} 496{ 497 (t = <EQ> | t = <NEQ> | t = <LEQ> | t = <GEQ> | t = <GT> | t = <LT>) 498 { 499 return t.kind; 500 } 501} 502 503int UnOp() : 504{ 505 Token t=null; 506} 507{ 508 (t = <MINUS> | t = <NOT>) 509 { 510 return t.kind; 511 } 512} 513 514 515TOKEN : /* Boolean and arithmetic operands */ 516{ 517 < GT : ">" > 518| 519 < LT : "<" > 520| 521 < GEQ : ">=" > 522| 523 < LEQ : "<=" > 524| 525 < EQ : "==" > 526| 527 < NEQ : "!=" > 528| 529 < NOT : "!" > 530| 531 < FALSE : "FALSE" > 532| 533 < TRUE : "TRUE" > 534| 535 < AND : "AND" > 536| 537 < OR : "OR" > 538| 539 < PLUS : "+"> 540| 541 < MINUS : "-"> 542| 543 < MULT : "*"> 544| 545 < MOD : "%"> 546| 547 < DIV : "/"> 548| 549 < LPAREN : "("> 550| 551 < RPAREN : ")"> 552| 553 < ASSIGN : "="> 554| 555 < COMMA : ","> 556| 557 < READ : "READ"> 558| 559 < WRITE : "WRITE"> 560} 561 562/* Has to be and the, otherwise every string wil become an <IDENT> token 563 * Who knows why ... 564 */ 565TOKEN : /* LITERALS */ 566{ 567 < #DIGIT: ["0"-"9"] > 568| 569 < #LETTER: ["a"-"z", "A"-"Z"] > 570| 571 < IDENT: <LETTER> (<LETTER> | <DIGIT> | "_")* > 572| 573 < INTEGER: (<DIGIT>)+ > 574| 575 < STRING: "\"" (~["\"", "\n", "\r"])* "\"" > 576} 577