blob: 79665b946121ea08670e763e2be39d7e06dfa24a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
options {
MULTI=true;
NODE_SCOPE_HOOK=true; /* Call methods on entry/exit of node */
}
PARSER_BEGIN(MiniParser)
package Mini;
public class MiniParser {
private static Token expr_token;
final static void jjtreeOpenNodeScope(Node n) {}
final static void jjtreeCloseNodeScope(Node n) {((SimpleNode)n).closeNode();}
}
PARSER_END(MiniParser)
SKIP : /* WHITE SPACE */
{
" "
| "\t"
| "\n"
| "\r"
| "\f"
}
/* Single-line Comments
*/
MORE :
{
"--" : SINGLE_LINE_COMMENT_STATE
}
<SINGLE_LINE_COMMENT_STATE> SPECIAL_TOKEN :
{
<SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" > : DEFAULT
}
<SINGLE_LINE_COMMENT_STATE> MORE :
{
< ~[] >
}
/* A program consists of a number of function declarations with a
* distinguished function `main' that starts the program.
*/
void Program() : {}
{
(FunDecl())*
<EOF>
}
/* "FUN" Ident() "(" NameList() ")" = Expr()
*/
void FunDecl() :
{
String s;
Token t;
}
{
t = "FUN" { jjtThis.setPosition(t.beginLine, t.beginColumn); }
Ident()
<LPAREN>
[
Ident() (<COMMA> Ident())*
]
<RPAREN>
<ASSIGN>
Expr() /* Body expression */
}
void Expr() :
{
int kind=-1;
int un_op=-1;
}
{
IfExpr()
|
LetExpr()
|
Term() [kind = AddOp() Expr() { jjtThis.setKind(kind); }]
|
un_op = UnOp() { jjtThis.setUnOp(un_op); } Expr()
}
/*
* The disambiguating algorithm of JavaCC automatically binds dangling
* else's to the innermost if statement. The LOOKAHEAD specification
* is to tell JavaCC that we know what we are doing.
*/
void IfExpr() :
{
Token t=null;
}
{
t = "IF" { jjtThis.setPosition(t.beginLine, t.beginColumn); }
Expr() "THEN" Expr() [ LOOKAHEAD(1) "ELSE" Expr() ] "FI"
}
void LetExpr() :
{
Token t=null;
}
{
t = "LET" { jjtThis.setPosition(t.beginLine, t.beginColumn); }
(Ident() <ASSIGN> Expr())+ "IN" Expr()
}
Token FunAppl() :
{
Token t=null;
}
{
t = Ident() { jjtThis.setPosition(t.beginLine, t.beginColumn); }
<LPAREN>
[Expr() (<COMMA> Expr())*] <RPAREN>
{ return t; }
}
void Term():
{
int kind=-1;
}
{
Factor() [kind = MultOp() { jjtThis.setKind(kind); } Term()]
{ jjtThis.setPosition(expr_token.beginLine, expr_token.beginColumn); }
}
void Factor() :
{
int kind=-1;
}
{
Element() [kind = CmpOp() { jjtThis.setKind(kind); } Factor()]
{ jjtThis.setPosition(expr_token.beginLine, expr_token.beginColumn); }
}
void Element() #void : {}
{
/* expr_token is a global variable used to remember the position of an Expr() node
*/
LOOKAHEAD(2)
expr_token = FunAppl()
|
expr_token = Ident()
|
expr_token = Integer()
|
expr_token = <LPAREN> Expr() <RPAREN>
}
Token Integer() :
{
int num;
Token t; // Contains lexem and line/column number
}
{
t = <INTEGER>
{
jjtThis.setValue(Integer.parseInt(t.image));
jjtThis.setPosition(t.beginLine, t.beginColumn);
return t;
}
}
Token Ident() :
{
String name;
Token t; // Contains lexem and line/column number
}
{
(t = <TRUE> | t = <FALSE> | t = <READ> | t = <WRITE> |
t = <IDENT>)
{
jjtThis.setName(t.image);
jjtThis.setPosition(t.beginLine, t.beginColumn);
return t;
}
}
int AddOp() #void :
{
Token t=null;
}
{
(t = <PLUS> | t = <MINUS> | t = <OR>)
{
return t.kind;
}
}
int MultOp() #void :
{
Token t=null;
}
{
(t = <MULT> | t = <DIV> | t = <MOD> | t = <AND>)
{
return t.kind;
}
}
int CmpOp() #void :
{
Token t=null;
}
{
(t = <EQ> | t = <NEQ> | t = <LEQ> | t = <GEQ> | t = <GT> | t = <LT>)
{
return t.kind;
}
}
int UnOp() #void :
{
Token t=null;
}
{
(t = <MINUS> | t = <NOT>)
{
return t.kind;
}
}
TOKEN : /* Boolean and arithmetic operands */
{
< GT : ">" >
|
< LT : "<" >
|
< GEQ : ">=" >
|
< LEQ : "<=" >
|
< EQ : "==" >
|
< NEQ : "!=" >
|
< NOT : "!" >
|
< FALSE : "FALSE" >
|
< TRUE : "TRUE" >
|
< AND : "AND" >
|
< OR : "OR" >
|
< PLUS : "+">
|
< MINUS : "-">
|
< MULT : "*">
|
< MOD : "%">
|
< DIV : "/">
|
< LPAREN : "(">
|
< RPAREN : ")">
|
< ASSIGN : "=">
|
< COMMA : ",">
|
< READ : "READ">
|
< WRITE : "WRITE">
}
/* Has to be and the, otherwise every string wil become an <IDENT> token
* Who knows why ...
*/
TOKEN : /* LITERALS */
{
< #DIGIT: ["0"-"9"] >
|
< #LETTER: ["a"-"z", "A"-"Z"] >
|
< IDENT: <LETTER> (<LETTER> | <DIGIT> | "_")* >
|
< INTEGER: (<DIGIT>)+ >
|
< STRING: "\"" (~["\"", "\n", "\r"])* "\"" >
}