Array Access following a function call

70 views
Skip to first unread message

coolt...@gmail.com

unread,
Aug 31, 2011, 2:12:30 PM8/31/11
to jep-...@googlegroups.com
Hello,

I would like JEP to parse the an expression which involves an array access immediately following a function call.

For e.g., I have defined a custom function to split a string on a supplied tokenizer and return an array of tokens, and I would like to access a particular index of the returned array:
split("A|B|C|D", "|")[2]

When JEP parses this, it assumes an implicit product operator between split("A|B|C|D", "|")and the constant [2]as in split("A|B|C|D", "|") * 2.0. How can I get JEP to parse this expression as an index access of an array returned by the preceding function ?

Thanks,
Tushar.

Richard Morris

unread,
Sep 1, 2011, 5:10:08 AM9/1/11
to jep-...@googlegroups.com
Dear Tushar,

The solution would depend on which version for Jep your using. In Jep
2.4 you would need to modify the javacc grammar in
org/nfunk/jep/Parser.jjt. In Jep 3.4 you could modify the grammar
using the ConfigurableParser
http://www.singularsys.com/jep/doc/html/confparser.html
You would need to add a new
com.singularsys.jep.configurableparser.matchers.GrammarMatcher
which would match the syntax you needed.

Rich

In Jep 3.4 you can

> --
> You received this message because you are subscribed to the Google Groups
> "Jep Java Users" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/jep-users/-/3xr5M07Jrk8J.
> To post to this group, send email to jep-...@googlegroups.com.
> To unsubscribe from this group, send email to
> jep-users+...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/jep-users?hl=en.
>

gattin...@googlemail.com

unread,
Jun 23, 2017, 4:40:52 PM6/23/17
to Jep Java Users, ri...@singsurf.org
Hi Richard,

I came across this problem, too. Can you provide the code for Jep 3.4 that allows to use an indexed access after a function call (i. e. f(...)[n] should return the n-th element of a list of values returned by function "f")?

Thank you very much,
Marcus

Richard Morris

unread,
Jun 26, 2017, 1:40:20 PM6/26/17
to Jep Java Users, ri...@singsurf.org
This is quite a tricky thing to implement as it requires quite deep changes to the grammar.

One way of doing it is to use the ConfigurableParser with a custom GrammarMatcher which can detect the particular syntax 

    f(x,y,z)[5]

For this we need the class ArrayFunctionGrammarMatcher 

public class ArrayFunctionGrammarMatcher implements GrammarMatcher {
   private static final long serialVersionUID = 300L;
   /**
    * @serial
    */
   private final Token open; // = new SymbolToken("(");
   /**
    * @serial
    */
   private final Token close; // = new SymbolToken(")");
   /**
    * @serial
    */
   private final Token comma; // = ",";
   
   private final Token arrayOpen;
   private final Token arrayClose;
   
   private transient NodeFactory nf;
   private transient OperatorTableI ot;

   /**
    * Create a FunctionGrammarMatcher
    * @param open token representing an opening bracket
    * @param close token representing a closing bracket
    * @param comma token representing a list item separator 
    */

   public ArrayFunctionGrammarMatcher(Token open, Token close, Token comma,Token aopen, Token aclose) {
       this.open = open;
       this.close = close;
       this.comma = comma;
       this.arrayOpen = aopen;
       this.arrayClose = aclose;
   }

   @Override
public void init(Jep j) {
       nf = j.getNodeFactory();
       ot = j.getOperatorTable();
   }

