From 899950a4742da64c5f2e1be96875a9a8ef410378 Mon Sep 17 00:00:00 2001 From: dennis zhuang Date: Mon, 2 Jan 2017 21:48:15 +0800 Subject: [PATCH] (feat) Supports array index access with methods and expression,close #15 --- .../aviator/parser/ExpressionParser.java | 46 +++++++++++------ .../test/function/GrammarUnitTest.java | 51 +++++++++++++++++++ 2 files changed, 81 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/googlecode/aviator/parser/ExpressionParser.java b/src/main/java/com/googlecode/aviator/parser/ExpressionParser.java index 014d4e60..45379d30 100644 --- a/src/main/java/com/googlecode/aviator/parser/ExpressionParser.java +++ b/src/main/java/com/googlecode/aviator/parser/ExpressionParser.java @@ -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 @@ -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); @@ -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())) { diff --git a/src/test/java/com/googlecode/aviator/test/function/GrammarUnitTest.java b/src/test/java/com/googlecode/aviator/test/function/GrammarUnitTest.java index e8448062..8cb50438 100644 --- a/src/test/java/com/googlecode/aviator/test/function/GrammarUnitTest.java +++ b/src/test/java/com/googlecode/aviator/test/function/GrammarUnitTest.java @@ -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 env = this.createEnv();