(feat) Parse array
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 0000000..916c2cd
--- /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<Token<?>> getConstants() {
+        return constants;
+    }
+
+    private List<Token<?>> constants = new ArrayList<Token<?>>();
+
+
+    @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 0000000..a32c18f
--- /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<List<Object>> {
+    private List<Token<?>> values;
+
+    private List<Object> result;
+
+    private int index;
+
+
+    public ArrayToken(List<Token<?>> values, int index) {
+        super();
+        this.values = values;
+        this.index = index;
+    }
+
+
+    @Override
+    public List<Object> getValue(Map<String, Object> env) {
+        if (result == null) {
+            result = new ArrayList<Object>();
+            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 d4adfce..c47102f 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 @@
         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 014d4e6..a68144a 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 @@
 
     private Token<?> prevToken;
 
-    private final CodeGenerator codeGenerator;
+    private CodeGenerator codeGenerator;
+
+    private Deque<CodeGenerator> cgStack = new ArrayDeque<CodeGenerator>();
 
     // Paren depth
     private int parenDepth = 0;
@@ -470,6 +478,20 @@
     }
 
 
+    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 @@
             }
             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 @@
                         this.move(true);
                     }
                     this.codeGenerator.onArrayIndexStart(this.prevToken);
-                    array();
+                    arrayIndex();
                 }
                 if (!hasArray)
                     this.codeGenerator.onConstant(this.prevToken);
@@ -536,7 +577,7 @@
     }
 
 
-    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 b174e56..3b5a48e 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);
     }
 }