   /**
    * Generate a token to use in GrammarExecptions 
    * @param it used to get current position
    * @return a TerminatorToken
    */
   protected Token errorToken(Lookahead2Iterator<Token> it) {
    Token t2 = it.peekNext();
    if(t2==null) {
    t2 = new TerminatorToken("Function Grammar Matcher");
    }
    return t2;
   }
   /**
    * Attempt to match a function, calls the GrammarParser.parseSubExpression() 
    * to match function arguments.
    */
   @Override
public Node match(Lookahead2Iterator<Token> it, GrammarParser parser) throws ParseException {
       Token t = it.peekNext();
       if(t==null) return null;
       if(!t.isFunction()) return null;
       String name = t.getSource();
       PostfixMathCommandI pfmc = ((FunctionToken) t).getPfmc();
       if(!open.equals(it.nextnext())) return null;
       it.consume();
       it.consume();
       if(close.equals(it.peekNext())) {
           if(!pfmc.checkNumberOfParameters(0)) {
               int req = pfmc.getNumberOfParameters();
               if(req>=0)
                   throw new GrammarException(
                           "Function "+pfmc.getName() + " Requires "+ req + " arguments. Found "+ 0,
                    errorToken(it)); 
                   
               throw new GrammarException(
                       "Function "+pfmc.getName()+"Illegal Number Of Arguments"+0,errorToken(it)); //$NON-NLS-1$
           }
           it.consume();
           return nf.buildFunctionNode(name, pfmc,new Node[0]);
       }
       List<Node> seq=new ArrayList<>();
       while(true) {
           Node contents = parser.parseSubExpression();
           seq.add(contents);
           if(close.equals(it.peekNext())) // this way round to cope with null
               break;
           else if(comma.equals(it.peekNext()))
               it.consume();
           else
               throw new GrammarException(
                "Function"+pfmc.getName()+" requre "+close,errorToken(it)); //$NON-NLS-1$
       }
       it.consume();
       if(!pfmc.checkNumberOfParameters(seq.size())) {
           int req = pfmc.getNumberOfParameters();
           if(req>=0)
                    throw new GrammarException(
                            "Function "+pfmc.getName() + " Requires "+ req + " arguments. Found "+ 0,
                    errorToken(it)); 
                    
                throw new GrammarException(
                        "Function "+pfmc.getName()+"Illegal Number Of Arguments"+0,errorToken(it)); //$NON-NLS-1$
       }
       
       Node functionNode = nf.buildFunctionNode(name, pfmc,seq.toArray(new Node[seq.size()]));

       // Parsed full function, now check if array subscript
       
       if(!arrayOpen.equals(it.peekNext())) {
       return functionNode;
       }

       // now has a array subscript
       List<Node> contents = new ArrayList<>(4);
       contents.add(functionNode);

       while(arrayOpen.equals(it.peekNext())) {
           it.consume();
           Node ele = parser.parseSubExpression();
           contents.add(ele);
           if(!arrayClose.equals(it.peekNext())) {
            Token t2 = it.peekNext();
            if(t2==null) {
            t2 = new TerminatorToken("TerminatorTokenName"); //$NON-NLS-1$
            }
               throw new GrammarException("Array Faunction Grammar Matcher requre "+close,t2); //$NON-NLS-1$
           }
           it.consume();
       }
       Node n = nf.buildOperatorNode(
               ot.getEle(), 
               contents.toArray(new Node[contents.size()]));
       return n;


   }
}



You could then create a Jep parser with this rule added

        ConfigurableParser cp = new ConfigurableParser();
        cp.addHashComments();
        cp.addSlashComments();
        cp.addDoubleQuoteStrings();
        cp.addWhiteSpace();
        cp.addTokenMatcher( NumberTokenMatcher.defaultNumberTokenMatcher());
        cp.addExponentNumbers();
        cp.addTokenMatcher(new OperatorTokenMatcher());
        cp.addSymbols("(",")","[","]");
        cp.setImplicitMultiplicationSymbols("(","[");
        cp.addIdentifiers();
        cp.addSemiColonTerminator();
        cp.addWhiteSpaceCommentFilter();
        cp.addBracketMatcher("(",")");

        // No longer want the standard function matcher
        //cp.addFunctionMatcher("(",")",",");

        // Add the new matcher
        cp.addGrammarMatcher(new ArrayFunctionGrammarMatcher(
        cp.getSymbolToken("("),
        cp.getSymbolToken(")"),
        cp.getSymbolToken(","),
        cp.getSymbolToken("["),
        cp.getSymbolToken("]")
        ));
        cp.addListMatcher("[","]",",");
        cp.addArrayAccessMatcher("[","]");

    jep = new Jep();
        jep.setComponent(cp);
        jep.reinitializeComponents();



