You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2017/08/16 15:36:54 UTC

[02/13] cayenne git commit: Own template render implementation: first draft

http://git-wip-us.apache.org/repos/asf/cayenne/blob/55e3c975/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParser.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParser.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParser.java
new file mode 100644
index 0000000..952dd06
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParser.java
@@ -0,0 +1,634 @@
+/* Generated By:JJTree&JavaCC: Do not edit this line. SQLTemplateParser.java */
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.template.parser;
+
+/**
+  * Parser of Cayenne Templates.
+  *
+  * @since 4.1
+  */
+public class SQLTemplateParser/*@bgen(jjtree)*/implements SQLTemplateParserTreeConstants, SQLTemplateParserConstants {/*@bgen(jjtree)*/
+  protected JJTSQLTemplateParserState jjtree = new JJTSQLTemplateParserState();
+
+  final public ASTBlock template() throws ParseException {
+    block();
+    jj_consume_token(0);
+        {if (true) return (ASTBlock) jjtree.rootNode();}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public void block() throws ParseException {
+                       /*@bgen(jjtree) Block */
+  ASTBlock jjtn000 = new ASTBlock(JJTBLOCK);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+    try {
+      label_1:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case IF:
+        case SHARP:
+        case TEXT:
+          ;
+          break;
+        default:
+          jj_la1[0] = jj_gen;
+          break label_1;
+        }
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case TEXT:
+          text();
+          break;
+        case IF:
+          ifElse();
+          break;
+        case SHARP:
+          directive();
+          break;
+        default:
+          jj_la1[1] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+      }
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        {if (true) throw (RuntimeException)jjte000;}
+      }
+      if (jjte000 instanceof ParseException) {
+        {if (true) throw (ParseException)jjte000;}
+      }
+      {if (true) throw (Error)jjte000;}
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+  }
+
+  final public void text() throws ParseException {
+                     /*@bgen(jjtree) Text */
+    ASTText jjtn000 = new ASTText(JJTTEXT);
+    boolean jjtc000 = true;
+    jjtree.openNodeScope(jjtn000);Token t;
+    try {
+      t = jj_consume_token(TEXT);
+                 jjtree.closeNodeScope(jjtn000, true);
+                 jjtc000 = false;
+        jjtn000.setValue(t.image);
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+  }
+
+  final public void ifElse() throws ParseException {
+                         /*@bgen(jjtree) IfElse */
+  ASTIfElse jjtn000 = new ASTIfElse(JJTIFELSE);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+    try {
+      jj_consume_token(IF);
+      jj_consume_token(LBRACKET);
+      expression();
+      jj_consume_token(RBRACKET);
+      block();
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case ELSE:
+        jj_consume_token(ELSE);
+        block();
+        break;
+      default:
+        jj_la1[2] = jj_gen;
+        ;
+      }
+      jj_consume_token(END);
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        {if (true) throw (RuntimeException)jjte000;}
+      }
+      if (jjte000 instanceof ParseException) {
+        {if (true) throw (ParseException)jjte000;}
+      }
+      {if (true) throw (Error)jjte000;}
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+  }
+
+  final public void directive() throws ParseException {
+                               /*@bgen(jjtree) Directive */
+    ASTDirective jjtn000 = new ASTDirective(JJTDIRECTIVE);
+    boolean jjtc000 = true;
+    jjtree.openNodeScope(jjtn000);Token t;
+    try {
+      jj_consume_token(SHARP);
+      t = jj_consume_token(IDENTIFIER);
+        jjtn000.setIdentifier(t.image);
+      jj_consume_token(LBRACKET);
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case TRUE:
+      case FALSE:
+      case DOLLAR:
+      case SINGLE_QUOTED_STRING:
+      case DOUBLE_QUOTED_STRING:
+      case INT_LITERAL:
+      case FLOAT_LITERAL:
+        expression();
+        label_2:
+        while (true) {
+          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+          case COMMA:
+            ;
+            break;
+          default:
+            jj_la1[3] = jj_gen;
+            break label_2;
+          }
+          jj_consume_token(COMMA);
+          expression();
+        }
+        break;
+      default:
+        jj_la1[4] = jj_gen;
+        ;
+      }
+      jj_consume_token(RBRACKET);
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        {if (true) throw (RuntimeException)jjte000;}
+      }
+      if (jjte000 instanceof ParseException) {
+        {if (true) throw (ParseException)jjte000;}
+      }
+      {if (true) throw (Error)jjte000;}
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+  }
+
+  final public void expression() throws ParseException {
+                                 /*@bgen(jjtree) Expression */
+  ASTExpression jjtn000 = new ASTExpression(JJTEXPRESSION);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+    try {
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case TRUE:
+      case FALSE:
+      case SINGLE_QUOTED_STRING:
+      case DOUBLE_QUOTED_STRING:
+      case INT_LITERAL:
+      case FLOAT_LITERAL:
+        scalar();
+        break;
+      case DOLLAR:
+        variable();
+        break;
+      default:
+        jj_la1[5] = jj_gen;
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        {if (true) throw (RuntimeException)jjte000;}
+      }
+      if (jjte000 instanceof ParseException) {
+        {if (true) throw (ParseException)jjte000;}
+      }
+      {if (true) throw (Error)jjte000;}
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+  }
+
+  final public void scalar() throws ParseException {
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case SINGLE_QUOTED_STRING:
+      jj_consume_token(SINGLE_QUOTED_STRING);
+                             ASTStringScalar jjtn001 = new ASTStringScalar(JJTSTRINGSCALAR);
+                             boolean jjtc001 = true;
+                             jjtree.openNodeScope(jjtn001);
+      try {
+                             jjtree.closeNodeScope(jjtn001,  0);
+                             jjtc001 = false;
+                             jjtn001.setValue((String)token_source.literalValue);
+      } finally {
+                             if (jjtc001) {
+                               jjtree.closeNodeScope(jjtn001,  0);
+                             }
+      }
+      break;
+    case DOUBLE_QUOTED_STRING:
+      jj_consume_token(DOUBLE_QUOTED_STRING);
+                                 ASTStringScalar jjtn002 = new ASTStringScalar(JJTSTRINGSCALAR);
+                                 boolean jjtc002 = true;
+                                 jjtree.openNodeScope(jjtn002);
+      try {
+                                 jjtree.closeNodeScope(jjtn002,  0);
+                                 jjtc002 = false;
+                                 jjtn002.setValue((String)token_source.literalValue);
+      } finally {
+                                 if (jjtc002) {
+                                   jjtree.closeNodeScope(jjtn002,  0);
+                                 }
+      }
+      break;
+    case INT_LITERAL:
+      jj_consume_token(INT_LITERAL);
+                          ASTIntScalar jjtn003 = new ASTIntScalar(JJTINTSCALAR);
+                          boolean jjtc003 = true;
+                          jjtree.openNodeScope(jjtn003);
+      try {
+                          jjtree.closeNodeScope(jjtn003,  0);
+                          jjtc003 = false;
+                          jjtn003.setValue((Long)token_source.literalValue);
+      } finally {
+                          if (jjtc003) {
+                            jjtree.closeNodeScope(jjtn003,  0);
+                          }
+      }
+      break;
+    case FLOAT_LITERAL:
+      jj_consume_token(FLOAT_LITERAL);
+                          ASTFloatScalar jjtn004 = new ASTFloatScalar(JJTFLOATSCALAR);
+                          boolean jjtc004 = true;
+                          jjtree.openNodeScope(jjtn004);
+      try {
+                          jjtree.closeNodeScope(jjtn004,  0);
+                          jjtc004 = false;
+                          jjtn004.setValue((Double)token_source.literalValue);
+      } finally {
+                          if (jjtc004) {
+                            jjtree.closeNodeScope(jjtn004,  0);
+                          }
+      }
+      break;
+    case TRUE:
+      jj_consume_token(TRUE);
+                  ASTBoolScalar jjtn005 = new ASTBoolScalar(JJTBOOLSCALAR);
+                  boolean jjtc005 = true;
+                  jjtree.openNodeScope(jjtn005);
+      try {
+                  jjtree.closeNodeScope(jjtn005,  0);
+                  jjtc005 = false;
+                  jjtn005.setValue(true);
+      } finally {
+                  if (jjtc005) {
+                    jjtree.closeNodeScope(jjtn005,  0);
+                  }
+      }
+      break;
+    case FALSE:
+      jj_consume_token(FALSE);
+                  ASTBoolScalar jjtn006 = new ASTBoolScalar(JJTBOOLSCALAR);
+                  boolean jjtc006 = true;
+                  jjtree.openNodeScope(jjtn006);
+      try {
+                  jjtree.closeNodeScope(jjtn006,  0);
+                  jjtc006 = false;
+                  jjtn006.setValue(false);
+      } finally {
+                  if (jjtc006) {
+                    jjtree.closeNodeScope(jjtn006,  0);
+                  }
+      }
+      break;
+    default:
+      jj_la1[6] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+  }
+
+  final public void variable() throws ParseException {
+                             /*@bgen(jjtree) Variable */
+    ASTVariable jjtn000 = new ASTVariable(JJTVARIABLE);
+    boolean jjtc000 = true;
+    jjtree.openNodeScope(jjtn000);Token t;
+    try {
+      jj_consume_token(DOLLAR);
+      t = jj_consume_token(IDENTIFIER);
+        jjtn000.setIdentifier(t.image);
+      label_3:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case DOT:
+          ;
+          break;
+        default:
+          jj_la1[7] = jj_gen;
+          break label_3;
+        }
+        jj_consume_token(DOT);
+        method();
+      }
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        {if (true) throw (RuntimeException)jjte000;}
+      }
+      if (jjte000 instanceof ParseException) {
+        {if (true) throw (ParseException)jjte000;}
+      }
+      {if (true) throw (Error)jjte000;}
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+  }
+
+  final public void method() throws ParseException {
+                         /*@bgen(jjtree) Method */
+    ASTMethod jjtn000 = new ASTMethod(JJTMETHOD);
+    boolean jjtc000 = true;
+    jjtree.openNodeScope(jjtn000);Token t;
+    try {
+      t = jj_consume_token(IDENTIFIER);
+        jjtn000.setIdentifier(t.image);
+      jj_consume_token(LBRACKET);
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case TRUE:
+      case FALSE:
+      case DOLLAR:
+      case SINGLE_QUOTED_STRING:
+      case DOUBLE_QUOTED_STRING:
+      case INT_LITERAL:
+      case FLOAT_LITERAL:
+        expression();
+        label_4:
+        while (true) {
+          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+          case COMMA:
+            ;
+            break;
+          default:
+            jj_la1[8] = jj_gen;
+            break label_4;
+          }
+          jj_consume_token(COMMA);
+          expression();
+        }
+        break;
+      default:
+        jj_la1[9] = jj_gen;
+        ;
+      }
+      jj_consume_token(RBRACKET);
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        {if (true) throw (RuntimeException)jjte000;}
+      }
+      if (jjte000 instanceof ParseException) {
+        {if (true) throw (ParseException)jjte000;}
+      }
+      {if (true) throw (Error)jjte000;}
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+      }
+    }
+  }
+
+  /** Generated Token Manager. */
+  public SQLTemplateParserTokenManager token_source;
+  JavaCharStream jj_input_stream;
+  /** Current token. */
+  public Token token;
+  /** Next token. */
+  public Token jj_nt;
+  private int jj_ntk;
+  private int jj_gen;
+  final private int[] jj_la1 = new int[10];
+  static private int[] jj_la1_0;
+  static private int[] jj_la1_1;
+  static {
+      jj_la1_init_0();
+      jj_la1_init_1();
+   }
+   private static void jj_la1_init_0() {
+      jj_la1_0 = new int[] {0x102,0x102,0x4,0x1000,0x39000230,0x39000230,0x39000030,0x2000,0x1000,0x39000230,};
+   }
+   private static void jj_la1_init_1() {
+      jj_la1_1 = new int[] {0x10,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,};
+   }
+
+  /** Constructor with InputStream. */
+  public SQLTemplateParser(java.io.InputStream stream) {
+     this(stream, null);
+  }
+  /** Constructor with InputStream and supplied encoding */
+  public SQLTemplateParser(java.io.InputStream stream, String encoding) {
+    try { jj_input_stream = new JavaCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+    token_source = new SQLTemplateParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 10; i++) jj_la1[i] = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream stream) {
+     ReInit(stream, null);
+  }
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream stream, String encoding) {
+    try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+    token_source.ReInit(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jjtree.reset();
+    jj_gen = 0;
+    for (int i = 0; i < 10; i++) jj_la1[i] = -1;
+  }
+
+  /** Constructor. */
+  public SQLTemplateParser(java.io.Reader stream) {
+    jj_input_stream = new JavaCharStream(stream, 1, 1);
+    token_source = new SQLTemplateParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 10; i++) jj_la1[i] = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader stream) {
+    jj_input_stream.ReInit(stream, 1, 1);
+    token_source.ReInit(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jjtree.reset();
+    jj_gen = 0;
+    for (int i = 0; i < 10; i++) jj_la1[i] = -1;
+  }
+
+  /** Constructor with generated Token Manager. */
+  public SQLTemplateParser(SQLTemplateParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 10; i++) jj_la1[i] = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(SQLTemplateParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jjtree.reset();
+    jj_gen = 0;
+    for (int i = 0; i < 10; i++) jj_la1[i] = -1;
+  }
+
+  private Token jj_consume_token(int kind) throws ParseException {
+    Token oldToken;
+    if ((oldToken = token).next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    if (token.kind == kind) {
+      jj_gen++;
+      return token;
+    }
+    token = oldToken;
+    jj_kind = kind;
+    throw generateParseException();
+  }
+
+
+/** Get the next Token. */
+  final public Token getNextToken() {
+    if (token.next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    jj_gen++;
+    return token;
+  }
+
+/** Get the specific Token. */
+  final public Token getToken(int index) {
+    Token t = token;
+    for (int i = 0; i < index; i++) {
+      if (t.next != null) t = t.next;
+      else t = t.next = token_source.getNextToken();
+    }
+    return t;
+  }
+
+  private int jj_ntk() {
+    if ((jj_nt=token.next) == null)
+      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
+    else
+      return (jj_ntk = jj_nt.kind);
+  }
+
+  private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>();
+  private int[] jj_expentry;
+  private int jj_kind = -1;
+
+  /** Generate ParseException. */
+  public ParseException generateParseException() {
+    jj_expentries.clear();
+    boolean[] la1tokens = new boolean[37];
+    if (jj_kind >= 0) {
+      la1tokens[jj_kind] = true;
+      jj_kind = -1;
+    }
+    for (int i = 0; i < 10; i++) {
+      if (jj_la1[i] == jj_gen) {
+        for (int j = 0; j < 32; j++) {
+          if ((jj_la1_0[i] & (1<<j)) != 0) {
+            la1tokens[j] = true;
+          }
+          if ((jj_la1_1[i] & (1<<j)) != 0) {
+            la1tokens[32+j] = true;
+          }
+        }
+      }
+    }
+    for (int i = 0; i < 37; i++) {
+      if (la1tokens[i]) {
+        jj_expentry = new int[1];
+        jj_expentry[0] = i;
+        jj_expentries.add(jj_expentry);
+      }
+    }
+    int[][] exptokseq = new int[jj_expentries.size()][];
+    for (int i = 0; i < jj_expentries.size(); i++) {
+      exptokseq[i] = jj_expentries.get(i);
+    }
+    return new ParseException(token, exptokseq, tokenImage);
+  }
+
+  /** Enable tracing. */
+  final public void enable_tracing() {
+  }
+
+  /** Disable tracing. */
+  final public void disable_tracing() {
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/55e3c975/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserConstants.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserConstants.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserConstants.java
new file mode 100644
index 0000000..4d1337a
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserConstants.java
@@ -0,0 +1,143 @@
+/* Generated By:JJTree&JavaCC: Do not edit this line. SQLTemplateParserConstants.java */
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.template.parser;
+
+
+/**
+ * Token literal values and constants.
+ * Generated by org.javacc.parser.OtherFilesGen#start()
+ */
+public interface SQLTemplateParserConstants {
+
+  /** End of File. */
+  int EOF = 0;
+  /** RegularExpression Id. */
+  int IF = 1;
+  /** RegularExpression Id. */
+  int ELSE = 2;
+  /** RegularExpression Id. */
+  int END = 3;
+  /** RegularExpression Id. */
+  int TRUE = 4;
+  /** RegularExpression Id. */
+  int FALSE = 5;
+  /** RegularExpression Id. */
+  int WHITESPACE = 6;
+  /** RegularExpression Id. */
+  int NEWLINE = 7;
+  /** RegularExpression Id. */
+  int SHARP = 8;
+  /** RegularExpression Id. */
+  int DOLLAR = 9;
+  /** RegularExpression Id. */
+  int LBRACKET = 10;
+  /** RegularExpression Id. */
+  int RBRACKET = 11;
+  /** RegularExpression Id. */
+  int COMMA = 12;
+  /** RegularExpression Id. */
+  int DOT = 13;
+  /** RegularExpression Id. */
+  int IDENTIFIER = 14;
+  /** RegularExpression Id. */
+  int LETTER = 15;
+  /** RegularExpression Id. */
+  int DIGIT = 16;
+  /** RegularExpression Id. */
+  int SINGLE_LINE_COMMENT_END = 18;
+  /** RegularExpression Id. */
+  int ESC = 22;
+  /** RegularExpression Id. */
+  int SINGLE_QUOTED_STRING = 24;
+  /** RegularExpression Id. */
+  int STRING_ESC = 25;
+  /** RegularExpression Id. */
+  int DOUBLE_QUOTED_STRING = 27;
+  /** RegularExpression Id. */
+  int INT_LITERAL = 28;
+  /** RegularExpression Id. */
+  int FLOAT_LITERAL = 29;
+  /** RegularExpression Id. */
+  int DEC_FLT = 30;
+  /** RegularExpression Id. */
+  int DEC_DIGITS = 31;
+  /** RegularExpression Id. */
+  int EXPONENT = 32;
+  /** RegularExpression Id. */
+  int FLT_SUFF = 33;
+  /** RegularExpression Id. */
+  int DOUBLE_ESCAPE = 34;
+  /** RegularExpression Id. */
+  int ESCAPE = 35;
+  /** RegularExpression Id. */
+  int TEXT = 36;
+
+  /** Lexical state. */
+  int DEFAULT = 0;
+  /** Lexical state. */
+  int IN_SINGLE_LINE_COMMENT = 1;
+  /** Lexical state. */
+  int WithinSingleQuoteLiteral = 2;
+  /** Lexical state. */
+  int WithinDoubleQuoteLiteral = 3;
+
+  /** Literal token values. */
+  String[] tokenImage = {
+    "<EOF>",
+    "\"#if\"",
+    "\"#else\"",
+    "\"#end\"",
+    "<TRUE>",
+    "<FALSE>",
+    "<WHITESPACE>",
+    "<NEWLINE>",
+    "\"#\"",
+    "\"$\"",
+    "\"(\"",
+    "\")\"",
+    "\",\"",
+    "\".\"",
+    "<IDENTIFIER>",
+    "<LETTER>",
+    "<DIGIT>",
+    "\"##\"",
+    "<SINGLE_LINE_COMMENT_END>",
+    "<token of kind 19>",
+    "\"\\\'\"",
+    "\"\\\"\"",
+    "<ESC>",
+    "<token of kind 23>",
+    "\"\\\'\"",
+    "<STRING_ESC>",
+    "<token of kind 26>",
+    "\"\\\"\"",
+    "<INT_LITERAL>",
+    "<FLOAT_LITERAL>",
+    "<DEC_FLT>",
+    "<DEC_DIGITS>",
+    "<EXPONENT>",
+    "<FLT_SUFF>",
+    "\"\\\\\\\\\"",
+    "\"\\\\\"",
+    "<TEXT>",
+  };
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/55e3c975/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTokenManager.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTokenManager.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTokenManager.java
new file mode 100644
index 0000000..2db5d13
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTokenManager.java
@@ -0,0 +1,1440 @@
+/* Generated By:JJTree&JavaCC: Do not edit this line. SQLTemplateParserTokenManager.java */
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.template.parser;
+
+/** Token Manager. */
+public class SQLTemplateParserTokenManager implements SQLTemplateParserConstants
+{
+    /** Holds the last value computed by a constant token. */
+    Object literalValue;
+
+    /** Holds the last string literal parsed. */
+    private StringBuffer stringBuffer;
+
+    /** Converts an escape sequence into a character value. */
+    private char escapeChar() {
+        int ofs = image.length() - 1;
+        switch ( image.charAt(ofs) ) {
+            case 'n':   return '\u005cn';
+            case 'r':   return '\u005cr';
+            case 't':   return '\u005ct';
+            case 'b':   return '\u005cb';
+            case 'f':   return '\u005cf';
+            case '\u005c\u005c':  return '\u005c\u005c';
+            case '\u005c'':  return '\u005c'';
+            case '\u005c"':  return '\u005c"';
+        }
+
+          // Otherwise, it's an octal number.  Find the backslash and convert.
+        while ( image.charAt(--ofs) != '\u005c\u005c' ){
+        }
+
+        int value = 0;
+        while ( ++ofs < image.length() ) {
+            value = (value << 3) | (image.charAt(ofs) - '0');
+        }
+        return (char) value;
+    }
+
+    private Object makeInt() {
+        Object  result;
+        String  s = image.toString();
+        int     base = 10;
+
+        if ( s.charAt(0) == '0' ) {
+            base = (s.length() > 1 && (s.charAt(1) == 'x' || s.charAt(1) == 'X'))? 16 : 8;
+        }
+        if ( base == 16 ) {
+            s = s.substring(2); // Trim the 0x off the front
+        }
+
+        switch ( s.charAt(s.length()-1) ) {
+            case 'l': case 'L':
+                result = Long.valueOf( s.substring(0,s.length()-1), base );
+                break;
+
+            default:
+                result = Long.valueOf( s, base );
+                break;
+        }
+        return result;
+    }
+
+    private Object makeFloat() {
+        String s = image.toString();
+        switch ( s.charAt(s.length()-1) ) {
+            case 'f': case 'F':
+                return Double.valueOf( s );
+
+            case 'd': case 'D':
+            default:
+                return Double.valueOf( s );
+        }
+    }
+
+  /** Debug output. */
+  public  java.io.PrintStream debugStream = System.out;
+  /** Set debug output. */
+  public  void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
+private final int jjStopStringLiteralDfa_0(int pos, long active0)
+{
+   switch (pos)
+   {
+      case 0:
+         if ((active0 & 0x300c00L) != 0L)
+            return 50;
+         if ((active0 & 0x2000L) != 0L)
+            return 51;
+         return -1;
+      default :
+         return -1;
+   }
+}
+private final int jjStartNfa_0(int pos, long active0)
+{
+   return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
+}
+private int jjStopAtPos(int pos, int kind)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   return pos + 1;
+}
+private int jjMoveStringLiteralDfa0_0()
+{
+   switch(curChar)
+   {
+      case 34:
+         return jjStartNfaWithStates_0(0, 21, 50);
+      case 35:
+         jjmatchedKind = 8;
+         return jjMoveStringLiteralDfa1_0(0x2000eL);
+      case 36:
+         return jjStopAtPos(0, 9);
+      case 39:
+         return jjStartNfaWithStates_0(0, 20, 50);
+      case 40:
+         return jjStartNfaWithStates_0(0, 10, 50);
+      case 41:
+         return jjStartNfaWithStates_0(0, 11, 50);
+      case 46:
+         return jjStartNfaWithStates_0(0, 13, 51);
+      case 92:
+         jjmatchedKind = 35;
+         return jjMoveStringLiteralDfa1_0(0x400000000L);
+      default :
+         return jjMoveNfa_0(3, 0);
+   }
+}
+private int jjMoveStringLiteralDfa1_0(long active0)
+{
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(0, active0);
+      return 1;
+   }
+   switch(curChar)
+   {
+      case 35:
+         if ((active0 & 0x20000L) != 0L)
+            return jjStopAtPos(1, 17);
+         break;
+      case 92:
+         if ((active0 & 0x400000000L) != 0L)
+            return jjStopAtPos(1, 34);
+         break;
+      case 101:
+         return jjMoveStringLiteralDfa2_0(active0, 0xcL);
+      case 105:
+         return jjMoveStringLiteralDfa2_0(active0, 0x2L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(0, active0);
+}
+private int jjMoveStringLiteralDfa2_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(0, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(1, active0);
+      return 2;
+   }
+   switch(curChar)
+   {
+      case 102:
+         if ((active0 & 0x2L) != 0L)
+            return jjStopAtPos(2, 1);
+         break;
+      case 108:
+         return jjMoveStringLiteralDfa3_0(active0, 0x4L);
+      case 110:
+         return jjMoveStringLiteralDfa3_0(active0, 0x8L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(1, active0);
+}
+private int jjMoveStringLiteralDfa3_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(1, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(2, active0);
+      return 3;
+   }
+   switch(curChar)
+   {
+      case 100:
+         if ((active0 & 0x8L) != 0L)
+            return jjStopAtPos(3, 3);
+         break;
+      case 115:
+         return jjMoveStringLiteralDfa4_0(active0, 0x4L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(2, active0);
+}
+private int jjMoveStringLiteralDfa4_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(2, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(3, active0);
+      return 4;
+   }
+   switch(curChar)
+   {
+      case 101:
+         if ((active0 & 0x4L) != 0L)
+            return jjStopAtPos(4, 2);
+         break;
+      default :
+         break;
+   }
+   return jjStartNfa_0(3, active0);
+}
+private int jjStartNfaWithStates_0(int pos, int kind, int state)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) { return pos + 1; }
+   return jjMoveNfa_0(state, pos + 1);
+}
+static final long[] jjbitVec0 = {
+   0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec2 = {
+   0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+private int jjMoveNfa_0(int startState, int curPos)
+{
+   int startsAt = 0;
+   jjnewStateCnt = 50;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 3:
+                  if ((0xffffffe7ffffffffL & l) != 0L)
+                     jjCheckNAddTwoStates(34, 35);
+                  if ((0xffffffe6fffffdffL & l) != 0L)
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAddTwoStates(35, 36);
+                  }
+                  else if ((0x100000200L & l) != 0L)
+                  {
+                     if (kind > 6)
+                        kind = 6;
+                     jjCheckNAdd(18);
+                  }
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddStates(0, 5);
+                  else if ((0x100100000000L & l) != 0L)
+                  {
+                     if (kind > 12)
+                        kind = 12;
+                  }
+                  else if ((0x2400L & l) != 0L)
+                  {
+                     if (kind > 7)
+                        kind = 7;
+                  }
+                  else if (curChar == 46)
+                     jjCheckNAdd(29);
+                  if ((0x3fe000000000000L & l) != 0L)
+                  {
+                     if (kind > 28)
+                        kind = 28;
+                     jjCheckNAddTwoStates(26, 27);
+                  }
+                  else if (curChar == 48)
+                  {
+                     if (kind > 28)
+                        kind = 28;
+                     jjCheckNAddStates(6, 8);
+                  }
+                  else if (curChar == 13)
+                     jjstateSet[jjnewStateCnt++] = 20;
+                  break;
+               case 51:
+                  if ((0xffffffe7ffffffffL & l) != 0L)
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAdd(36);
+                  }
+                  if ((0xffffffe7ffffffffL & l) != 0L)
+                     jjCheckNAddTwoStates(34, 35);
+                  if ((0xffffffe6fffffdffL & l) != 0L)
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAddTwoStates(35, 36);
+                  }
+                  if ((0x3ff000000000000L & l) != 0L)
+                  {
+                     if (kind > 29)
+                        kind = 29;
+                     jjCheckNAddStates(9, 11);
+                  }
+                  break;
+               case 50:
+                  if ((0xffffffe7ffffffffL & l) != 0L)
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAdd(36);
+                  }
+                  if ((0xffffffe7ffffffffL & l) != 0L)
+                     jjCheckNAddTwoStates(34, 35);
+                  if ((0xffffffe6fffffdffL & l) != 0L)
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAddTwoStates(35, 36);
+                  }
+                  break;
+               case 18:
+                  if ((0x100000200L & l) == 0L)
+                     break;
+                  if (kind > 6)
+                     kind = 6;
+                  jjCheckNAdd(18);
+                  break;
+               case 19:
+                  if ((0x2400L & l) != 0L && kind > 7)
+                     kind = 7;
+                  break;
+               case 20:
+                  if (curChar == 10 && kind > 7)
+                     kind = 7;
+                  break;
+               case 21:
+                  if (curChar == 13)
+                     jjstateSet[jjnewStateCnt++] = 20;
+                  break;
+               case 22:
+                  if ((0x100100000000L & l) != 0L && kind > 12)
+                     kind = 12;
+                  break;
+               case 24:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 14)
+                     kind = 14;
+                  jjstateSet[jjnewStateCnt++] = 24;
+                  break;
+               case 25:
+                  if ((0x3fe000000000000L & l) == 0L)
+                     break;
+                  if (kind > 28)
+                     kind = 28;
+                  jjCheckNAddTwoStates(26, 27);
+                  break;
+               case 26:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 28)
+                     kind = 28;
+                  jjCheckNAddTwoStates(26, 27);
+                  break;
+               case 28:
+                  if (curChar == 46)
+                     jjCheckNAdd(29);
+                  break;
+               case 29:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 29)
+                     kind = 29;
+                  jjCheckNAddStates(9, 11);
+                  break;
+               case 31:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(32);
+                  break;
+               case 32:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 29)
+                     kind = 29;
+                  jjCheckNAddTwoStates(32, 33);
+                  break;
+               case 34:
+                  if ((0xffffffe7ffffffffL & l) != 0L)
+                     jjCheckNAddTwoStates(34, 35);
+                  break;
+               case 35:
+                  if ((0xffffffe6fffffdffL & l) == 0L)
+                     break;
+                  if (kind > 36)
+                     kind = 36;
+                  jjCheckNAddTwoStates(35, 36);
+                  break;
+               case 36:
+                  if ((0xffffffe7ffffffffL & l) == 0L)
+                     break;
+                  if (kind > 36)
+                     kind = 36;
+                  jjCheckNAdd(36);
+                  break;
+               case 37:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddStates(0, 5);
+                  break;
+               case 38:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(38, 39);
+                  break;
+               case 39:
+                  if (curChar != 46)
+                     break;
+                  if (kind > 29)
+                     kind = 29;
+                  jjCheckNAddStates(12, 14);
+                  break;
+               case 40:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 29)
+                     kind = 29;
+                  jjCheckNAddStates(12, 14);
+                  break;
+               case 41:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(41, 42);
+                  break;
+               case 43:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(44);
+                  break;
+               case 44:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 29)
+                     kind = 29;
+                  jjCheckNAddTwoStates(44, 33);
+                  break;
+               case 45:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(45, 33);
+                  break;
+               case 46:
+                  if (curChar != 48)
+                     break;
+                  if (kind > 28)
+                     kind = 28;
+                  jjCheckNAddStates(6, 8);
+                  break;
+               case 47:
+                  if ((0xff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 28)
+                     kind = 28;
+                  jjCheckNAddTwoStates(47, 27);
+                  break;
+               case 49:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 28)
+                     kind = 28;
+                  jjCheckNAddTwoStates(49, 27);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 3:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAddTwoStates(35, 36);
+                  }
+                  if ((0xffffffffefffffffL & l) != 0L)
+                     jjCheckNAddTwoStates(34, 35);
+                  if ((0x7fffffe87fffffeL & l) != 0L)
+                  {
+                     if (kind > 14)
+                        kind = 14;
+                     jjCheckNAdd(24);
+                  }
+                  if (curChar == 70)
+                     jjstateSet[jjnewStateCnt++] = 16;
+                  else if (curChar == 102)
+                     jjstateSet[jjnewStateCnt++] = 11;
+                  else if (curChar == 84)
+                     jjstateSet[jjnewStateCnt++] = 6;
+                  else if (curChar == 116)
+                     jjstateSet[jjnewStateCnt++] = 2;
+                  break;
+               case 51:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAdd(36);
+                  }
+                  if ((0xffffffffefffffffL & l) != 0L)
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAddTwoStates(35, 36);
+                  }
+                  if ((0xffffffffefffffffL & l) != 0L)
+                     jjCheckNAddTwoStates(34, 35);
+                  break;
+               case 50:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAdd(36);
+                  }
+                  if ((0xffffffffefffffffL & l) != 0L)
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAddTwoStates(35, 36);
+                  }
+                  if ((0xffffffffefffffffL & l) != 0L)
+                     jjCheckNAddTwoStates(34, 35);
+                  break;
+               case 0:
+                  if (curChar == 101 && kind > 4)
+                     kind = 4;
+                  break;
+               case 1:
+                  if (curChar == 117)
+                     jjstateSet[jjnewStateCnt++] = 0;
+                  break;
+               case 2:
+                  if (curChar == 114)
+                     jjstateSet[jjnewStateCnt++] = 1;
+                  break;
+               case 4:
+                  if (curChar == 69 && kind > 4)
+                     kind = 4;
+                  break;
+               case 5:
+                  if (curChar == 85)
+                     jjstateSet[jjnewStateCnt++] = 4;
+                  break;
+               case 6:
+                  if (curChar == 82)
+                     jjstateSet[jjnewStateCnt++] = 5;
+                  break;
+               case 7:
+                  if (curChar == 84)
+                     jjstateSet[jjnewStateCnt++] = 6;
+                  break;
+               case 8:
+                  if (curChar == 101 && kind > 5)
+                     kind = 5;
+                  break;
+               case 9:
+                  if (curChar == 115)
+                     jjstateSet[jjnewStateCnt++] = 8;
+                  break;
+               case 10:
+                  if (curChar == 108)
+                     jjstateSet[jjnewStateCnt++] = 9;
+                  break;
+               case 11:
+                  if (curChar == 97)
+                     jjstateSet[jjnewStateCnt++] = 10;
+                  break;
+               case 12:
+                  if (curChar == 102)
+                     jjstateSet[jjnewStateCnt++] = 11;
+                  break;
+               case 13:
+                  if (curChar == 69 && kind > 5)
+                     kind = 5;
+                  break;
+               case 14:
+                  if (curChar == 83)
+                     jjstateSet[jjnewStateCnt++] = 13;
+                  break;
+               case 15:
+                  if (curChar == 76)
+                     jjstateSet[jjnewStateCnt++] = 14;
+                  break;
+               case 16:
+                  if (curChar == 65)
+                     jjstateSet[jjnewStateCnt++] = 15;
+                  break;
+               case 17:
+                  if (curChar == 70)
+                     jjstateSet[jjnewStateCnt++] = 16;
+                  break;
+               case 23:
+               case 24:
+                  if ((0x7fffffe87fffffeL & l) == 0L)
+                     break;
+                  if (kind > 14)
+                     kind = 14;
+                  jjCheckNAdd(24);
+                  break;
+               case 27:
+                  if ((0x110000001100L & l) != 0L && kind > 28)
+                     kind = 28;
+                  break;
+               case 30:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(15, 16);
+                  break;
+               case 33:
+                  if ((0x5400000054L & l) != 0L && kind > 29)
+                     kind = 29;
+                  break;
+               case 34:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                     jjCheckNAddTwoStates(34, 35);
+                  break;
+               case 35:
+                  if ((0xffffffffefffffffL & l) == 0L)
+                     break;
+                  if (kind > 36)
+                     kind = 36;
+                  jjCheckNAddTwoStates(35, 36);
+                  break;
+               case 36:
+                  if ((0xffffffffefffffffL & l) == 0L)
+                     break;
+                  if (kind > 36)
+                     kind = 36;
+                  jjCheckNAdd(36);
+                  break;
+               case 42:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(17, 18);
+                  break;
+               case 48:
+                  if ((0x100000001000000L & l) != 0L)
+                     jjCheckNAdd(49);
+                  break;
+               case 49:
+                  if ((0x7e0000007eL & l) == 0L)
+                     break;
+                  if (kind > 28)
+                     kind = 28;
+                  jjCheckNAddTwoStates(49, 27);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = (int)(curChar >> 8);
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 077);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 3:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                     jjCheckNAddTwoStates(34, 35);
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAddTwoStates(35, 36);
+                  }
+                  break;
+               case 51:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                     jjCheckNAddTwoStates(34, 35);
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAddTwoStates(35, 36);
+                  }
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAdd(36);
+                  }
+                  break;
+               case 50:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                     jjCheckNAddTwoStates(34, 35);
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAddTwoStates(35, 36);
+                  }
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                  {
+                     if (kind > 36)
+                        kind = 36;
+                     jjCheckNAdd(36);
+                  }
+                  break;
+               case 34:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                     jjCheckNAddTwoStates(34, 35);
+                  break;
+               case 35:
+                  if (!jjCanMove_0(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 36)
+                     kind = 36;
+                  jjCheckNAddTwoStates(35, 36);
+                  break;
+               case 36:
+                  if (!jjCanMove_0(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 36)
+                     kind = 36;
+                  jjCheckNAdd(36);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 50 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+private final int jjStopStringLiteralDfa_2(int pos, long active0)
+{
+   switch (pos)
+   {
+      default :
+         return -1;
+   }
+}
+private final int jjStartNfa_2(int pos, long active0)
+{
+   return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
+}
+private int jjMoveStringLiteralDfa0_2()
+{
+   switch(curChar)
+   {
+      case 39:
+         return jjStopAtPos(0, 24);
+      default :
+         return jjMoveNfa_2(0, 0);
+   }
+}
+private int jjMoveNfa_2(int startState, int curPos)
+{
+   int startsAt = 0;
+   jjnewStateCnt = 6;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if ((0xffffff7fffffffffL & l) != 0L && kind > 23)
+                     kind = 23;
+                  break;
+               case 1:
+                  if ((0x8400000000L & l) != 0L && kind > 22)
+                     kind = 22;
+                  break;
+               case 2:
+                  if ((0xf000000000000L & l) != 0L)
+                     jjstateSet[jjnewStateCnt++] = 3;
+                  break;
+               case 3:
+                  if ((0xff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 22)
+                     kind = 22;
+                  jjstateSet[jjnewStateCnt++] = 4;
+                  break;
+               case 4:
+                  if ((0xff000000000000L & l) != 0L && kind > 22)
+                     kind = 22;
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                  {
+                     if (kind > 23)
+                        kind = 23;
+                  }
+                  else if (curChar == 92)
+                     jjAddStates(19, 21);
+                  break;
+               case 1:
+                  if ((0x14404510000000L & l) != 0L && kind > 22)
+                     kind = 22;
+                  break;
+               case 5:
+                  if ((0xffffffffefffffffL & l) != 0L && kind > 23)
+                     kind = 23;
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = (int)(curChar >> 8);
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 077);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2) && kind > 23)
+                     kind = 23;
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 6 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+private int jjMoveStringLiteralDfa0_1()
+{
+   return jjMoveNfa_1(0, 0);
+}
+private int jjMoveNfa_1(int startState, int curPos)
+{
+   int startsAt = 0;
+   jjnewStateCnt = 3;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if ((0x2400L & l) != 0L)
+                  {
+                     if (kind > 18)
+                        kind = 18;
+                  }
+                  if (curChar == 13)
+                     jjstateSet[jjnewStateCnt++] = 1;
+                  break;
+               case 1:
+                  if (curChar == 10 && kind > 18)
+                     kind = 18;
+                  break;
+               case 2:
+                  if (curChar == 13)
+                     jjstateSet[jjnewStateCnt++] = 1;
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = (int)(curChar >> 8);
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 077);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+private final int jjStopStringLiteralDfa_3(int pos, long active0)
+{
+   switch (pos)
+   {
+      default :
+         return -1;
+   }
+}
+private final int jjStartNfa_3(int pos, long active0)
+{
+   return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1);
+}
+private int jjMoveStringLiteralDfa0_3()
+{
+   switch(curChar)
+   {
+      case 34:
+         return jjStopAtPos(0, 27);
+      default :
+         return jjMoveNfa_3(0, 0);
+   }
+}
+private int jjMoveNfa_3(int startState, int curPos)
+{
+   int startsAt = 0;
+   jjnewStateCnt = 6;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if ((0xfffffffbffffffffL & l) != 0L && kind > 26)
+                     kind = 26;
+                  break;
+               case 1:
+                  if ((0x8400000000L & l) != 0L && kind > 25)
+                     kind = 25;
+                  break;
+               case 2:
+                  if ((0xf000000000000L & l) != 0L)
+                     jjstateSet[jjnewStateCnt++] = 3;
+                  break;
+               case 3:
+                  if ((0xff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 25)
+                     kind = 25;
+                  jjstateSet[jjnewStateCnt++] = 4;
+                  break;
+               case 4:
+                  if ((0xff000000000000L & l) != 0L && kind > 25)
+                     kind = 25;
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                  {
+                     if (kind > 26)
+                        kind = 26;
+                  }
+                  else if (curChar == 92)
+                     jjAddStates(19, 21);
+                  break;
+               case 1:
+                  if ((0x14404510000000L & l) != 0L && kind > 25)
+                     kind = 25;
+                  break;
+               case 5:
+                  if ((0xffffffffefffffffL & l) != 0L && kind > 26)
+                     kind = 26;
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = (int)(curChar >> 8);
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 077);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2) && kind > 26)
+                     kind = 26;
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 6 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+static final int[] jjnextStates = {
+   38, 39, 41, 42, 45, 33, 47, 48, 27, 29, 30, 33, 40, 30, 33, 31, 
+   32, 43, 44, 1, 2, 3, 
+};
+private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
+{
+   switch(hiByte)
+   {
+      case 0:
+         return ((jjbitVec2[i2] & l2) != 0L);
+      default :
+         if ((jjbitVec0[i1] & l1) != 0L)
+            return true;
+         return false;
+   }
+}
+
+/** Token literal values. */
+public static final String[] jjstrLiteralImages = {
+"", "\43\151\146", "\43\145\154\163\145", "\43\145\156\144", null, null, null, 
+null, "\43", "\44", "\50", "\51", null, "\56", null, null, null, "\43\43", null, 
+null, null, null, null, null, null, null, null, null, null, null, null, null, null, 
+null, "\134\134", "\134", null, };
+
+/** Lexer state names. */
+public static final String[] lexStateNames = {
+   "DEFAULT",
+   "IN_SINGLE_LINE_COMMENT",
+   "WithinSingleQuoteLiteral",
+   "WithinDoubleQuoteLiteral",
+};
+
+/** Lex State array. */
+public static final int[] jjnewLexState = {
+   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 0, -1, 2, 3, -1, -1, 0, 
+   -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+};
+static final long[] jjtoToken = {
+   0x1c39067fffL, 
+};
+static final long[] jjtoSkip = {
+   0x80000L, 
+};
+static final long[] jjtoMore = {
+   0x6f00000L, 
+};
+protected JavaCharStream input_stream;
+private final int[] jjrounds = new int[50];
+private final int[] jjstateSet = new int[100];
+private final StringBuilder jjimage = new StringBuilder();
+private StringBuilder image = jjimage;
+private int jjimageLen;
+private int lengthOfMatch;
+protected char curChar;
+/** Constructor. */
+public SQLTemplateParserTokenManager(JavaCharStream stream){
+   if (JavaCharStream.staticFlag)
+      throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+   input_stream = stream;
+}
+
+/** Constructor. */
+public SQLTemplateParserTokenManager(JavaCharStream stream, int lexState){
+   this(stream);
+   SwitchTo(lexState);
+}
+
+/** Reinitialise parser. */
+public void ReInit(JavaCharStream stream)
+{
+   jjmatchedPos = jjnewStateCnt = 0;
+   curLexState = defaultLexState;
+   input_stream = stream;
+   ReInitRounds();
+}
+private void ReInitRounds()
+{
+   int i;
+   jjround = 0x80000001;
+   for (i = 50; i-- > 0;)
+      jjrounds[i] = 0x80000000;
+}
+
+/** Reinitialise parser. */
+public void ReInit(JavaCharStream stream, int lexState)
+{
+   ReInit(stream);
+   SwitchTo(lexState);
+}
+
+/** Switch to specified lex state. */
+public void SwitchTo(int lexState)
+{
+   if (lexState >= 4 || lexState < 0)
+      throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+   else
+      curLexState = lexState;
+}
+
+protected Token jjFillToken()
+{
+   final Token t;
+   final String curTokenImage;
+   final int beginLine;
+   final int endLine;
+   final int beginColumn;
+   final int endColumn;
+   String im = jjstrLiteralImages[jjmatchedKind];
+   curTokenImage = (im == null) ? input_stream.GetImage() : im;
+   beginLine = input_stream.getBeginLine();
+   beginColumn = input_stream.getBeginColumn();
+   endLine = input_stream.getEndLine();
+   endColumn = input_stream.getEndColumn();
+   t = Token.newToken(jjmatchedKind, curTokenImage);
+
+   t.beginLine = beginLine;
+   t.endLine = endLine;
+   t.beginColumn = beginColumn;
+   t.endColumn = endColumn;
+
+   return t;
+}
+
+int curLexState = 0;
+int defaultLexState = 0;
+int jjnewStateCnt;
+int jjround;
+int jjmatchedPos;
+int jjmatchedKind;
+
+/** Get the next Token. */
+public Token getNextToken() 
+{
+  Token matchedToken;
+  int curPos = 0;
+
+  EOFLoop :
+  for (;;)
+  {
+   try
+   {
+      curChar = input_stream.BeginToken();
+   }
+   catch(java.io.IOException e)
+   {
+      jjmatchedKind = 0;
+      matchedToken = jjFillToken();
+      return matchedToken;
+   }
+   image = jjimage;
+   image.setLength(0);
+   jjimageLen = 0;
+
+   for (;;)
+   {
+     switch(curLexState)
+     {
+       case 0:
+         jjmatchedKind = 0x7fffffff;
+         jjmatchedPos = 0;
+         curPos = jjMoveStringLiteralDfa0_0();
+         break;
+       case 1:
+         jjmatchedKind = 0x7fffffff;
+         jjmatchedPos = 0;
+         curPos = jjMoveStringLiteralDfa0_1();
+         if (jjmatchedPos == 0 && jjmatchedKind > 19)
+         {
+            jjmatchedKind = 19;
+         }
+         break;
+       case 2:
+         jjmatchedKind = 0x7fffffff;
+         jjmatchedPos = 0;
+         curPos = jjMoveStringLiteralDfa0_2();
+         break;
+       case 3:
+         jjmatchedKind = 0x7fffffff;
+         jjmatchedPos = 0;
+         curPos = jjMoveStringLiteralDfa0_3();
+         break;
+     }
+     if (jjmatchedKind != 0x7fffffff)
+     {
+        if (jjmatchedPos + 1 < curPos)
+           input_stream.backup(curPos - jjmatchedPos - 1);
+        if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+        {
+           matchedToken = jjFillToken();
+           TokenLexicalActions(matchedToken);
+       if (jjnewLexState[jjmatchedKind] != -1)
+         curLexState = jjnewLexState[jjmatchedKind];
+           return matchedToken;
+        }
+        else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+        {
+         if (jjnewLexState[jjmatchedKind] != -1)
+           curLexState = jjnewLexState[jjmatchedKind];
+           continue EOFLoop;
+        }
+        MoreLexicalActions();
+      if (jjnewLexState[jjmatchedKind] != -1)
+        curLexState = jjnewLexState[jjmatchedKind];
+        curPos = 0;
+        jjmatchedKind = 0x7fffffff;
+        try {
+           curChar = input_stream.readChar();
+           continue;
+        }
+        catch (java.io.IOException e1) { }
+     }
+     int error_line = input_stream.getEndLine();
+     int error_column = input_stream.getEndColumn();
+     String error_after = null;
+     boolean EOFSeen = false;
+     try { input_stream.readChar(); input_stream.backup(1); }
+     catch (java.io.IOException e1) {
+        EOFSeen = true;
+        error_after = curPos <= 1 ? "" : input_stream.GetImage();
+        if (curChar == '\n' || curChar == '\r') {
+           error_line++;
+           error_column = 0;
+        }
+        else
+           error_column++;
+     }
+     if (!EOFSeen) {
+        input_stream.backup(1);
+        error_after = curPos <= 1 ? "" : input_stream.GetImage();
+     }
+     throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
+   }
+  }
+}
+
+void MoreLexicalActions()
+{
+   jjimageLen += (lengthOfMatch = jjmatchedPos + 1);
+   switch(jjmatchedKind)
+   {
+      case 20 :
+         image.append(input_stream.GetSuffix(jjimageLen));
+         jjimageLen = 0;
+           stringBuffer = new StringBuffer();
+         break;
+      case 21 :
+         image.append(input_stream.GetSuffix(jjimageLen));
+         jjimageLen = 0;
+            stringBuffer = new StringBuffer();
+         break;
+      case 22 :
+         image.append(input_stream.GetSuffix(jjimageLen));
+         jjimageLen = 0;
+          stringBuffer.append( escapeChar() );
+         break;
+      case 23 :
+         image.append(input_stream.GetSuffix(jjimageLen));
+         jjimageLen = 0;
+          stringBuffer.append( image.charAt(image.length()-1) );
+         break;
+      case 25 :
+         image.append(input_stream.GetSuffix(jjimageLen));
+         jjimageLen = 0;
+          stringBuffer.append( escapeChar() );
+         break;
+      case 26 :
+         image.append(input_stream.GetSuffix(jjimageLen));
+         jjimageLen = 0;
+          stringBuffer.append( image.charAt(image.length()-1) );
+         break;
+      default :
+         break;
+   }
+}
+void TokenLexicalActions(Token matchedToken)
+{
+   switch(jjmatchedKind)
+   {
+      case 24 :
+        image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
+          literalValue = stringBuffer.toString();
+         break;
+      case 27 :
+        image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
+          literalValue = stringBuffer.toString();
+         break;
+      case 28 :
+        image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
+      literalValue = makeInt();
+         break;
+      case 29 :
+        image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
+      literalValue = makeFloat();
+         break;
+      default :
+         break;
+   }
+}
+private void jjCheckNAdd(int state)
+{
+   if (jjrounds[state] != jjround)
+   {
+      jjstateSet[jjnewStateCnt++] = state;
+      jjrounds[state] = jjround;
+   }
+}
+private void jjAddStates(int start, int end)
+{
+   do {
+      jjstateSet[jjnewStateCnt++] = jjnextStates[start];
+   } while (start++ != end);
+}
+private void jjCheckNAddTwoStates(int state1, int state2)
+{
+   jjCheckNAdd(state1);
+   jjCheckNAdd(state2);
+}
+
+private void jjCheckNAddStates(int start, int end)
+{
+   do {
+      jjCheckNAdd(jjnextStates[start]);
+   } while (start++ != end);
+}
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/55e3c975/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTreeConstants.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTreeConstants.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTreeConstants.java
new file mode 100644
index 0000000..f48762a
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SQLTemplateParserTreeConstants.java
@@ -0,0 +1,35 @@
+/* Generated By:JavaCC: Do not edit this line. SQLTemplateParserTreeConstants.java Version 5.0 */
+package org.apache.cayenne.template.parser;
+
+public interface SQLTemplateParserTreeConstants
+{
+  public int JJTVOID = 0;
+  public int JJTBLOCK = 1;
+  public int JJTTEXT = 2;
+  public int JJTIFELSE = 3;
+  public int JJTDIRECTIVE = 4;
+  public int JJTEXPRESSION = 5;
+  public int JJTSTRINGSCALAR = 6;
+  public int JJTINTSCALAR = 7;
+  public int JJTFLOATSCALAR = 8;
+  public int JJTBOOLSCALAR = 9;
+  public int JJTVARIABLE = 10;
+  public int JJTMETHOD = 11;
+
+
+  public String[] jjtNodeName = {
+    "void",
+    "Block",
+    "Text",
+    "IfElse",
+    "Directive",
+    "Expression",
+    "StringScalar",
+    "IntScalar",
+    "FloatScalar",
+    "BoolScalar",
+    "Variable",
+    "Method",
+  };
+}
+/* JavaCC - OriginalChecksum=7c5329fded1e29c67b674bf81b4db143 (do not edit this line) */

