Hi,
Is it possible to configure the parser to parse a 'number followed by a string' as a string and pass it to the numberfactory?
For example, when given the expression ( x + 1.5m + y), I would like the parser to parse the 1.5m as the string "1.5 m" so the number factory can then process it.
Is this doable?
Thanks,
Karthik
/**
* Pattern used to match numbers with units.
* The pattern needs some work as it not smart enough to get all numbers/units so .1m/s
*/
static Pattern numberWithUnitPattern = Pattern.compile("(\\d+.\\d*)([a-zA-Z]+)");
/**
* Class to hold a number with a unit.
*/
static class NumberWithUnit {
double num;
String unit;
public NumberWithUnit(String s) throws ParseException {
Matcher m = numberWithUnitPattern.matcher(s);
if(!m.matches()) throw new ParseException("Number didn't match \""+s+"\"");
num = Double.parseDouble(m.group(1));
unit = m.group(2);
}
public NumberWithUnit(double n,String u) {
num=n;
unit=u;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof NumberWithUnit)) return false;
NumberWithUnit that=(NumberWithUnit) obj;
boolean b1 = this.num == that.num;
boolean b2 = this.unit.equals(that.unit);
return b1 && b2;
}
@Override
public String toString() {
return "" + num + unit;
}
public double getNum() {
return num;
}
public String getUnit() {
return unit;
}
}
/**
* TokenMatcher used to match the a number with a unit.
*/
static class NumberWithUnitTokenMatcher extends RegExpTokenMatcher {
private static final long serialVersionUID = 1L;
public NumberWithUnitTokenMatcher() {
super(numberWithUnitPattern);
}
@Override
public void init(Jep j) {
}
@Override
public Token buildToken(String s) {
NumberToken t;
try {
t = new NumberToken(s,new NumberWithUnit(s));
return t;
} catch (ParseException e) {
System.out.println(e);
return null;
}
}}
/**
* Test method to check operation
* https://groups.google.com/forum/?hl=en_US&fromgroups=#!topic/jep-users/isBXCrRBg3c
* @throws JepException
*/
@Test
public void testNumbersAsStrings() throws JepException {
NumberWithUnit num1 = new NumberWithUnit("1.5m");
NumberWithUnit num2 = new NumberWithUnit(1.5,"m");
assertEquals(num2,num1);
ConfigurableParser cp = new ConfigurableParser();
cp.addHashComments();
cp.addSlashComments();
cp.addSingleQuoteStrings();
cp.addDoubleQuoteStrings();
cp.addWhiteSpace();
cp.addTokenMatcher(new NumberWithUnitTokenMatcher());
cp.addExponentNumbers();
cp.addOperatorTokenMatcher();
cp.addSymbols("(",")","[","]",",");
cp.setImplicitMultiplicationSymbols("(","[");
cp.addIdentifiers();
cp.addSemiColonTerminator();
cp.addWhiteSpaceCommentFilter();
cp.addBracketMatcher("(",")");
cp.addFunctionMatcher("(",")",",");
cp.addListMatcher("[","]",",");
cp.addArrayAccessMatcher("[","]");
Jep j = new Jep(cp);
String s0="1.5m";
Node n0 = j.parse(s0);
assertEquals(num2,n0.getValue());
String s="x + 1.5m + y";
Node n = j.parse(s);
Node term1 = n.jjtGetChild(0).jjtGetChild(0);
Node term2 = n.jjtGetChild(0).jjtGetChild(1);
Node term3 = n.jjtGetChild(1);
assertEquals("x",term1.getName());
assertEquals("y",term3.getName());
assertEquals(num2,term2.getValue());