We can set a test function, which generates a sequence of numbers as its result. So "seq(3)" returns the array [1,2,3]

   class SeqFun extends UnaryFunction {
private static final long serialVersionUID = 1L;

@Override
public Object eval(Object arg) throws EvaluationException {
Vector<Object> res = new Vector<>();
int n = this.asInt(0, arg);
for(int i=1;i<=n;++i) {
res.add(Double.valueOf(i));
}
return res;
}    
    }


which can be tested as follows

    @Test
    public void simpleTest() throws Exception {
    jep.addFunction("seq",new SeqFun());
   
    Node n2 = jep.parse("seq(3)[2]");
    Object o2 = jep.evaluate(n2);
    assertEquals(2.0, o2);
    }

I've put these all together in the attached file.


This method is not perfect. If would not work with a more complex expression where we do some array arithmetic, and then extract an array element.
   
    (seq(5) + seq(5))[3]

I might look at this over the next couple of days.

Richard
ArrayFunctionTest.java

gattin...@googlemail.com

unread,
Jun 27, 2017, 11:46:19 AM6/27/17
to Jep Java Users, ri...@singsurf.org
Hi, Richard!

Thank you very much for your very detailed and comprehensive anwser. I'm working with Jep for over four years now and our product uses it with great success but I think I wouldn't be able to solve this problem without your help.
I will have a close look at your code during the next days.

Kind regards and keep on with your outstanding support,
Marcus

P.S.: Is 3.4 the final version of Jep or are there any plans for a future version?

gattin...@googlemail.com

unread,
Jun 29, 2017, 6:11:41 AM6/29/17
to Jep Java Users, ri...@singsurf.org
Hi Richard,

based on your draft, I've reworked the implementation of the grammar matcher to match our needs. Here is the revised code:

/**
 * Parsers to allow indexed access to a value list that is a result of an evaluated function, i. e. parses expressions like <tt>function(...)[index]</tt>.
 */

