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