http://git-wip-us.apache.org/repos/asf/cayenne/blob/55e3c975/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ScalarNode.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ScalarNode.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ScalarNode.java
new file mode 100644
index 0000000..79457a3
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ScalarNode.java
@@ -0,0 +1,65 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.template.parser;
+
+import org.apache.cayenne.template.Context;
+
+/**
+ * @since 4.1
+ */
+public class ScalarNode<V> extends SimpleNode implements ExpressionNode {
+
+    V value;
+
+    public ScalarNode(int i) {
+        super(i);
+    }
+
+    public void setValue(V value) {
+        this.value = value;
+    }
+
+    public V getValue() {
+        return value;
+    }
+
+    @Override
+    public String evaluate(Context context) {
+        if(value == null) {
+            return "";
+        }
+        return value.toString();
+    }
+
+    @Override
+    public long evaluateAsLong(Context context) {
+        throw new UnsupportedOperationException("Can't convert " + value + " value to long");
+    }
+
+    @Override
+    public double evaluateAsDouble(Context context) {
+        throw new UnsupportedOperationException("Can't convert " + value + " value to double");
+    }
+
+    @Override
+    public boolean evaluateAsBoolean(Context context) {
+        throw new UnsupportedOperationException("Can't convert " + value + " value to boolean");
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/55e3c975/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SimpleNode.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SimpleNode.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SimpleNode.java
new file mode 100644
index 0000000..df4fc8a
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/SimpleNode.java
@@ -0,0 +1,90 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.template.parser;
+
+/**
+ * @since 4.1
+ */
+public abstract class SimpleNode implements Node {
+
+    protected Node parent;
+    protected Node[] children;
+    protected int id;
+
+    public SimpleNode(int i) {
+        id = i;
+    }
+
+    public void jjtOpen() {
+    }
+
+    public void jjtClose() {
+    }
+
+    public void jjtSetParent(Node n) {
+        parent = n;
+    }
+
+    public Node jjtGetParent() {
+        return parent;
+    }
+
+    public void jjtAddChild(Node n, int i) {
+        if (children == null) {
+            children = new Node[i + 1];
+        } else if (i >= children.length) {
+            Node c[] = new Node[i + 1];
+            System.arraycopy(children, 0, c, 0, children.length);
+            children = c;
+        }
+        children[i] = n;
+    }
+
+    public Node jjtGetChild(int i) {
+        return children[i];
+    }
+
+    public int jjtGetNumChildren() {
+        return (children == null) ? 0 : children.length;
+    }
+
+    public String toString() {
+        return SQLTemplateParserTreeConstants.jjtNodeName[id];
+    }
+
+    public String toString(String prefix) {
+        return prefix + toString();
+    }
+
+    /**
+     * Override this method if you want to customize how the node dumps out its children.
+     */
+    public void dump(String prefix) {
+        System.out.println(toString(prefix));
+        if (children != null) {
+            for (Node aChildren : children) {
+                SimpleNode n = (SimpleNode) aChildren;
+                if (n != null) {
+                    n.dump(prefix + " ");
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/55e3c975/cayenne-server/src/main/java/org/apache/cayenne/template/parser/Token.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/Token.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/Token.java
new file mode 100644
index 0000000..fe53fe9
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/Token.java
@@ -0,0 +1,150 @@
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */
+/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.template.parser;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token implements java.io.Serializable {
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * An integer that describes the kind of this token.  This numbering
+   * system is determined by JavaCCParser, and a table of these numbers is
+   * stored in the file ...Constants.java.
+   */
+  public int kind;
+
+  /** The line number of the first character of this Token. */
+  public int beginLine;
+  /** The column number of the first character of this Token. */
+  public int beginColumn;
+  /** The line number of the last character of this Token. */
+  public int endLine;
+  /** The column number of the last character of this Token. */
+  public int endColumn;
+
+  /**
+   * The string image of the token.
+   */
+  public String image;
+
+  /**
+   * A reference to the next regular (non-special) token from the input
+   * stream.  If this is the last token from the input stream, or if the
+   * token manager has not read tokens beyond this one, this field is
+   * set to null.  This is true only if this token is also a regular
+   * token.  Otherwise, see below for a description of the contents of
+   * this field.
+   */
+  public Token next;
+
+  /**
+   * This field is used to access special tokens that occur prior to this
+   * token, but after the immediately preceding regular (non-special) token.
+   * If there are no such special tokens, this field is set to null.
+   * When there are more than one such special token, this field refers
+   * to the last of these special tokens, which in turn refers to the next
+   * previous special token through its specialToken field, and so on
+   * until the first special token (whose specialToken field is null).
+   * The next fields of special tokens refer to other special tokens that
+   * immediately follow it (without an intervening regular token).  If there
+   * is no such token, this field is null.
+   */
+  public Token specialToken;
+
+  /**
+   * An optional attribute value of the Token.
+   * Tokens which are not used as syntactic sugar will often contain
+   * meaningful values that will be used later on by the compiler or
+   * interpreter. This attribute value is often different from the image.
+   * Any subclass of Token that actually wants to return a non-null value can
+   * override this method as appropriate.
+   */
+  public Object getValue() {
+    return null;
+  }
+
+  /**
+   * No-argument constructor
+   */
+  public Token() {}
+
+  /**
+   * Constructs a new token for the specified Image.
+   */
+  public Token(int kind)
+  {
+    this(kind, null);
+  }
+
+  /**
+   * Constructs a new token for the specified Image and Kind.
+   */
+  public Token(int kind, String image)
+  {
+    this.kind = kind;
+    this.image = image;
+  }
+
+  /**
+   * Returns the image.
+   */
+  public String toString()
+  {
+    return image;
+  }
+
+  /**
+   * Returns a new Token object, by default. However, if you want, you
+   * can create and return subclass objects based on the value of ofKind.
+   * Simply add the cases to the switch for all those special cases.
+   * For example, if you have a subclass of Token called IDToken that
+   * you want to create if ofKind is ID, simply add something like :
+   *
+   *    case MyParserConstants.ID : return new IDToken(ofKind, image);
+   *
+   * to the following switch statement. Then you can cast matchedToken
+   * variable to the appropriate type and use sit in your lexical actions.
+   */
+  public static Token newToken(int ofKind, String image)
+  {
+    switch(ofKind)
+    {
+      default : return new Token(ofKind, image);
+    }
+  }
+
+  public static Token newToken(int ofKind)
+  {
+    return newToken(ofKind, null);
+  }
+
+}
+/* JavaCC - OriginalChecksum=4a50f271eb81ec98d46be4c7c6402564 (do not edit this line) */

http://git-wip-us.apache.org/repos/asf/cayenne/blob/55e3c975/cayenne-server/src/main/java/org/apache/cayenne/template/parser/TokenMgrError.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/TokenMgrError.java b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/TokenMgrError.java
new file mode 100644
index 0000000..573fa18
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/TokenMgrError.java
@@ -0,0 +1,166 @@
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */
+/* JavaCCOptions: */
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.template.parser;
+
+/** Token Manager Error. */
+public class TokenMgrError extends Error
+{
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /*
+   * Ordinals for various reasons why an Error of this type can be thrown.
+   */
+
+  /**
+   * Lexical error occurred.
+   */
+  static final int LEXICAL_ERROR = 0;
+
+  /**
+   * An attempt was made to create a second instance of a static token manager.
+   */
+  static final int STATIC_LEXER_ERROR = 1;
+
+  /**
+   * Tried to change to an invalid lexical state.
+   */
+  static final int INVALID_LEXICAL_STATE = 2;
+
+  /**
+   * Detected (and bailed out of) an infinite loop in the token manager.
+   */
+  static final int LOOP_DETECTED = 3;
+
+  /**
+   * Indicates the reason why the exception is thrown. It will have
+   * one of the above 4 values.
+   */
+  int errorCode;
+
+  /**
+   * Replaces unprintable characters by their escaped (or unicode escaped)
+   * equivalents in the given string
+   */
+  protected static final String addEscapes(String str) {
+    StringBuffer retval = new StringBuffer();
+    char ch;
+    for (int i = 0; i < str.length(); i++) {
+      switch (str.charAt(i))
+      {
+        case 0 :
+          continue;
+        case '\b':
+          retval.append("\\b");
+          continue;
+        case '\t':
+          retval.append("\\t");
+          continue;
+        case '\n':
+          retval.append("\\n");
+          continue;
+        case '\f':
+          retval.append("\\f");
+          continue;
+        case '\r':
+          retval.append("\\r");
+          continue;
+        case '\"':
+          retval.append("\\\"");
+          continue;
+        case '\'':
+          retval.append("\\\'");
+          continue;
+        case '\\':
+          retval.append("\\\\");
+          continue;
+        default:
+          if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+            String s = "0000" + Integer.toString(ch, 16);
+            retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+          } else {
+            retval.append(ch);
+          }
+          continue;
+      }
+    }
+    return retval.toString();
+  }
+
+  /**
+   * Returns a detailed message for the Error when it is thrown by the
+   * token manager to indicate a lexical error.
+   * Parameters :
+   *    EOFSeen     : indicates if EOF caused the lexical error
+   *    curLexState : lexical state in which this error occurred
+   *    errorLine   : line number when the error occurred
+   *    errorColumn : column number when the error occurred
+   *    errorAfter  : prefix that was seen before this error occurred
+   *    curchar     : the offending character
+   * Note: You can customize the lexical error message by modifying this method.
+   */
+  protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
+    return("Lexical error at line " +
+          errorLine + ", column " +
+          errorColumn + ".  Encountered: " +
+          (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+          "after : \"" + addEscapes(errorAfter) + "\"");
+  }
+
+  /**
+   * You can also modify the body of this method to customize your error messages.
+   * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+   * of end-users concern, so you can return something like :
+   *
+   *     "Internal Error : Please file a bug report .... "
+   *
+   * from this method for such cases in the release version of your parser.
+   */
+  public String getMessage() {
+    return super.getMessage();
+  }
+
+  /*
+   * Constructors of various flavors follow.
+   */
+
+  /** No arg constructor. */
+  public TokenMgrError() {
+  }
+
+  /** Constructor with message and reason. */
+  public TokenMgrError(String message, int reason) {
+    super(message);
+    errorCode = reason;
+  }
+
+  /** Full Constructor. */
+  public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
+    this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+  }
+}
+/* JavaCC - OriginalChecksum=1cf443bf553d015a7d546cad69ee7aaa (do not edit this line) */