public class IndexedFunctionGrammarMatcher implements GrammarMatcher {

   
private static final long serialVersionUID = 300L;


   
private final Token comma = new SymbolToken(",");
   
private final Token openingBracket = new SymbolToken("(");
   
private final Token closingBracket = new SymbolToken(")");
   
private final Token openingSquareBracket = new SymbolToken("[");
   
private final Token closingSquareBracket = new SymbolToken("]");

   
private transient Jep jep;

   
@Override
   
public Node match(final Lookahead2Iterator<Token> iterator, final GrammarParser parser) throws ParseException {
       
Token nextToken;
       
Token token = iterator.peekNext();
       
if (token == null || !token.isFunction() || !openingBracket.equals(iterator.nextnext())) {
           
return null;
       
}

       
// Get access to function definition and function name.
       
PostfixMathCommandI function = ((FunctionToken) token).getPfmc();
       
String functionName = token.getSource();

       
// Process function token and opening bracket.
        iterator
.consume();
        iterator
.consume();

       
// Check whether any function arguments have been provided. If no arguments have been provided, the function must not expect any arguments, too.
       
// Otherwise raise a grammar exception.
        nextToken
= iterator.peekNext();
       
if (closingBracket.equals(nextToken)) {
           
if (!function.checkNumberOfParameters(0)) {
               
throw new GrammarException(String.format("Missing parameter in function '%s'.", functionName), closingBracket);
           
}

           
// Process closing bracket.
            iterator
.consume();

           
// Create and return the node representing the function.
           
return jep.getNodeFactory().buildFunctionNode(functionName, function, new Node[0]);
       
}

       
// Process function arguments.
       
List<Node> functionArgs = new ArrayList<>();
       
while (true) {
            nextToken
= iterator.peekNext();
            functionArgs
.add(parser.parseSubExpression());

           
// After processing of a function argument, either a closing bracket or a comma (as delimiter for further function arguments) is expected.
           
if (closingBracket.equals(iterator.peekNext())) {
               
break;
           
}
           
if (!comma.equals(iterator.peekNext())) {
               
throw new GrammarException(String.format("Missing '%s' in function '%s'.", closingBracket.getSource(), functionName), nextToken);
           
}

           
// Process comma.
            iterator
.consume();
       
}

       
// Check whether the number of provided function arguments matches the number of expected function arguments.
        nextToken
= iterator.peekNext();
       
if (!function.checkNumberOfParameters(functionArgs.size())) {
           
throw new GrammarException(String.format("Missing parameter in function '%s'.", functionName), nextToken);
       
}

       
// Process closing bracket.
        iterator
.consume();

       
// Create the node representing the function.
       
// At this step the function has been fully parsed.
       
Node functionNode = jep.getNodeFactory().buildFunctionNode(functionName, function, functionArgs.toArray(new Node[functionArgs.size()]));

       
// Check for opening square bracket (indexed access).
       
if (!openingSquareBracket.equals(iterator.peekNext())) {
           
return functionNode;
       
}

       
// Process opening square bracket.
        iterator
.consume();

       
// Process index and check whether it is a positive integer number.
        nextToken
= iterator.peekNext();
       
Node indexNode = parser.parseSubExpression();
       
if (!Convert.isInteger(indexNode.getValue()) || Convert.toInteger(indexNode.getValue(), 0) < 1) {
           
throw new GrammarException(String.format("'%s' is not considered to be a valid element index.", nextToken.getSource()), nextToken);
       
}

       
// Ensure the closing square bracket comes next.
        nextToken
= iterator.peekNext();
       
if (!closingSquareBracket.equals(iterator.peekNext())) {
           
throw new GrammarException(String.format("Function '%s' expects '%s'.", functionName, closingSquareBracket.getSource()), nextToken);
       
}

       
// Process closing square bracket.
        iterator
.consume();

       
// Create and return the node representing the function as well as the indexed access.
       
return jep.getNodeFactory().buildOperatorNode(jep.getOperatorTable().getEle(), new Node[]{ functionNode, indexNode });
   
}

   
@Override
   
public void init(final Jep jep) {
       
this.jep = jep;
   
}
}

Any comments about it are really welcome.

Kind regards,
Marcus

Richard Morris

unread,
Jun 29, 2017, 7:21:15 AM6/29/17
to Jep Java Users, coolt...@gmail.com
Looks good to me.

Check the way the Configurable Parser is set up to make sure it has the parts you want.

Richard

gattin...@googlemail.com

unread,
Sep 20, 2017, 3:13:50 AM9/20/17
to Jep Java Users
Hi, Richard!

The grammar matcher "IndexedFunctionGrammarMatcher" works fine on indexed functions but fails on indexed lists.

For example the expression "[3, [4, 5], 6][3]" should return "6" as the result.
Another example: the expression "[[1, 2], [3, 4], [5, 6]][3][1]" should return "5" as the result.

The parser is configured like:
ConfigurableParser cp = new ConfigurableParser();
cp
.addHashComments();
cp
.addSlashComments();
cp
.addDoubleQuoteStrings();

cp
.addSingleQuoteStrings();
cp
.addWhiteSpace();
cp
.addExponentNumbers();
cp
.addOperatorTokenMatcher();
cp
.addSymbols("(", ")", "[", "]", ",");
//cp.setImplicitMultiplicationSymbols("(", "[");
cp.addTokenMatcher(IdentifierTokenMatcher.dottedIndetifierMatcher());
cp
.addGrammarMatcher(new IndexedFunctionGrammarMatcher());

cp
.addSemiColonTerminator();
cp
.addWhiteSpaceCommentFilter();
cp
.addBracketMatcher("(", ")");

