From 5aa095e2224ed6dfffed5f3d6e12017aaecec13e Mon Sep 17 00:00:00 2001 From: dennis zhuang Date: Sat, 15 Oct 2016 15:37:56 +0800 Subject: [PATCH] (feat) Parse array --- .../aviator/code/ConstantsCollector.java | 263 ++++++++++++++++++ .../aviator/lexer/token/ArrayToken.java | 77 +++++ .../googlecode/aviator/lexer/token/Token.java | 1 + .../aviator/parser/ExpressionParser.java | 47 +++- .../aviator/example/SimpleExample.java | 2 +- 5 files changed, 386 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/googlecode/aviator/code/ConstantsCollector.java create mode 100644 src/main/java/com/googlecode/aviator/lexer/token/ArrayToken.java diff --git a/src/main/java/com/googlecode/aviator/code/ConstantsCollector.java b/src/main/java/com/googlecode/aviator/code/ConstantsCollector.java new file mode 100644 index 00000000..916c2cdc --- /dev/null +++ b/src/main/java/com/googlecode/aviator/code/ConstantsCollector.java @@ -0,0 +1,263 @@ +package com.googlecode.aviator.code; + +import java.util.ArrayList; +import java.util.List; + +import com.googlecode.aviator.Expression; +import com.googlecode.aviator.LiteralExpression; +import com.googlecode.aviator.lexer.token.Token; + + +public class ConstantsCollector implements CodeGenerator { + + public List> getConstants() { + return constants; + } + + private List> constants = new ArrayList>(); + + + @Override + public void onShiftRight(Token lookhead) { + throw new UnsupportedOperationException(); + } + + + @Override + public void onShiftLeft(Token lookhead) { + throw new UnsupportedOperationException(); + } + + + @Override + public void onUnsignedShiftRight(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onBitOr(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onBitAnd(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onBitXor(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onBitNot(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onAdd(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onSub(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onMult(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onDiv(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onAndLeft(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onAndRight(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onTernaryBoolean(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onTernaryLeft(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onTernaryRight(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onJoinLeft(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onJoinRight(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onEq(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onMatch(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onNeq(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onLt(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onLe(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onGt(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onGe(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onMod(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onNot(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onNeg(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public Expression getResult() { + return new LiteralExpression(this.constants, null); + } + + + @Override + public void onConstant(Token lookhead) { + this.constants.add(lookhead); + } + + + @Override + public void onMethodName(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onMethodParameter(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onMethodInvoke(Token lookhead) { + throw new UnsupportedOperationException(); + + } + + + @Override + public void onArray(Token lookhead) { + throw new UnsupportedOperationException(); + } + + + @Override + public void onArrayIndexStart(Token token) { + throw new UnsupportedOperationException(); + } + + + @Override + public void onArrayIndexEnd(Token lookhead) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/com/googlecode/aviator/lexer/token/ArrayToken.java b/src/main/java/com/googlecode/aviator/lexer/token/ArrayToken.java new file mode 100644 index 00000000..a32c18fd --- /dev/null +++ b/src/main/java/com/googlecode/aviator/lexer/token/ArrayToken.java @@ -0,0 +1,77 @@ +package com.googlecode.aviator.lexer.token; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +/** + * Array token, only created by parser. + * + * @author dennis + * + */ +public class ArrayToken implements Token> { + private List> values; + + private List result; + + private int index; + + + public ArrayToken(List> values, int index) { + super(); + this.values = values; + this.index = index; + } + + + @Override + public List getValue(Map env) { + if (result == null) { + result = new ArrayList(); + for (Token t : this.values) { + result.add(t.getValue(env)); + } + } + return result; + } + + @Override + public com.googlecode.aviator.lexer.token.Token.TokenType getType() { + return TokenType.Array; + } + + + @Override + public String getLexeme() { + StringBuilder sb = new StringBuilder("["); + boolean wasFirst = true; + for (Object o : this.values) { + String literal = "nil"; + if (o != null) { + if (o instanceof String) { + literal = "\"" + o.toString() + "\""; + } + else { + literal = o.toString(); + } + } + if (wasFirst) { + sb.append(literal); + wasFirst = false; + } + else { + sb.append(", ").append(literal); + } + } + return sb.toString(); + } + + + @Override + public int getStartIndex() { + return this.index; + } + +} diff --git a/src/main/java/com/googlecode/aviator/lexer/token/Token.java b/src/main/java/com/googlecode/aviator/lexer/token/Token.java index d4adfcec..c47102fc 100644 --- a/src/main/java/com/googlecode/aviator/lexer/token/Token.java +++ b/src/main/java/com/googlecode/aviator/lexer/token/Token.java @@ -33,6 +33,7 @@ public enum TokenType { String, Variable, Number, + Array, Char, Operator, Pattern, diff --git a/src/main/java/com/googlecode/aviator/parser/ExpressionParser.java b/src/main/java/com/googlecode/aviator/parser/ExpressionParser.java index 014d4e60..a68144a1 100644 --- a/src/main/java/com/googlecode/aviator/parser/ExpressionParser.java +++ b/src/main/java/com/googlecode/aviator/parser/ExpressionParser.java @@ -18,14 +18,20 @@ **/ package com.googlecode.aviator.parser; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; import java.util.HashSet; +import java.util.List; import java.util.Set; import com.googlecode.aviator.AviatorEvaluator; import com.googlecode.aviator.Expression; import com.googlecode.aviator.code.CodeGenerator; +import com.googlecode.aviator.code.ConstantsCollector; import com.googlecode.aviator.exception.ExpressionSyntaxErrorException; import com.googlecode.aviator.lexer.ExpressionLexer; +import com.googlecode.aviator.lexer.token.ArrayToken; import com.googlecode.aviator.lexer.token.CharToken; import com.googlecode.aviator.lexer.token.PatternToken; import com.googlecode.aviator.lexer.token.Token; @@ -55,7 +61,9 @@ public class ExpressionParser { private Token prevToken; - private final CodeGenerator codeGenerator; + private CodeGenerator codeGenerator; + + private Deque cgStack = new ArrayDeque(); // Paren depth private int parenDepth = 0; @@ -470,6 +478,20 @@ public boolean isOPVariable(Token token) { } + public void array() { + while (true) { + this.factor(); + if (this.expectLexeme(",")) { + this.move(true); + continue; + } + else { + break; + } + } + } + + public void factor() { if (this.lookhead == null) { this.reportSyntaxError("invalid value"); @@ -486,6 +508,25 @@ public void factor() { } this.parenDepth--; } + else if (this.expectLexeme("[")) { + this.bracketDepth++; + int index = this.lookhead.getStartIndex(); + this.move(true); + this.cgStack.push(this.codeGenerator); + ConstantsCollector collector = new ConstantsCollector(); + this.codeGenerator = collector; + this.array(); + if (!expectLexeme("]")) { + this.reportSyntaxError("insert ']' to complete array."); + } + else { + this.move(true); + } + this.codeGenerator = this.cgStack.pop(); + this.prevToken = new ArrayToken(collector.getConstants(), index); + this.bracketDepth--; + this.codeGenerator.onConstant(this.prevToken); + } else if (this.lookhead.getType() == TokenType.Number || this.lookhead.getType() == TokenType.String || this.lookhead.getType() == TokenType.Variable || this.lookhead == Variable.TRUE || this.lookhead == Variable.FALSE || this.isOPVariable(this.lookhead)) { @@ -517,7 +558,7 @@ else if (prev.getType() == TokenType.Variable || prev.getLexeme().equals(")")) { this.move(true); } this.codeGenerator.onArrayIndexStart(this.prevToken); - array(); + arrayIndex(); } if (!hasArray) this.codeGenerator.onConstant(this.prevToken); @@ -536,7 +577,7 @@ else if (this.expectLexeme("/")) { } - private void array() { + private void arrayIndex() { this.bracketDepth++; if (RESERVED_WORDS.contains(this.prevToken.getLexeme())) { throw new ExpressionSyntaxErrorException(this.prevToken.getLexeme() + " could not use [] operator"); diff --git a/src/test/java/com/googlecode/aviator/example/SimpleExample.java b/src/test/java/com/googlecode/aviator/example/SimpleExample.java index b174e563..3b5a48ec 100644 --- a/src/test/java/com/googlecode/aviator/example/SimpleExample.java +++ b/src/test/java/com/googlecode/aviator/example/SimpleExample.java @@ -5,7 +5,7 @@ public class SimpleExample { public static void main(String[] args) { - Long result = (Long) AviatorEvaluator.execute("1+2+3"); + Long result = (Long) AviatorEvaluator.execute("[1,2,3]"); System.out.println(result); } }