JavaCC is a parser/scanner generator for java
It lives here:
https://javacc.dev.java.net/Following example demonstrates the use of javacc parser definition. It defines a calculator that supports arithmetic operations as well as some generic functions like SUM, AVG, MAX, MIN. The functions can take arbitrary number of comma separated parameters. Parenthesis can be used to change the priority of operation.
options
{
LOOKAHEAD = 2;
STATIC=false;}PARSER_BEGIN(Calculator)package com.custommode;import com.custommode.*;import java.io.StringReader;/**
* @author JavaCC
*/public class Calculator
{
private int _dimention;
private Metric _metric;
public static void main(String args[]) throws ParseException
{
Calculator parser = new Calculator(System.in);
while (true)
{
parser.parseOneLine();
}
} public Calculator(int pDimention, Metric pMetric) {
this(new StringReader(pMetric.getFormula()));
_dimention = pDimention;
_metric = pMetric;
}
}
PARSER_END(Calculator)SKIP :
{
" "
| "r"
| "t"
}TOKEN:
{
< NUMBER: (<DIGIT>)+ ( "." (<DIGIT>)+ )? >
| < #LETTER : ["a"-"z","A"-"Z"] >
| < #DIGIT: ["0"-"9"] >
| < METRIC_NAME: <LETTER> (["a"-"z","A"-"Z","0"-"9"])* >
| < SUM: "SUM" "(" >
| < AVG: "AVG" "(" >
| < MIN: "MIN" "(" >
| < MAX: "MAX" "(" >
| < EOL: "n" >
}Float parseOneLine():
{
Float a;
}
{
a=expr() <EOF> { return a;}
}Float metricValue():
{
Token t;
Float result = null;
}
{
t=<METRIC_NAME> {
String metricKey = t.image;
//System.out.println("metricKey................... " + t.image);
result = ((Metric)_metric.getMetricTemplate().getMetrics().get(metricKey)).getComputeValue(_dimention);
return result;
}
}
Float sum():
{
Float result = null;
Float param;
}
{
<SUM>
result=expr()
("," param=expr()
{
if(result == null && param != null)
result = param;
else if(result != null && param != null)
result = new Float(param.floatValue() + result.floatValue());
}
)*
")"
{
return result;
}
}Float min():
{
Float result = null;
Float param = null;
}
{
<MIN>
result=expr()
("," param=expr()
{
if(result == null && param != null)
result = param;
else if(result != null && param != null)
result = param.floatValue() < result.floatValue()? param: result;
}
)*
")"
{
return result;
}
}Float max():
{
Float result = null;
Float param = null;
}
{
<MAX>
result=expr()
("," param=expr()
{
if(result == null && param != null)
result = param;
else if(result != null && param != null)
result = param.floatValue() > result.floatValue()? param: result;
}
)*
")"
{
return result;
}
}Float avg():
{
int i=1;
Float result;
Float param;
}
{
<AVG>
result=expr()
("," param=expr()
{
if(result == null && param != null)
result = param;
else if(result != null && param != null) {
result = new Float(result.floatValue() + param.floatValue());
i++;
}
}
)*
")"
{
if(result != null && i != 0)
return new Float(result.floatValue()/(float)i);
return null;
}
}
Float expr():
{
Float a;
Float b;
}
{
a=term()
(
"+" b=expr() {
if(a == null && b != null)
a = b;
else if(a != null && b != null)
a = new Float(a.floatValue() + b.floatValue()); }
| "-" b=expr() {
if(a == null && b != null)
a = new Float( b.floatValue()* (-1));
else if(a != null && b != null)
a = new Float(a.floatValue() - b.floatValue());
}
)*
{ return a; }
}Float term():
{
Float a;
Float b;
}
{
a=unary()
(
"*" b=term() {
if(a == null || b == null)
a = new Float(0.0);
else
a = new Float(a.floatValue() * b.floatValue());
}
| "/" b=term() {
if(a == null && b != null)
a = new Float(0);
else if(a != null && (b == null || b.floatValue() == 0))
a = new Float(Float.NaN);
else if(a != null && b != null && b.floatValue() != (float)0.0)
a = new Float(a.floatValue() / b.floatValue());
}
)*
{ return a; }
}Float unary():
{
Float a;
}
{
"-" a=element() { return new Float(-a.floatValue()); }
| a=element() { return a; }
}Float element():
{
Token t;
Float a;
}
{
t=<NUMBER> { return new Float(t.toString()); }
| a=sum() { return a; }
| a=avg() { return a; }
| a=max() { return a; }
| a=min() { return a; }
| a=metricValue() { return a; }
| "(" a=expr() ")" { return a; }
}