cp
.addFunctionMatcher("(", ")", ",");

cp
.addListMatcher("[", "]", ",");
cp
.addArrayAccessMatcher("[", "]");

As you can see I disabled the implicit multiplication option, because I do not want the list values to be multiplicated.

Is this possible, too?

Regards,
Marcus

Richard Morris

unread,
Sep 20, 2017, 3:06:15 PM9/20/17
to Jep Java Users
Yes, we need a separate matcher for that case

/**
* Parsers to allow index access to an array[4,5,6][2].
*/
public class IndexedArrayGrammarMatcher implements GrammarMatcher {
private static final long serialVersionUID = 300L;

private final Token comma = new SymbolToken(",");
private final Token open = new SymbolToken("[");
private final Token close = new SymbolToken("]");

private transient NodeFactory nf;
private transient Operator list;

public void init(Jep jep) {
nf = jep.getNodeFactory();
list = jep.getOperatorTable().getList();
}

public Node match(Lookahead2Iterator<Token> it, GrammarParser parser) throws ParseException {
if (!open.equals(it.peekNext()))
return null;
it.consume();
if (close.equals(it.peekNext())) {
it.consume();
return nf.buildOperatorNode(list, new Node[0]);
}
List<Node> seq = new ArrayList<Node>();
while (true) {
Node contents = parser.parseSubExpression();
seq.add(contents);
if (close.equals(it.peekNext())) // this way round to cope with
// null
break;
else if (comma.equals(it.peekNext()))
it.consume();
else
throw new GrammarException("List", close, it.peekNext());
}
it.consume();
Node inner = nf.buildOperatorNode(list, seq.toArray(new Node[seq.size()]));
if (!open.equals(it.peekNext())) {
return inner;
}

List<Node> arguments = new ArrayList<Node>();
arguments.add(inner);
while (open.equals(it.peekNext())) {

// Process opening square bracket.
it.consume();

// Process index and check whether it is a positive integer
// number.
Token nextToken = it.peekNext();
Node indexNode = parser.parseSubExpression();
if (!Convert.isInteger(indexNode.getValue()) || Convert.toInteger(indexNode.getValue(), 0) < 1) {
throw new GrammarException(
String.format("'%s' is not considered to be a valid element index.", nextToken.getSource()),
nextToken);
}

// Ensure the closing square bracket comes next.
nextToken = it.peekNext();
if (!close.equals(it.peekNext())) {
throw new GrammarException(String.format("Index array expects '%s'.", close.getSource()),
nextToken);
}
arguments.add(indexNode);
// Process closing square bracket.
it.consume();

}

// Create and return the node representing the function as well
// as the indexed access.
inner = jep.getNodeFactory().buildOperatorNode(jep.getOperatorTable().getEle(),
arguments.toArray(new Node[arguments.size()]));

return inner;
}
}


A test class might be


class SeqFun extends UnaryFunction {
private static final long serialVersionUID = 1L;

@Override
public Object eval(Object arg) throws EvaluationException {
Vector<Object> res = new Vector<Object>();
int n = this.asInt(0, arg);
for (int i = 1; i <= n; ++i) {
res.add(Double.valueOf(i));
}
return res;
}
}

