1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18options { 19 MULTI=true; 20 NODE_SCOPE_HOOK=true; /* Call methods on entry/exit of node */ 21} 22 23PARSER_BEGIN(MiniParser) 24package Mini; 25 26public class MiniParser { 27 private static Token expr_token; 28 29 final static void jjtreeOpenNodeScope(Node n) {} 30 final static void jjtreeCloseNodeScope(Node n) {((SimpleNode)n).closeNode();} 31} 32 33PARSER_END(MiniParser) 34 35SKIP : /* WHITE SPACE */ 36{ 37 " " 38| "\t" 39| "\n" 40| "\r" 41| "\f" 42} 43 44/* Single-line Comments 45 */ 46MORE : 47{ 48 "--" : SINGLE_LINE_COMMENT_STATE 49} 50 51<SINGLE_LINE_COMMENT_STATE> SPECIAL_TOKEN : 52{ 53 <SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" > : DEFAULT 54} 55 56<SINGLE_LINE_COMMENT_STATE> MORE : 57{ 58 < ~[] > 59} 60 61/* A program consists of a number of function declarations with a 62 * distinguished function `main' that starts the program. 63 */ 64void Program() : {} 65{ 66 (FunDecl())* 67 <EOF> 68} 69 70/* "FUN" Ident() "(" NameList() ")" = Expr() 71 */ 72void FunDecl() : 73{ 74 String s; 75 Token t; 76} 77{ 78 t = "FUN" { jjtThis.setPosition(t.beginLine, t.beginColumn); } 79 80 Ident() 81 82 <LPAREN> 83 [ 84 Ident() (<COMMA> Ident())* 85 ] 86 <RPAREN> 87 88 <ASSIGN> 89 90 Expr() /* Body expression */ 91} 92 93void Expr() : 94{ 95 int kind=-1; 96 int un_op=-1; 97} 98{ 99 IfExpr() 100| 101 LetExpr() 102| 103 Term() [kind = AddOp() Expr() { jjtThis.setKind(kind); }] 104| 105 un_op = UnOp() { jjtThis.setUnOp(un_op); } Expr() 106} 107 108/* 109 * The disambiguating algorithm of JavaCC automatically binds dangling 110 * else's to the innermost if statement. The LOOKAHEAD specification 111 * is to tell JavaCC that we know what we are doing. 112 */ 113void IfExpr() : 114{ 115 Token t=null; 116} 117{ 118 t = "IF" { jjtThis.setPosition(t.beginLine, t.beginColumn); } 119 Expr() "THEN" Expr() [ LOOKAHEAD(1) "ELSE" Expr() ] "FI" 120} 121 122void LetExpr() : 123{ 124 Token t=null; 125} 126{ 127 t = "LET" { jjtThis.setPosition(t.beginLine, t.beginColumn); } 128 (Ident() <ASSIGN> Expr())+ "IN" Expr() 129} 130 131Token FunAppl() : 132{ 133 Token t=null; 134} 135{ 136 t = Ident() { jjtThis.setPosition(t.beginLine, t.beginColumn); } 137 <LPAREN> 138 [Expr() (<COMMA> Expr())*] <RPAREN> 139 { return t; } 140 141} 142 143void Term(): 144{ 145 int kind=-1; 146} 147{ 148 Factor() [kind = MultOp() { jjtThis.setKind(kind); } Term()] 149 { jjtThis.setPosition(expr_token.beginLine, expr_token.beginColumn); } 150} 151 152void Factor() : 153{ 154 int kind=-1; 155} 156{ 157 Element() [kind = CmpOp() { jjtThis.setKind(kind); } Factor()] 158 { jjtThis.setPosition(expr_token.beginLine, expr_token.beginColumn); } 159} 160 161void Element() #void : {} 162{ 163/* expr_token is a global variable used to remember the position of an Expr() node 164*/ 165 LOOKAHEAD(2) 166 expr_token = FunAppl() 167| 168 expr_token = Ident() 169| 170 expr_token = Integer() 171| 172 expr_token = <LPAREN> Expr() <RPAREN> 173} 174 175Token Integer() : 176{ 177 int num; 178 Token t; // Contains lexem and line/column number 179} 180{ 181 t = <INTEGER> 182 { 183 jjtThis.setValue(Integer.parseInt(t.image)); 184 jjtThis.setPosition(t.beginLine, t.beginColumn); 185 return t; 186 } 187} 188 189Token Ident() : 190{ 191 String name; 192 Token t; // Contains lexem and line/column number 193} 194{ 195 (t = <TRUE> | t = <FALSE> | t = <READ> | t = <WRITE> | 196 t = <IDENT>) 197 { 198 jjtThis.setName(t.image); 199 jjtThis.setPosition(t.beginLine, t.beginColumn); 200 return t; 201 } 202} 203 204int AddOp() #void : 205{ 206 Token t=null; 207} 208{ 209 (t = <PLUS> | t = <MINUS> | t = <OR>) 210 { 211 return t.kind; 212 } 213} 214 215int MultOp() #void : 216{ 217 Token t=null; 218} 219{ 220 (t = <MULT> | t = <DIV> | t = <MOD> | t = <AND>) 221 { 222 return t.kind; 223 } 224} 225 226int CmpOp() #void : 227{ 228 Token t=null; 229} 230{ 231 (t = <EQ> | t = <NEQ> | t = <LEQ> | t = <GEQ> | t = <GT> | t = <LT>) 232 { 233 return t.kind; 234 } 235} 236 237int UnOp() #void : 238{ 239 Token t=null; 240} 241{ 242 (t = <MINUS> | t = <NOT>) 243 { 244 return t.kind; 245 } 246} 247 248 249TOKEN : /* Boolean and arithmetic operands */ 250{ 251 < GT : ">" > 252| 253 < LT : "<" > 254| 255 < GEQ : ">=" > 256| 257 < LEQ : "<=" > 258| 259 < EQ : "==" > 260| 261 < NEQ : "!=" > 262| 263 < NOT : "!" > 264| 265 < FALSE : "FALSE" > 266| 267 < TRUE : "TRUE" > 268| 269 < AND : "AND" > 270| 271 < OR : "OR" > 272| 273 < PLUS : "+"> 274| 275 < MINUS : "-"> 276| 277 < MULT : "*"> 278| 279 < MOD : "%"> 280| 281 < DIV : "/"> 282| 283 < LPAREN : "("> 284| 285 < RPAREN : ")"> 286| 287 < ASSIGN : "="> 288| 289 < COMMA : ","> 290| 291 < READ : "READ"> 292| 293 < WRITE : "WRITE"> 294} 295 296/* Has to be and the, otherwise every string wil become an <IDENT> token 297 * Who knows why ... 298 */ 299TOKEN : /* LITERALS */ 300{ 301 < #DIGIT: ["0"-"9"] > 302| 303 < #LETTER: ["a"-"z", "A"-"Z"] > 304| 305 < IDENT: <LETTER> (<LETTER> | <DIGIT> | "_")* > 306| 307 < INTEGER: (<DIGIT>)+ > 308| 309 < STRING: "\"" (~["\"", "\n", "\r"])* "\"" > 310} 311