Skip to content

Commit

Permalink
(feat) Supports array index access with methods and expression,close #15
Browse files Browse the repository at this point in the history
  • Loading branch information
killme2008 committed Jan 2, 2017
1 parent 239358c commit 899950a
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 16 deletions.
46 changes: 30 additions & 16 deletions src/main/java/com/googlecode/aviator/parser/ExpressionParser.java
Expand Up @@ -485,6 +485,10 @@ public void factor() {
this.move(true);
}
this.parenDepth--;
//(...)[index]
if (expectLexeme("[")) {
arrayAccess();
}
}
else if (this.lookhead.getType() == TokenType.Number || this.lookhead.getType() == TokenType.String
|| this.lookhead.getType() == TokenType.Variable || this.lookhead == Variable.TRUE
Expand All @@ -503,24 +507,14 @@ else if (this.lookhead.getType() == TokenType.Number || this.lookhead.getType()
Token<?> prev = this.prevToken;
if (prev.getType() == TokenType.Variable && this.expectLexeme("(")) {
this.method();
//method.invoke()[index]
if (expectLexeme("[")) {
arrayAccess();
}
}
else if (prev.getType() == TokenType.Variable || prev.getLexeme().equals(")")) {
// check if it is a array index access
boolean hasArray = false;
while (this.expectLexeme("[")) {
if (!hasArray) {
this.codeGenerator.onArray(this.prevToken);
this.move(true);
hasArray = true;
}
else {
this.move(true);
}
this.codeGenerator.onArrayIndexStart(this.prevToken);
array();
}
if (!hasArray)
this.codeGenerator.onConstant(this.prevToken);
//var[index]
arrayAccess();
}
else {
this.codeGenerator.onConstant(prev);
Expand All @@ -536,6 +530,26 @@ else if (this.expectLexeme("/")) {
}


private void arrayAccess() {
// check if it is a array index access
boolean hasArray = false;
while (this.expectLexeme("[")) {
if (!hasArray) {
this.codeGenerator.onArray(this.prevToken);
this.move(true);
hasArray = true;
}
else {
this.move(true);
}
this.codeGenerator.onArrayIndexStart(this.prevToken);
array();
}
if (!hasArray)
this.codeGenerator.onConstant(this.prevToken);
}


private void array() {
this.bracketDepth++;
if (RESERVED_WORDS.contains(this.prevToken.getLexeme())) {
Expand Down
Expand Up @@ -946,6 +946,57 @@ public void testIndex() {
}


@Test
public void testArrayIndexAccessWithMethod() {
assertEquals("a", AviatorEvaluator.exec("string.split('a,b,c,d',',')[0]"));
assertEquals("b", AviatorEvaluator.exec("string.split('a,b,c,d',',')[1]"));
assertEquals("c", AviatorEvaluator.exec("string.split('a,b,c,d',',')[2]"));
assertEquals("d", AviatorEvaluator.exec("string.split('a,b,c,d',',')[3]"));
try {
AviatorEvaluator.exec("string.split('a,b,c,d',',')[4]");
fail();
}
catch (ExpressionRuntimeException e) {

}

assertEquals("a", AviatorEvaluator.exec("string.split(s,',')[0]", "a,b,c,d"));
assertEquals("b", AviatorEvaluator.exec("string.split(s,',')[1]", "a,b,c,d"));
assertEquals("c", AviatorEvaluator.exec("string.split(s,',')[2]", "a,b,c,d"));
assertEquals("d", AviatorEvaluator.exec("string.split(s,',')[3]", "a,b,c,d"));
}


@Test
public void testArrayIndexAccessWithMethodAndBracket() {
assertEquals("a", AviatorEvaluator.exec("(string.split('a,b,c,d',','))[0]"));
assertEquals("b", AviatorEvaluator.exec("(string.split('a,b,c,d',','))[1]"));
assertEquals("c", AviatorEvaluator.exec("(string.split('a,b,c,d',','))[2]"));
assertEquals("d", AviatorEvaluator.exec("(string.split('a,b,c,d',','))[3]"));
try {
AviatorEvaluator.exec("(string.split('a,b,c,d',','))[4]");
fail();
}
catch (ExpressionRuntimeException e) {

}
assertEquals("a", AviatorEvaluator.exec("(string.split(s,','))[0]", "a,b,c,d"));
assertEquals("b", AviatorEvaluator.exec("(string.split(s,','))[1]", "a,b,c,d"));
assertEquals("c", AviatorEvaluator.exec("(string.split(s,','))[2]", "a,b,c,d"));
assertEquals("d", AviatorEvaluator.exec("(string.split(s,','))[3]", "a,b,c,d"));
}

@Test(expected = CompileExpressionErrorException.class)
public void testIllegalArrayIndexAccessWithMethod1(){
AviatorEvaluator.exec("string.split('a,b,c,d',',')[0");
}

@Test(expected = CompileExpressionErrorException.class)
public void testIllegalArrayIndexAccessWithMethod2(){
AviatorEvaluator.exec("string.split('a,b,c,d',','[0]");
}


@Test
public void testFunctionCall() {
Map<String, Object> env = this.createEnv();
Expand Down

0 comments on commit 899950a

Please sign in to comment.