@Test
public void testAnonArrayAccess() throws JepException {
ConfigurableParser cp = new ConfigurableParser();
cp.addHashComments();
cp.addSlashComments();
cp.addDoubleQuoteStrings();
cp.addSingleQuoteStrings();
cp.addWhiteSpace();
cp.addExponentNumbers();
cp.addOperatorTokenMatcher();
cp.addSymbols("(", ")", "[", "]", ",");
// cp.setImplicitMultiplicationSymbols("(", "[");
cp.addTokenMatcher(IdentifierTokenMatcher.dottedIndetifierMatcher());
cp.addGrammarMatcher(new IndexedFunctionGrammarMatcher());
cp.addGrammarMatcher(new IndexedArrayGrammarMatcher());
cp.addSemiColonTerminator();
cp.addWhiteSpaceCommentFilter();
cp.addBracketMatcher("(", ")");
// cp.addFunctionMatcher("(", ")", ",");
// cp.addListMatcher("[", "]", ",");
cp.addArrayAccessMatcher("[", "]");

Jep jep = new Jep(cp);
jep.addFunction("seq", new SeqFun());

{
Node n2 = jep.parse("x=[7,8,9]");
Object o2 = jep.evaluate(n2);
assertEquals("[7.0, 8.0, 9.0]", o2.toString());
}
{
Node n2 = jep.parse("x[3]");
Object o2 = jep.evaluate(n2);
assertEquals(9.0, o2);
}

{
Node n2 = jep.parse("seq(3)[2]");
Object o2 = jep.evaluate(n2);
assertEquals(2.0, o2);
}
{
Node n2 = jep.parse("[4, 5, 6][2]");
jep.println(n2);
(new PrefixTreeDumper()).dump(n2);
Object o2 = jep.evaluate(n2);
assertEquals(5.0, o2);
}
{
Node n2 = jep.parse("[3, [4, 5], 6][3]");
jep.println(n2);
(new PrefixTreeDumper()).dump(n2);
Object o2 = jep.evaluate(n2);
assertEquals(6.0, o2);
}
{
Node n2 = jep.parse("[[1, 2], [3, 4], [5, 6]][3][1]");
jep.println(n2);
(new PrefixTreeDumper()).dump(n2);
Object o2 = jep.evaluate(n2);
assertEquals(5.0, o2);
}
}



Now I think about it a better solution would be to subclass the ShuntingYard parser and override the prefixSuffix() method. Really x[3] should be considered a suffix operation and it should apply to any particular item, either a variable x[3], a function  seq(4)[3], and array [1,2,3][2] or a more complex expression ([1,2,3]+[7,8,9])[2]. I'll try and get some example code for this written. 

Richard Morris

unread,
Sep 20, 2017, 4:31:47 PM9/20/17
to Jep Java Users
It turns out that the subclassing solution was not as complex as I though.

First, you need a shunting yard subclass

static class SuffixArrayAccessShuntingYard extends ShuntingYard {

private final Token comma = new SymbolToken(",");
private final Token open = new SymbolToken("[");
private final Token close = new SymbolToken("]");

public SuffixArrayAccessShuntingYard(Jep jep, List<GrammarMatcher> gm) {
super(jep, gm);
}

@Override
protected void prefixSuffix() throws ParseException {
        // if(DUMP) dumpState("PS");
        prefix();
        Token t;
        while(true) {
            t = it.peekNext();
            if(open.equals(t)) {
           
    List<Node> arguments = new ArrayList<Node>();
    Node lhs = nodes.pop();
    arguments.add(lhs);
    while (open.equals(it.peekNext())) {

    // Process opening square bracket.
    it.consume();

    // Process index and check whether it is a positive integer
    // number.
    Token nextToken = it.peekNext();
    Node indexNode = this.parseSubExpression();
    if (!Convert.isInteger(indexNode.getValue()) || Convert.toInteger(indexNode.getValue(), 0) < 1) {
    throw new GrammarException(
    String.format("'%s' is not considered to be a valid element index.", nextToken.getSource()),
    nextToken);
    }

    // Ensure the closing square bracket comes next.
    nextToken = it.peekNext();
    if (!close.equals(it.peekNext())) {
    throw new GrammarException(String.format("Index array expects '%s'.", close.getSource()),
    nextToken);
    }
    arguments.add(indexNode);
    // Process closing square bracket.
    it.consume();

    }

    // Create and return the node representing the function as well
    // as the indexed access.
    Node inner = jep.getNodeFactory().buildOperatorNode(jep.getOperatorTable().getEle(),
    arguments.toArray(new Node[arguments.size()]));

    nodes.push(inner);
           
            } else if(t==null || !t.isSuffix()) {
            break;
            } else {
            pushOp(((OperatorToken)t).getSuffixOp(),t);
            it.consume();
            }
        }
}
}


