Re: Parsing number as String

73 views
Skip to first unread message

Richard Morris

unread,
Aug 30, 2012, 7:04:13 AM8/30/12
to jep-...@googlegroups.com, krno...@gmail.com


On Wednesday, August 29, 2012 8:38:26 PM UTC+1, (unknown) wrote:
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


Karthik,

Yes this is doable although there might be problems with specifying advanced units. You need to use the ConfigurableParser with a custom TokenMatcher to match the input. I've used a NumberWithUnit class to represent numbers although it could be done in other ways. You will probably need to modify the various functions like Add to cope with numbers with units.




/**

* 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());

Reply all
Reply to author
Forward
0 new messages