Then you need a helper class

public static class SuffixArrayAccessShuntingYardGrammarParserFactory implements GrammarParserFactory,Serializable {
private static final long serialVersionUID = 340L;
/**
* Create a new ShuntingYard instance.
*/
public GrammarParser newInstance(ConfigurableParser cp) {
return new SuffixArrayAccessShuntingYard(cp.getJep(),cp.getGrammarMatchers());
}
}



This is needed as each time the parser is called a new instance is created. 

The set up is a bit simpler. You need to original set of grammar matchers, and also need the add the above factory

@Test

@Test public void testGeneralArrayAccess() throws JepException { ConfigurableParser cp = new ConfigurableParser(); cp.addHashComments(); cp.addSlashComments(); cp.addDoubleQuoteStrings(); cp.addSingleQuoteStrings(); cp.addWhiteSpace(); cp.addExponentNumbers(); cp.addOperatorTokenMatcher(); cp.addSymbols("(", ")", "[", "]", ","); // cp.setImplicitMultiplicationSymbols("(", "["); cp.addTokenMatcher(IdentifierTokenMatcher.dottedIndetifierMatcher()); cp.addSemiColonTerminator(); cp.addWhiteSpaceCommentFilter(); cp.addBracketMatcher("(", ")"); cp.addFunctionMatcher("(", ")", ","); cp.addListMatcher("[", "]", ","); cp.setGrammarParserFactory(new SuffixArrayAccessShuntingYardGrammarParserFactory()); // cp.addArrayAccessMatcher("[", "]"); Jep jep = new Jep(cp); jep.addFunction("seq", new SeqFun()); { Node n2 = jep.parse("sin(pi)"); Object o2 = jep.evaluate(n2); assertEquals(0.0, (Double) o2, 1e-9); } { Node n2 = jep.parse("x=[7,8,9]"); Object o2 = jep.evaluate(n2); assertEquals("[7.0, 8.0, 9.0]", o2.toString()); } { Node n2 = jep.parse("x=[7,8,9]"); Object o2 = jep.evaluate(n2); assertEquals("[7.0, 8.0, 9.0]", o2.toString()); } { Node n2 = jep.parse("x[3]"); Object o2 = jep.evaluate(n2); assertEquals(9.0, o2); } { Node n2 = jep.parse("x[3]+x[2]"); Object o2 = jep.evaluate(n2); assertEquals(17.0, o2); } { Node n2 = jep.parse("seq(3)[2]"); Object o2 = jep.evaluate(n2); assertEquals(2.0, o2); } { Node n2 = jep.parse("[4, 5, 6][2]"); jep.println(n2); (new PrefixTreeDumper()).dump(n2); Object o2 = jep.evaluate(n2); assertEquals(5.0, o2); } { Node n2 = jep.parse("[3, [4, 5], 6][3]"); jep.println(n2); (new PrefixTreeDumper()).dump(n2); Object o2 = jep.evaluate(n2); assertEquals(6.0, o2); } { Node n2 = jep.parse("[[1, 2], [3, 4], [5, 6]][3][1]"); jep.println(n2); (new PrefixTreeDumper()).dump(n2); Object o2 = jep.evaluate(n2); assertEquals(5.0, o2); } { Node n2 = jep.parse("(x+[1,2,3])[2]"); jep.println(n2); (new PrefixTreeDumper()).dump(n2); Object o2 = jep.evaluate(n2); assertEquals(10.0, o2); } }

Note how the last test has quite a complex expression with an array access.


Richard

gattin...@googlemail.com

unread,
Oct 2, 2017, 12:35:48 PM10/2/17
to Jep Java Users
Hi, Richard!

Thank you again for your great support. As far as my tests have shown, the code works as expected. However, I will make some further test to be sure, the code will match our needs.

Kind regards,
Marcus
Reply all
Reply to author
Forward
0 new messages