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/01/19 11:33:11 UTC

[1/3] cayenne git commit: CAY-2196 Support for new function expressions in expression parser - updated and refactored grammar for parser - add token id to AST* function call nodes - escape in parse exception message - tests

Repository: cayenne
Updated Branches:
  refs/heads/master 666c96de1 -> c44ccfde3


http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JavaCharStream.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JavaCharStream.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JavaCharStream.java
index 7394b28..4065980 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JavaCharStream.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JavaCharStream.java
@@ -29,8 +29,7 @@ import java.io.IOException;
  * contain only ASCII characters (with java-like unicode escape processing).
  */
 
-public class JavaCharStream
-{
+public class JavaCharStream {
 
     // optimizing internal Exception by reusing the exception per CAY-1667. This exception
     // never reaches the end user, so we can suppress stack trace creation and make it
@@ -40,547 +39,603 @@ public class JavaCharStream
         @Override
         public synchronized Throwable fillInStackTrace() {
             return this;
-        };
+        }
     };
-    
-/** Whether parser is static. */
-  public static final boolean staticFlag = false;
-  static final int hexval(char c) throws java.io.IOException {
-    switch(c)
-    {
-       case '0' :
-          return 0;
-       case '1' :
-          return 1;
-       case '2' :
-          return 2;
-       case '3' :
-          return 3;
-       case '4' :
-          return 4;
-       case '5' :
-          return 5;
-       case '6' :
-          return 6;
-       case '7' :
-          return 7;
-       case '8' :
-          return 8;
-       case '9' :
-          return 9;
-
-       case 'a' :
-       case 'A' :
-          return 10;
-       case 'b' :
-       case 'B' :
-          return 11;
-       case 'c' :
-       case 'C' :
-          return 12;
-       case 'd' :
-       case 'D' :
-          return 13;
-       case 'e' :
-       case 'E' :
-          return 14;
-       case 'f' :
-       case 'F' :
-          return 15;
-    }
-
-    throw new java.io.IOException(); // Should never come here
-  }
-
-/** Position in buffer. */
-  public int bufpos = -1;
-  int bufsize;
-  int available;
-  int tokenBegin;
-  protected int bufline[];
-  protected int bufcolumn[];
-
-  protected int column = 0;
-  protected int line = 1;
-
-  protected boolean prevCharIsCR = false;
-  protected boolean prevCharIsLF = false;
-
-  protected java.io.Reader inputStream;
-
-  protected char[] nextCharBuf;
-  protected char[] buffer;
-  protected int maxNextCharInd = 0;
-  protected int nextCharInd = -1;
-  protected int inBuf = 0;
-  protected int tabSize = 8;
-  private boolean closed;
-
-  protected void setTabSize(int i) { tabSize = i; }
-  protected int getTabSize(int i) { return tabSize; }
-
-  protected void ExpandBuff(boolean wrapAround)
-  {
-     char[] newbuffer = new char[bufsize + 2048];
-     int newbufline[] = new int[bufsize + 2048];
-     int newbufcolumn[] = new int[bufsize + 2048];
-
-     try
-     {
-        if (wrapAround)
-        {
-           System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
-           System.arraycopy(buffer, 0, newbuffer,
-                                             bufsize - tokenBegin, bufpos);
-           buffer = newbuffer;
-
-           System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
-           System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
-           bufline = newbufline;
-
-           System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
-           System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
-           bufcolumn = newbufcolumn;
-
-           bufpos += (bufsize - tokenBegin);
+
+    /**
+     * Whether parser is static.
+     */
+    public static final boolean staticFlag = false;
+
+    static final int hexval(char c) throws java.io.IOException {
+        switch (c) {
+            case '0':
+                return 0;
+            case '1':
+                return 1;
+            case '2':
+                return 2;
+            case '3':
+                return 3;
+            case '4':
+                return 4;
+            case '5':
+                return 5;
+            case '6':
+                return 6;
+            case '7':
+                return 7;
+            case '8':
+                return 8;
+            case '9':
+                return 9;
+
+            case 'a':
+            case 'A':
+                return 10;
+            case 'b':
+            case 'B':
+                return 11;
+            case 'c':
+            case 'C':
+                return 12;
+            case 'd':
+            case 'D':
+                return 13;
+            case 'e':
+            case 'E':
+                return 14;
+            case 'f':
+            case 'F':
+                return 15;
         }
-        else
-        {
-           System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
-           buffer = newbuffer;
 
-           System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
-           bufline = newbufline;
+        throw new java.io.IOException(); // Should never come here
+    }
+
+    /**
+     * Position in buffer.
+     */
+    public int bufpos = -1;
+    int bufsize;
+    int available;
+    int tokenBegin;
+    protected int bufline[];
+    protected int bufcolumn[];
+
+    protected int column = 0;
+    protected int line = 1;
+
+    protected boolean prevCharIsCR = false;
+    protected boolean prevCharIsLF = false;
+
+    protected java.io.Reader inputStream;
+
+    protected char[] nextCharBuf;
+    protected char[] buffer;
+    protected int maxNextCharInd = 0;
+    protected int nextCharInd = -1;
+    protected int inBuf = 0;
+    protected int tabSize = 8;
+    private boolean closed;
+
+    protected void setTabSize(int i) {
+        tabSize = i;
+    }
+
+    protected int getTabSize(int i) {
+        return tabSize;
+    }
+
+    protected void ExpandBuff(boolean wrapAround) {
+        char[] newbuffer = new char[bufsize + 2048];
+        int newbufline[] = new int[bufsize + 2048];
+        int newbufcolumn[] = new int[bufsize + 2048];
+
+        try {
+            if (wrapAround) {
+                System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+                System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
+                buffer = newbuffer;
+
+                System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+                System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+                bufline = newbufline;
+
+                System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+                System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+                bufcolumn = newbufcolumn;
+
+                bufpos += (bufsize - tokenBegin);
+            } else {
+                System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+                buffer = newbuffer;
 
-           System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
-           bufcolumn = newbufcolumn;
+                System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+                bufline = newbufline;
 
-           bufpos -= tokenBegin;
+                System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+                bufcolumn = newbufcolumn;
+
+                bufpos -= tokenBegin;
+            }
+        } catch (Throwable t) {
+            throw new Error(t.getMessage());
         }
-     }
-     catch (Throwable t)
-     {
-        throw new Error(t.getMessage());
-     }
-
-     available = (bufsize += 2048);
-     tokenBegin = 0;
-  }
-
-  protected void FillBuff() throws java.io.IOException
-  {
-     int i;
-     if (maxNextCharInd == nextCharBuf.length)
-        maxNextCharInd = nextCharInd = 0;
-
-     try {
-        // check for closed status to prevent the underlying Reader from 
-        // throwing IOException that causes performance degradation
-        if (closed || (i = inputStream.read(nextCharBuf, maxNextCharInd,
-                nextCharBuf.length - maxNextCharInd)) == -1)
-        {
-           inputStream.close();
-           closed = true;
-           throw END_OF_STREAM_EXCEPTION;
+
+        available = (bufsize += 2048);
+        tokenBegin = 0;
+    }
+
+    protected void FillBuff() throws java.io.IOException {
+        int i;
+        if (maxNextCharInd == nextCharBuf.length)
+            maxNextCharInd = nextCharInd = 0;
+
+        try {
+            // check for closed status to prevent the underlying Reader from
+            // throwing IOException that causes performance degradation
+            if (closed || (i = inputStream.read(nextCharBuf, maxNextCharInd,
+                    nextCharBuf.length - maxNextCharInd)) == -1) {
+                inputStream.close();
+                closed = true;
+                throw END_OF_STREAM_EXCEPTION;
+            } else
+                maxNextCharInd += i;
+            return;
+        } catch (java.io.IOException e) {
+            if (bufpos != 0) {
+                --bufpos;
+                backup(0);
+            } else {
+                bufline[bufpos] = line;
+                bufcolumn[bufpos] = column;
+            }
+            throw e;
         }
-        else
-           maxNextCharInd += i;
-        return;
-     }
-     catch(java.io.IOException e) {
-        if (bufpos != 0)
-        {
-           --bufpos;
-           backup(0);
+    }
+
+    protected char ReadByte() throws java.io.IOException {
+        if (++nextCharInd >= maxNextCharInd)
+            FillBuff();
+
+        return nextCharBuf[nextCharInd];
+    }
+
+    /**
+     * @return starting character for token.
+     */
+    public char BeginToken() throws java.io.IOException {
+        if (inBuf > 0) {
+            --inBuf;
+
+            if (++bufpos == bufsize)
+                bufpos = 0;
+
+            tokenBegin = bufpos;
+            return buffer[bufpos];
         }
+
+        tokenBegin = 0;
+        bufpos = -1;
+
+        return readChar();
+    }
+
+    protected void AdjustBuffSize() {
+        if (available == bufsize) {
+            if (tokenBegin > 2048) {
+                bufpos = 0;
+                available = tokenBegin;
+            } else
+                ExpandBuff(false);
+        } else if (available > tokenBegin)
+            available = bufsize;
+        else if ((tokenBegin - available) < 2048)
+            ExpandBuff(true);
         else
-        {
-           bufline[bufpos] = line;
-           bufcolumn[bufpos] = column;
+            available = tokenBegin;
+    }
+
+    protected void UpdateLineColumn(char c) {
+        column++;
+
+        if (prevCharIsLF) {
+            prevCharIsLF = false;
+            line += (column = 1);
+        } else if (prevCharIsCR) {
+            prevCharIsCR = false;
+            if (c == '\n') {
+                prevCharIsLF = true;
+            } else
+                line += (column = 1);
         }
-        throw e;
-     }
-  }
-
-  protected char ReadByte() throws java.io.IOException
-  {
-     if (++nextCharInd >= maxNextCharInd)
-        FillBuff();
-
-     return nextCharBuf[nextCharInd];
-  }
-
-/** @return starting character for token. */
-  public char BeginToken() throws java.io.IOException
-  {
-     if (inBuf > 0)
-     {
-        --inBuf;
-
-        if (++bufpos == bufsize)
-           bufpos = 0;
-
-        tokenBegin = bufpos;
-        return buffer[bufpos];
-     }
-
-     tokenBegin = 0;
-     bufpos = -1;
-
-     return readChar();
-  }
-
-  protected void AdjustBuffSize()
-  {
-     if (available == bufsize)
-     {
-        if (tokenBegin > 2048)
-        {
-           bufpos = 0;
-           available = tokenBegin;
+
+        switch (c) {
+            case '\r':
+                prevCharIsCR = true;
+                break;
+            case '\n':
+                prevCharIsLF = true;
+                break;
+            case '\t':
+                column--;
+                column += (tabSize - (column % tabSize));
+                break;
+            default:
+                break;
         }
-        else
-           ExpandBuff(false);
-     }
-     else if (available > tokenBegin)
-        available = bufsize;
-     else if ((tokenBegin - available) < 2048)
-        ExpandBuff(true);
-     else
-        available = tokenBegin;
-  }
-
-  protected void UpdateLineColumn(char c)
-  {
-     column++;
-
-     if (prevCharIsLF)
-     {
-        prevCharIsLF = false;
-        line += (column = 1);
-     }
-     else if (prevCharIsCR)
-     {
-        prevCharIsCR = false;
-        if (c == '\n')
-        {
-           prevCharIsLF = true;
+
+        bufline[bufpos] = line;
+        bufcolumn[bufpos] = column;
+    }
+
+    /**
+     * Read a character.
+     */
+    public char readChar() throws java.io.IOException {
+        if (inBuf > 0) {
+            --inBuf;
+
+            if (++bufpos == bufsize)
+                bufpos = 0;
+
+            return buffer[bufpos];
         }
-        else
-           line += (column = 1);
-     }
-
-     switch (c)
-     {
-        case '\r' :
-           prevCharIsCR = true;
-           break;
-        case '\n' :
-           prevCharIsLF = true;
-           break;
-        case '\t' :
-           column--;
-           column += (tabSize - (column % tabSize));
-           break;
-        default :
-           break;
-     }
-
-     bufline[bufpos] = line;
-     bufcolumn[bufpos] = column;
-  }
-
-/** Read a character. */
-  public char readChar() throws java.io.IOException
-  {
-     if (inBuf > 0)
-     {
-        --inBuf;
-
-        if (++bufpos == bufsize)
-           bufpos = 0;
-
-        return buffer[bufpos];
-     }
-
-     char c;
-
-     if (++bufpos == available)
-        AdjustBuffSize();
-
-     if ((buffer[bufpos] = c = ReadByte()) == '\\')
-     {
-        UpdateLineColumn(c);
-
-        int backSlashCnt = 1;
-
-        for (;;) // Read all the backslashes
-        {
-           if (++bufpos == available)
-              AdjustBuffSize();
-
-           try
-           {
-              if ((buffer[bufpos] = c = ReadByte()) != '\\')
-              {
-                 UpdateLineColumn(c);
-                 // found a non-backslash char.
-                 if ((c == 'u') && ((backSlashCnt & 1) == 1))
-                 {
-                    if (--bufpos < 0)
-                       bufpos = bufsize - 1;
-
-                    break;
-                 }
-
-                 backup(backSlashCnt);
-                 return '\\';
-              }
-           }
-           catch(java.io.IOException e)
-           {
-              if (backSlashCnt > 1)
-                 backup(backSlashCnt-1);
-
-              return '\\';
-           }
-
-           UpdateLineColumn(c);
-           backSlashCnt++;
+
+        char c;
+
+        if (++bufpos == available)
+            AdjustBuffSize();
+
+        if ((buffer[bufpos] = c = ReadByte()) == '\\') {
+            UpdateLineColumn(c);
+
+            int backSlashCnt = 1;
+
+            for (; ; ) // Read all the backslashes
+            {
+                if (++bufpos == available)
+                    AdjustBuffSize();
+
+                try {
+                    if ((buffer[bufpos] = c = ReadByte()) != '\\') {
+                        UpdateLineColumn(c);
+                        // found a non-backslash char.
+                        if ((c == 'u') && ((backSlashCnt & 1) == 1)) {
+                            if (--bufpos < 0)
+                                bufpos = bufsize - 1;
+
+                            break;
+                        }
+
+                        backup(backSlashCnt);
+                        return '\\';
+                    }
+                } catch (java.io.IOException e) {
+                    // We are returning one backslash so we should only backup (count-1)
+                    if (backSlashCnt > 1)
+                        backup(backSlashCnt - 1);
+
+                    return '\\';
+                }
+
+                UpdateLineColumn(c);
+                backSlashCnt++;
+            }
+
+            // Here, we have seen an odd number of backslash's followed by a 'u'
+            try {
+                while ((c = ReadByte()) == 'u')
+                    ++column;
+
+                buffer[bufpos] = c = (char) (hexval(c) << 12 |
+                        hexval(ReadByte()) << 8 |
+                        hexval(ReadByte()) << 4 |
+                        hexval(ReadByte()));
+
+                column += 4;
+            } catch (java.io.IOException e) {
+                throw new Error("Invalid escape character at line " + line +
+                        " column " + column + ".");
+            }
+
+            if (backSlashCnt == 1)
+                return c;
+            else {
+                backup(backSlashCnt - 1);
+                return '\\';
+            }
+        } else {
+            UpdateLineColumn(c);
+            return c;
         }
+    }
 
-        // Here, we have seen an odd number of backslash's followed by a 'u'
-        try
-        {
-           while ((c = ReadByte()) == 'u')
-              ++column;
+    @Deprecated
+    /**
+     * @deprecated
+     * @see #getEndColumn
+     */
+    public int getColumn() {
+        return bufcolumn[bufpos];
+    }
 
-           buffer[bufpos] = c = (char)(hexval(c) << 12 |
-                                       hexval(ReadByte()) << 8 |
-                                       hexval(ReadByte()) << 4 |
-                                       hexval(ReadByte()));
+    @Deprecated
+    /**
+     * @deprecated
+     * @see #getEndLine
+     */
+    public int getLine() {
+        return bufline[bufpos];
+    }
 
-           column += 4;
-        }
-        catch(java.io.IOException e)
-        {
-           throw new Error("Invalid escape character at line " + line +
-                                         " column " + column + ".");
+    /**
+     * Get end column.
+     */
+    public int getEndColumn() {
+        return bufcolumn[bufpos];
+    }
+
+    /**
+     * Get end line.
+     */
+    public int getEndLine() {
+        return bufline[bufpos];
+    }
+
+    /**
+     * @return column of token start
+     */
+    public int getBeginColumn() {
+        return bufcolumn[tokenBegin];
+    }
+
+    /**
+     * @return line number of token start
+     */
+    public int getBeginLine() {
+        return bufline[tokenBegin];
+    }
+
+    /**
+     * Retreat.
+     */
+    public void backup(int amount) {
+
+        inBuf += amount;
+        if ((bufpos -= amount) < 0)
+            bufpos += bufsize;
+    }
+
+    /**
+     * Constructor.
+     */
+    public JavaCharStream(java.io.Reader dstream, int startline, int startcolumn, int buffersize) {
+        inputStream = dstream;
+        line = startline;
+        column = startcolumn - 1;
+
+        available = bufsize = buffersize;
+        buffer = new char[buffersize];
+        bufline = new int[buffersize];
+        bufcolumn = new int[buffersize];
+        nextCharBuf = new char[buffersize];
+    }
+
+    /**
+     * Constructor.
+     */
+    public JavaCharStream(java.io.Reader dstream, int startline, int startcolumn) {
+        this(dstream, startline, startcolumn, 4096);
+    }
+
+    /**
+     * Constructor.
+     */
+    public JavaCharStream(java.io.Reader dstream) {
+        this(dstream, 1, 1, 4096);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.Reader dstream) {
+        ReInit(dstream, 1, 1, 4096);
+    }
+
+    /**
+     * Constructor.
+     */
+    public JavaCharStream(java.io.InputStream dstream, String encoding, int startline,
+                          int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException {
+        this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+    }
+
+    /**
+     * Constructor.
+     */
+    public JavaCharStream(java.io.InputStream dstream, int startline,
+                          int startcolumn, int buffersize) {
+        this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
+    }
+
+    /**
+     * Constructor.
+     */
+    public JavaCharStream(java.io.InputStream dstream, String encoding, int startline,
+                          int startcolumn) throws java.io.UnsupportedEncodingException {
+        this(dstream, encoding, startline, startcolumn, 4096);
+    }
+
+    /**
+     * Constructor.
+     */
+    public JavaCharStream(java.io.InputStream dstream, int startline,
+                          int startcolumn) {
+        this(dstream, startline, startcolumn, 4096);
+    }
+
+    /**
+     * Constructor.
+     */
+    public JavaCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException {
+        this(dstream, encoding, 1, 1, 4096);
+    }
+
+    /**
+     * Constructor.
+     */
+    public JavaCharStream(java.io.InputStream dstream) {
+        this(dstream, 1, 1, 4096);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.Reader dstream, int startline, int startcolumn, int buffersize) {
+        inputStream = dstream;
+        line = startline;
+        column = startcolumn - 1;
+
+        if (buffer == null || buffersize != buffer.length) {
+            available = bufsize = buffersize;
+            buffer = new char[buffersize];
+            bufline = new int[buffersize];
+            bufcolumn = new int[buffersize];
+            nextCharBuf = new char[buffersize];
         }
+        prevCharIsLF = prevCharIsCR = false;
+        tokenBegin = inBuf = maxNextCharInd = 0;
+        nextCharInd = bufpos = -1;
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.Reader dstream, int startline, int startcolumn) {
+        ReInit(dstream, startline, startcolumn, 4096);
+    }
 
-        if (backSlashCnt == 1)
-           return c;
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.InputStream dstream, String encoding, int startline, int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException {
+        ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.InputStream dstream, int startline, int startcolumn, int buffersize) {
+        ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.InputStream dstream, String encoding, int startline, int startcolumn) throws java.io.UnsupportedEncodingException {
+        ReInit(dstream, encoding, startline, startcolumn, 4096);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.InputStream dstream, int startline, int startcolumn) {
+        ReInit(dstream, startline, startcolumn, 4096);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException {
+        ReInit(dstream, encoding, 1, 1, 4096);
+    }
+
+    /**
+     * Reinitialise.
+     */
+    public void ReInit(java.io.InputStream dstream) {
+        ReInit(dstream, 1, 1, 4096);
+    }
+
+    /**
+     * @return token image as String
+     */
+    public String GetImage() {
+        if (bufpos >= tokenBegin)
+            return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
         else
-        {
-           backup(backSlashCnt - 1);
-           return '\\';
+            return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+                    new String(buffer, 0, bufpos + 1);
+    }
+
+    /**
+     * @return suffix
+     */
+    public char[] GetSuffix(int len) {
+        char[] ret = new char[len];
+
+        if ((bufpos + 1) >= len)
+            System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+        else {
+            System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+                    len - bufpos - 1);
+            System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
         }
-     }
-     else
-     {
-        UpdateLineColumn(c);
-        return c;
-     }
-  }
-
-  /**
-   * @deprecated
-   * @see #getEndColumn
-   */
-  public int getColumn() {
-     return bufcolumn[bufpos];
-  }
-
-  /**
-   * @deprecated
-   * @see #getEndLine
-   */
-  public int getLine() {
-     return bufline[bufpos];
-  }
-
-/** Get end column. */
-  public int getEndColumn() {
-     return bufcolumn[bufpos];
-  }
-
-/** Get end line. */
-  public int getEndLine() {
-     return bufline[bufpos];
-  }
-
-/** @return column of token start */
-  public int getBeginColumn() {
-     return bufcolumn[tokenBegin];
-  }
-
-/** @return line number of token start */
-  public int getBeginLine() {
-     return bufline[tokenBegin];
-  }
-
-/** Retreat. */
-  public void backup(int amount) {
-
-    inBuf += amount;
-    if ((bufpos -= amount) < 0)
-       bufpos += bufsize;
-  }
-
-/** Constructor. */
-  public JavaCharStream(java.io.Reader dstream,
-                 int startline, int startcolumn, int buffersize)
-  {
-    inputStream = dstream;
-    line = startline;
-    column = startcolumn - 1;
-
-    available = bufsize = buffersize;
-    buffer = new char[buffersize];
-    bufline = new int[buffersize];
-    bufcolumn = new int[buffersize];
-    nextCharBuf = new char[buffersize];
-  }
-
-/** Constructor. */
-  public JavaCharStream(java.io.Reader dstream,
-                                        int startline, int startcolumn)
-  {
-     this(dstream, startline, startcolumn, 4096);
-  }
-
-/** Constructor. */
-  public JavaCharStream(java.io.Reader dstream)
-  {
-     this(dstream, 1, 1, 4096);
-  }
-
-/** Constructor. */
-  public JavaCharStream(java.io.InputStream dstream, String encoding, int startline,
-  int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
-  {
-     this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
-  }
-
-/** Constructor. */
-  public JavaCharStream(java.io.InputStream dstream, int startline,
-  int startcolumn, int buffersize)
-  {
-     this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
-  }
-
-/** Constructor. */
-  public JavaCharStream(java.io.InputStream dstream, String encoding, int startline,
-                        int startcolumn) throws java.io.UnsupportedEncodingException
-  {
-     this(dstream, encoding, startline, startcolumn, 4096);
-  }
-
-/** Constructor. */
-  public JavaCharStream(java.io.InputStream dstream, int startline,
-                        int startcolumn)
-  {
-     this(dstream, startline, startcolumn, 4096);
-  }
-
-/** Constructor. */
-  public JavaCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
-  {
-     this(dstream, encoding, 1, 1, 4096);
-  }
-
-/** Constructor. */
-  public JavaCharStream(java.io.InputStream dstream)
-  {
-     this(dstream, 1, 1, 4096);
-  }
-
-
-
-
-  /** @return token image as String */
-  public String GetImage()
-  {
-     if (bufpos >= tokenBegin)
-        return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
-     else
-        return new String(buffer, tokenBegin, bufsize - tokenBegin) +
-                              new String(buffer, 0, bufpos + 1);
-  }
-
-  /** @return suffix */
-  public char[] GetSuffix(int len)
-  {
-     char[] ret = new char[len];
-
-     if ((bufpos + 1) >= len)
-        System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
-     else
-     {
-        System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
-                                                          len - bufpos - 1);
-        System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
-     }
-
-     return ret;
-  }
-
-  /** Set buffers back to null when finished. */
-  public void Done()
-  {
-     nextCharBuf = null;
-     buffer = null;
-     bufline = null;
-     bufcolumn = null;
-  }
-
-  /**
-   * Method to adjust line and column numbers for the start of a token.
-   */
-  public void adjustBeginLineColumn(int newLine, int newCol)
-  {
-     int start = tokenBegin;
-     int len;
-
-     if (bufpos >= tokenBegin)
-     {
-        len = bufpos - tokenBegin + inBuf + 1;
-     }
-     else
-     {
-        len = bufsize - tokenBegin + bufpos + 1 + inBuf;
-     }
-
-     int i = 0, j = 0, k = 0;
-     int nextColDiff = 0, columnDiff = 0;
-
-     while (i < len &&
-            bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
-     {
-        bufline[j] = newLine;
-        nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
-        bufcolumn[j] = newCol + columnDiff;
-        columnDiff = nextColDiff;
-        i++;
-     }
-
-     if (i < len)
-     {
-        bufline[j] = newLine++;
-        bufcolumn[j] = newCol + columnDiff;
-
-        while (i++ < len)
-        {
-           if (bufline[j = start % bufsize] != bufline[++start % bufsize])
-              bufline[j] = newLine++;
-           else
-              bufline[j] = newLine;
+
+        return ret;
+    }
+
+    /**
+     * Set buffers back to null when finished.
+     */
+    public void Done() {
+        nextCharBuf = null;
+        buffer = null;
+        bufline = null;
+        bufcolumn = null;
+    }
+
+    /**
+     * Method to adjust line and column numbers for the start of a token.
+     */
+    public void adjustBeginLineColumn(int newLine, int newCol) {
+        int start = tokenBegin;
+        int len;
+
+        if (bufpos >= tokenBegin) {
+            len = bufpos - tokenBegin + inBuf + 1;
+        } else {
+            len = bufsize - tokenBegin + bufpos + 1 + inBuf;
         }
-     }
 
-     line = bufline[j];
-     column = bufcolumn[j];
-  }
+        int i = 0, j = 0, k = 0;
+        int nextColDiff = 0, columnDiff = 0;
+
+        while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) {
+            bufline[j] = newLine;
+            nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+            bufcolumn[j] = newCol + columnDiff;
+            columnDiff = nextColDiff;
+            i++;
+        }
+
+        if (i < len) {
+            bufline[j] = newLine++;
+            bufcolumn[j] = newCol + columnDiff;
+
+            while (i++ < len) {
+                if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+                    bufline[j] = newLine++;
+                else
+                    bufline[j] = newLine;
+            }
+        }
+
+        line = bufline[j];
+        column = bufcolumn[j];
+    }
 
 }
-/* JavaCC - OriginalChecksum=de7dff2a3eda69c495bc3a754d6314ab (do not edit this line) */
+/* JavaCC - OriginalChecksum=42728d5d6de379c28d8e61854c22fc66 (do not edit this line) */

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/jjtree/org/apache/cayenne/exp/parser/ExpressionParser.jjt
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/jjtree/org/apache/cayenne/exp/parser/ExpressionParser.jjt b/cayenne-server/src/main/jjtree/org/apache/cayenne/exp/parser/ExpressionParser.jjt
index 370a223..16e443b 100644
--- a/cayenne-server/src/main/jjtree/org/apache/cayenne/exp/parser/ExpressionParser.jjt
+++ b/cayenne-server/src/main/jjtree/org/apache/cayenne/exp/parser/ExpressionParser.jjt
@@ -77,82 +77,91 @@ void notCondition() : {}
 
 void simpleCondition() : {} 
 {
-	<TRUE> #True
-	| 
-	<FALSE> #False
-	| 
-	  scalarConditionExpression()
-	(
-	   simpleNotCondition()
-	| 
-	  ("="  | "==") scalarExpression() #Equal(2)
-	| 
-	  ("!=" | "<>")  scalarExpression() #NotEqual(2)
+	  <TRUE> #True
 	|
-	  "<=" scalarExpression() #LessOrEqual(2)
-	| 
-	  "<" scalarExpression() #Less(2)
-	| 
-	  ">"  scalarExpression() #Greater(2)
-	| 
-	  ">=" scalarExpression() #GreaterOrEqual(2)
-	|
-		"like" scalarExpression() #Like(2)
+	  <FALSE> #False
 	|
-	    "likeIgnoreCase"  scalarExpression() #LikeIgnoreCase(2)
-	|  
-		"in"  
-		(  namedParameter() | "(" scalarCommaList() ")" )
-		#In(2)
-	|  
-		"between"  scalarExpression() "and" scalarExpression() #Between(3)
+	  conditionExpression()
+	(
+          ("="  | "==") scalarExpression() #Equal(2)
+        |
+          ("!=" | "<>")  scalarExpression() #NotEqual(2)
+        |
+          "<=" scalarExpression() #LessOrEqual(2)
+        |
+          "<" scalarExpression() #Less(2)
+        |
+          ">"  scalarExpression() #Greater(2)
+        |
+          ">=" scalarExpression() #GreaterOrEqual(2)
+        |
+          "like" scalarExpression() #Like(2)
+        |
+          "likeIgnoreCase"  scalarExpression() #LikeIgnoreCase(2)
+        |
+          "in" ( namedParameter() | "(" scalarCommaList() ")" ) #In(2)
+        |
+          "between"  scalarExpression() "and" scalarExpression() #Between(3)
+        |
+          simpleNotCondition()
 	)?
 }
 
 void simpleNotCondition() : {} 
 {
 	("not" | "!" )
-	
 	(
 		"like" scalarExpression() #NotLike(2)
 	|
 	    "likeIgnoreCase"  scalarExpression() #NotLikeIgnoreCase(2)
-	|  
-		"in"  
-		(  namedParameter() |  "(" scalarCommaList() ")" )
-		#NotIn(2)
-	|  
+	|
+		"in" (  namedParameter() |  "(" scalarCommaList() ")" ) #NotIn(2)
+	|
 		"between"  scalarExpression() "and" scalarExpression() #NotBetween(3)
 	)
 }
 
 void scalarCommaList() : {}
 {
-	(
-		scalarConstExpression()
-		( ","  scalarConstExpression() )*
-	) #List
+	( scalarConstExpression() ( ","  scalarConstExpression() )* ) #List
 }
 
-void scalarConditionExpression() : {} 
+void conditionExpression() : {}
 {
    // TODO: once we switch expression package to use AST* from parser package,
    // we might need implement special subclasses for numeric and character constant
    // nodes for the purpose of expression evaluation, instead . For now keep them as 
    // generic ASTScalar and purge from the parent node to keep compatible with QualifierTranslator.
-   
-		scalarNumericExpression()
+
+        // Path without any operator will go to numeric expression.
+        // This done intentionally to remove lookahead that leads
+        // to dramatically perfomance degradation (parser can become 3 times slower)
+		numericExpression()
+    |
+        stringExpression()
 	|
-		<SINGLE_QUOTED_STRING> { jjtThis.setValue(token_source.literalValue); } #Scalar(0)
-	| 
-	  	<DOUBLE_QUOTED_STRING> { jjtThis.setValue(token_source.literalValue); } #Scalar(0)
-	| 
-		<NULL> #Scalar(0) 
+		<NULL> #Scalar(0)
+}
+
+void stringParameter() : {}
+{
+        pathExpression()
+    |
+        stringExpression()
+}
+
+void stringExpression() : {}
+{
+    <SINGLE_QUOTED_STRING> { jjtThis.setValue(token_source.literalValue); } #Scalar(0)
+    |
+    <DOUBLE_QUOTED_STRING> { jjtThis.setValue(token_source.literalValue); } #Scalar(0)
+    |
+    functionsReturningStrings()
 }
 
 void scalarExpression() : {} 
 {
-  	   scalarConditionExpression()
+  	   conditionExpression()
 	|
 	  <TRUE> { jjtThis.setValue(true); }  #Scalar(0)
 	| 
@@ -176,7 +185,7 @@ void scalarConstExpression() : {}
 	  <FALSE> { jjtThis.setValue(false); }  #Scalar(0)
 }
 
-void scalarNumericExpression() : {}
+void numericExpression() : {}
 {
     bitwiseOr()
 }
@@ -259,40 +268,75 @@ void numericPrimary() : {}
 		
 		"(" orCondition() ")"
 	|
-		pathExpression()
-	|
-		namedParameter()
-	|
 	   <INT_LITERAL> { jjtThis.setValue(token_source.literalValue); } #Scalar(0)
 	| 
 	   <FLOAT_LITERAL>{ jjtThis.setValue(token_source.literalValue); }  #Scalar(0)
+	|
+        namedParameter()
+    |
+        functionsReturningNumerics()
+	|
+        pathExpression()
 }
 
-void namedParameter() : 
+void functionsReturningStrings() : { }
 {
-	Token t;
+	concat() | substring() | trim() | lower() | upper()
 }
+
+void concat() #Concat : { }
 {
-	"$" t = <PROPERTY_PATH> { jjtThis.setValue(t.image); } #NamedParameter(0)
+	<CONCAT> "(" stringParameter() "," stringParameter() ")"
+}
+
+void substring() #Substring : { }
+{
+	<SUBSTRING> "(" stringParameter() "," numericExpression() ["," numericExpression()] ")"
 }
 
+void trim() #Trim : { }
+{
+	<TRIM> "(" stringParameter() ")"
+}
 
-void pathExpression() : {
-   Token t;
+void lower() #Lower : { }
+{
+	<LOWER> "(" stringParameter() ")"
 }
+
+void upper() #Upper : { }
 {
-   ( 
-     t = <PROPERTY_PATH> { jjtThis.setPath(t.image); } #ObjPath(0)
-   | 
-     "obj:" 
-     t = <PROPERTY_PATH> { jjtThis.setPath(t.image); } #ObjPath(0)
-   |
-     "db:" 
-     t = <PROPERTY_PATH> { jjtThis.setPath(t.image); } #DbPath(0)
-   |
-     "enum:" 
-     t = <PROPERTY_PATH> { jjtThis.setValue(ParserUtil.makeEnum(t.image)); } #Scalar(0)
-   )
+	<UPPER> "(" stringParameter() ")"
+}
+
+void functionsReturningNumerics() : { }
+{
+	length() | locate() | abs() | sqrt() | mod()
+}
+
+void length() #Length : { }
+{
+	<LENGTH> "(" stringParameter() ")"
+}
+
+void locate() #Locate : { }
+{
+	<LOCATE> "(" stringParameter() "," stringParameter() ["," numericExpression()] ")"
+}
+
+void abs() #Abs : { }
+{
+	<ABS> "(" numericExpression() ")"
+}
+
+void sqrt() #Sqrt : { }
+{
+	<SQRT> "(" numericExpression() ")"
+}
+
+void mod() #Mod : { }
+{
+	<MOD> "(" numericExpression() "," numericExpression() ")"
 }
 
 
@@ -381,10 +425,65 @@ SKIP :
 
 TOKEN : {
 	<NULL: "null" | "NULL" >
-|
-	<TRUE: "true" | "TRUE" >
-|
-	<FALSE: "false" | "FALSE" >
+    |   <TRUE: "true" | "TRUE" >
+    |   <FALSE: "false" | "FALSE" >
+}
+
+TOKEN [ IGNORE_CASE ]: /* aggregates */
+{
+	<AVG: "AVG" >
+	|	<MIN: "MIN" >
+	|	<MAX: "MAX" >
+	|	<SUM: "SUM" >
+	|	<COUNT: "COUNT" >
+}
+
+TOKEN [ IGNORE_CASE ]: /* functions returning strings */
+{
+	<CONCAT: "CONCAT" >
+	|	<SUBSTRING: "SUBSTRING" >
+	|	<TRIM: "TRIM" >
+	|	<LOWER: "LOWER" >
+	|	<UPPER: "UPPER" >
+}
+
+TOKEN [ IGNORE_CASE ]: /* functions returning numerics */
+{
+	<LENGTH: "LENGTH" >
+	|	<LOCATE: "LOCATE" >
+	|	<ABS: "ABS" >
+	|	<SQRT: "SQRT" >
+	|	<MOD: "MOD" >
+}
+
+TOKEN [ IGNORE_CASE ]: /* functions returning datetime */
+{
+	<CURRENT_DATE: "CURRENT_DATE" >
+	|	<CURRENT_TIME: "CURRENT_TIME" >
+	|	<CURRENT_TIMESTAMP: "CURRENT_TIMESTAMP" >
+}
+
+void namedParameter() :
+{
+	Token t;
+}
+{
+	"$" t = <PROPERTY_PATH> { jjtThis.setValue(t.image); } #NamedParameter(0)
+}
+
+void pathExpression() : {
+   Token t;
+}
+{
+   (
+             t = <PROPERTY_PATH> { jjtThis.setPath(t.image); } #ObjPath(0)
+   |
+     "obj:"  t = <PROPERTY_PATH> { jjtThis.setPath(t.image); } #ObjPath(0)
+   |
+     "db:"   t = <PROPERTY_PATH> { jjtThis.setPath(t.image); } #DbPath(0)
+   |
+     "enum:" t = <PROPERTY_PATH> { jjtThis.setValue(ParserUtil.makeEnum(t.image)); } #Scalar(0)
+   )
 }
 
 TOKEN : {
@@ -400,8 +499,7 @@ TOKEN :
   < #DIGIT: ["0"-"9"] >
 }
 
-
-/** 
+/**
  * Quoted Strings, whose object value is stored in the token manager's
  * "literalValue" field. Both single and double qoutes are allowed 
  */

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionFactoryTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionFactoryTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionFactoryTest.java
index 3cf4a46..9fc6ac2 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionFactoryTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionFactoryTest.java
@@ -33,6 +33,7 @@ import java.util.Map;
 
 import org.apache.cayenne.exp.parser.ASTLike;
 import org.apache.cayenne.exp.parser.ASTLikeIgnoreCase;
+import org.apache.cayenne.exp.parser.ASTTrim;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -471,4 +472,16 @@ public class ExpressionFactoryTest {
 	public void testDbPathExp() {
 		assertEquals("db:abc.xyz", ExpressionFactory.dbPathExp("abc.xyz").toString());
 	}
+
+	@Test
+	public void testFuncExp() {
+		Expression e = ExpressionFactory.exp("TRIM(abc.xyz)");
+		assertEquals(ASTTrim.class, e.getClass());
+	}
+
+    // CAY-2081
+    @Test(expected = ExpressionException.class)
+    public void testExceptionInParse() {
+        ExpressionFactory.exp("name like %32_65415'");
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallMathIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallMathIT.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallMathIT.java
index 192a1ad..9033ab9 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallMathIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallMathIT.java
@@ -19,8 +19,12 @@
 
 package org.apache.cayenne.exp.parser;
 
+import java.math.BigDecimal;
+
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.exp.Property;
 import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.testdo.table_primitives.TablePrimitives;
@@ -80,4 +84,27 @@ public class ASTFunctionCallMathIT extends ServerCase {
         assertEquals(p1, p2);
     }
 
+    @Test
+    public void testASTAbsParse() {
+        Expression exp = ExpressionFactory.exp("ABS(-3)");
+        assertEquals(3.0, exp.evaluate(new Object()));
+    }
+
+    @Test
+    public void testASTSqrtParse() {
+        Expression exp = ExpressionFactory.exp("SQRT(16)");
+        assertEquals(4.0, exp.evaluate(new Object()));
+    }
+
+    @Test
+    public void testASTModParse() {
+        Expression exp = ExpressionFactory.exp("MOD(11,2)");
+        assertEquals(1.0, exp.evaluate(new Object()));
+    }
+
+    @Test
+    public void testComplexParse() {
+        Expression exp = ExpressionFactory.exp("10 - MOD(SQRT(ABS(-9)), 2)");
+        assertEquals(BigDecimal.valueOf(9L), exp.evaluate(new Object()));
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallStringIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallStringIT.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallStringIT.java
index cbb7514..58a69dd 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallStringIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallStringIT.java
@@ -23,6 +23,8 @@ import java.util.Date;
 
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.exp.Property;
 import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.testdo.testmap.Artist;
@@ -152,4 +154,45 @@ public class ASTFunctionCallStringIT extends ServerCase {
         assertEquals(a1, a2);
     }
 
+    @Test
+    public void testASTConcatParse() {
+        Expression exp = ExpressionFactory.exp("CONCAT('abc', 'def')");
+        assertEquals("abcdef", exp.evaluate(new Object()));
+    }
+
+    @Test
+    public void testASTSubstringParse() {
+        Expression exp = ExpressionFactory.exp("SUBSTRING('123456789', 3, 2)");
+        assertEquals("45", exp.evaluate(new Object()));
+    }
+
+    @Test
+    public void testASTTrimParse() {
+        Expression exp = ExpressionFactory.exp("TRIM(' abc ')");
+        assertEquals("abc", exp.evaluate(new Object()));
+    }
+
+    @Test
+    public void testASTLowerParse() {
+        Expression exp = ExpressionFactory.exp("LOWER('AbC')");
+        assertEquals("abc", exp.evaluate(new Object()));
+    }
+
+    @Test
+    public void testASTUpperParse() {
+        Expression exp = ExpressionFactory.exp("UPPER('aBc')");
+        assertEquals("ABC", exp.evaluate(new Object()));
+    }
+
+    @Test
+    public void testASTLocateParse() {
+        Expression exp = ExpressionFactory.exp("LOCATE('Bc', 'aBc')");
+        assertEquals(2, exp.evaluate(new Object()));
+    }
+
+    @Test
+    public void testComplexParse() {
+        Expression exp = ExpressionFactory.exp("LOCATE(UPPER('Bc'), UPPER('aBc')) = LENGTH(SUBSTRING(TRIM(LOWER(CONCAT('   abc', 'def   '))), 3, 2))");
+        assertEquals(true, exp.evaluate(new Object()));
+    }
 }


[3/3] cayenne git commit: CAY-2196 Support for new function expressions in expression parser - updated and refactored grammar for parser - add token id to AST* function call nodes - escape in parse exception message - tests

Posted by nt...@apache.org.
CAY-2196 Support for new function expressions in expression parser
 - updated and refactored grammar for parser
 - add token id to AST* function call nodes
 - escape in parse exception message
 - tests


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/c44ccfde
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/c44ccfde
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/c44ccfde

Branch: refs/heads/master
Commit: c44ccfde3a2e0c85eb3f0853a257cb990568766a
Parents: 666c96d
Author: Nikita Timofeev <st...@gmail.com>
Authored: Thu Jan 19 14:31:41 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Thu Jan 19 14:31:41 2017 +0300

----------------------------------------------------------------------
 cayenne-server/pom.xml                          |   20 +-
 .../apache/cayenne/exp/ExpressionFactory.java   |   15 +-
 .../org/apache/cayenne/exp/parser/ASTAbs.java   |    2 +-
 .../exp/parser/ASTAggregateFunctionCall.java    |    4 +-
 .../org/apache/cayenne/exp/parser/ASTAvg.java   |    2 +-
 .../apache/cayenne/exp/parser/ASTConcat.java    |    2 +-
 .../org/apache/cayenne/exp/parser/ASTCount.java |    4 +-
 .../cayenne/exp/parser/ASTFunctionCall.java     |    4 +-
 .../apache/cayenne/exp/parser/ASTLength.java    |    2 +-
 .../apache/cayenne/exp/parser/ASTLocate.java    |    4 +-
 .../org/apache/cayenne/exp/parser/ASTLower.java |    2 +-
 .../org/apache/cayenne/exp/parser/ASTMax.java   |    2 +-
 .../org/apache/cayenne/exp/parser/ASTMin.java   |    2 +-
 .../org/apache/cayenne/exp/parser/ASTMod.java   |    2 +-
 .../org/apache/cayenne/exp/parser/ASTSqrt.java  |    2 +-
 .../apache/cayenne/exp/parser/ASTSubstring.java |    2 +-
 .../org/apache/cayenne/exp/parser/ASTSum.java   |    2 +-
 .../org/apache/cayenne/exp/parser/ASTTrim.java  |    2 +-
 .../org/apache/cayenne/exp/parser/ASTUpper.java |    2 +-
 .../cayenne/exp/parser/ExpressionParser.java    |  707 ++++++++--
 .../exp/parser/ExpressionParserConstants.java   |  100 +-
 .../parser/ExpressionParserTokenManager.java    | 1294 +++++++++++-------
 .../parser/ExpressionParserTreeConstants.java   |   47 +-
 .../exp/parser/JJTExpressionParserState.java    |   19 +
 .../cayenne/exp/parser/JavaCharStream.java      | 1099 ++++++++-------
 .../cayenne/exp/parser/ExpressionParser.jjt     |  246 +++-
 .../cayenne/exp/ExpressionFactoryTest.java      |   13 +
 .../exp/parser/ASTFunctionCallMathIT.java       |   27 +
 .../exp/parser/ASTFunctionCallStringIT.java     |   43 +
 29 files changed, 2435 insertions(+), 1237 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/pom.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/pom.xml b/cayenne-server/pom.xml
index 913ceca..1e27e2f 100644
--- a/cayenne-server/pom.xml
+++ b/cayenne-server/pom.xml
@@ -199,11 +199,21 @@
 							<goal>jjtree-javacc</goal>
 						</goals>
 					</execution>
-					<!-- src/main/jjtree/org/apache/cayenne/exp/parser for now is generated 
-						outside of Maven with JavaCC command line tools (maybe we should do the same 
-						for EJBQL) : # Parser grammar out of tree grammar: $ ./javacc-5.0/bin/jjtree 
-						src/main/jjtree/org/apache/cayenne/exp/parser/ExpressionParser.jjt # docs 
-						$ ./javacc-5.0/bin/jjdoc -TEXT=true ExpressionParser.jj -->
+					<!--
+						src/main/jjtree/org/apache/cayenne/exp/parser for now is generated
+						outside of Maven with JavaCC command line tools (maybe we should do the same for EJBQL) :
+							$ cd cayenne-server/src/main/jjtree/org/apache/cayenne/exp/parser
+						# Parser grammar out of tree grammar:
+							$ ~/javacc-5.0/bin/jjtree ExpressionParser.jjt
+						# Parser java code:
+							$ ~/javacc-5.0/bin/javacc ExpressionParser.jj
+
+						# Copy generated classes to src/main/jjtree/org/apache/cayenne/exp/parser
+						# except all AST*, Node, SimpleNode, JavaCharStream
+
+						# docs
+							$ ./javacc-5.0/bin/jjdoc -TEXT=true ExpressionParser.jj
+					-->
 				</executions>
 			</plugin>
 			<plugin>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
index 22dec9f..8d132a9 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
@@ -57,7 +57,6 @@ import org.apache.cayenne.exp.parser.ASTTrue;
 import org.apache.cayenne.exp.parser.ExpressionParser;
 import org.apache.cayenne.exp.parser.ExpressionParserTokenManager;
 import org.apache.cayenne.exp.parser.JavaCharStream;
-import org.apache.cayenne.exp.parser.ParseException;
 import org.apache.cayenne.exp.parser.SimpleNode;
 import org.apache.cayenne.map.Entity;
 
@@ -1310,8 +1309,8 @@ public class ExpressionFactory {
 		// optimizing parser buffers per CAY-1667...
 		// adding 1 extra char to the buffer size above the String length, as
 		// otherwise resizing still occurs at the end of the stream
-		int bufferSize = expressionString.length() > PARSE_BUFFER_MAX_SIZE ? PARSE_BUFFER_MAX_SIZE : expressionString
-				.length() + 1;
+		int bufferSize = expressionString.length() > PARSE_BUFFER_MAX_SIZE ?
+				PARSE_BUFFER_MAX_SIZE : expressionString.length() + 1;
 		Reader reader = new StringReader(expressionString);
 		JavaCharStream stream = new JavaCharStream(reader, 1, 1, bufferSize);
 		ExpressionParserTokenManager tm = new ExpressionParserTokenManager(stream);
@@ -1319,17 +1318,9 @@ public class ExpressionFactory {
 
 		try {
 			return parser.expression();
-		} catch (ParseException ex) {
-
-			// can be null
-			String message = ex.getMessage();
-			throw new ExpressionException(message != null ? message : "", ex);
 		} catch (Throwable th) {
-			// can be null
 			String message = th.getMessage();
-
-			// another common error is TokenManagerError
-			throw new ExpressionException(message != null ? message : "", th);
+			throw new ExpressionException("%s", th, message != null ? message : "");
 		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAbs.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAbs.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAbs.java
index 47b06dc..b5220bb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAbs.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAbs.java
@@ -32,7 +32,7 @@ public class ASTAbs extends ASTFunctionCall {
     }
 
     public ASTAbs(Expression expression) {
-        super("ABS", expression);
+        super(ExpressionParserTreeConstants.JJTABS, "ABS", expression);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAggregateFunctionCall.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAggregateFunctionCall.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAggregateFunctionCall.java
index d4dec9e..b6e692d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAggregateFunctionCall.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAggregateFunctionCall.java
@@ -30,7 +30,7 @@ public abstract class ASTAggregateFunctionCall extends ASTFunctionCall {
         super(id, functionName);
     }
 
-    ASTAggregateFunctionCall(String functionName, Object... nodes) {
-        super(functionName, nodes);
+    ASTAggregateFunctionCall(int id, String functionName, Object... nodes) {
+        super(id, functionName, nodes);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAvg.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAvg.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAvg.java
index 16146cf..eb95216 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAvg.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTAvg.java
@@ -31,7 +31,7 @@ public class ASTAvg extends ASTAggregateFunctionCall {
     }
 
     public ASTAvg(Expression expression) {
-        super("AVG", expression);
+        super(0, "AVG", expression);
     }
 
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTConcat.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTConcat.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTConcat.java
index efb11ad..0e285c4 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTConcat.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTConcat.java
@@ -32,7 +32,7 @@ public class ASTConcat extends ASTFunctionCall {
     }
 
     public ASTConcat(Expression... expressions) {
-        super("CONCAT", expressions);
+        super(ExpressionParserTreeConstants.JJTCONCAT, "CONCAT", expressions);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTCount.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTCount.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTCount.java
index 72172f7..ee3a65e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTCount.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTCount.java
@@ -31,11 +31,11 @@ public class ASTCount extends ASTAggregateFunctionCall {
     }
 
     public ASTCount(Expression expression) {
-        super("COUNT", expression);
+        super(0, "COUNT", expression);
     }
 
     public ASTCount() {
-        super("COUNT", new ASTAsterisk());
+        super(0, "COUNT", new ASTAsterisk());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTFunctionCall.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTFunctionCall.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTFunctionCall.java
index 9c3aa07..8080a52 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTFunctionCall.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTFunctionCall.java
@@ -33,8 +33,8 @@ public abstract class ASTFunctionCall extends SimpleNode {
         this.functionName = functionName;
     }
 
-    public ASTFunctionCall(String functionName, Object... nodes) {
-        this(0, functionName);
+    public ASTFunctionCall(int id, String functionName, Object... nodes) {
+        this(id, functionName);
         this.functionName = functionName;
         int len = nodes.length;
         for (int i = 0; i < len; i++) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLength.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLength.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLength.java
index 5d1eea8..e12512e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLength.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLength.java
@@ -32,7 +32,7 @@ public class ASTLength extends ASTFunctionCall {
     }
 
     public ASTLength(Expression expression) {
-        super("LENGTH", expression);
+        super(ExpressionParserTreeConstants.JJTLENGTH, "LENGTH", expression);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLocate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLocate.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLocate.java
index 1c537e5..d26dbb5 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLocate.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLocate.java
@@ -32,11 +32,11 @@ public class ASTLocate extends ASTFunctionCall {
     }
 
     public ASTLocate(Expression substring, Expression path) {
-        super("LOCATE", substring, path);
+        super(ExpressionParserTreeConstants.JJTLOCATE, "LOCATE", substring, path);
     }
 
     public ASTLocate(Expression substring, Expression path, Expression offset) {
-        super("LOCATE", substring, path, offset);
+        super(ExpressionParserTreeConstants.JJTLOCATE, "LOCATE", substring, path, offset);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLower.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLower.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLower.java
index b63319a..78b6f80 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLower.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLower.java
@@ -33,7 +33,7 @@ public class ASTLower extends ASTFunctionCall {
     }
 
     public ASTLower(Expression expression) {
-        super("LOWER", expression);
+        super(ExpressionParserTreeConstants.JJTLOWER, "LOWER", expression);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMax.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMax.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMax.java
index b0356eb..2a59d76 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMax.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMax.java
@@ -31,7 +31,7 @@ public class ASTMax extends ASTAggregateFunctionCall {
     }
 
     public ASTMax(Expression expression) {
-        super("MAX", expression);
+        super(0, "MAX", expression);
     }
 
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMin.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMin.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMin.java
index c55b5df..dc5142f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMin.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMin.java
@@ -31,7 +31,7 @@ public class ASTMin extends ASTAggregateFunctionCall {
     }
 
     public ASTMin(Expression expression) {
-        super("MIN", expression);
+        super(0, "MIN", expression);
     }
 
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMod.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMod.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMod.java
index f951cb7..c4f79a7 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMod.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTMod.java
@@ -32,7 +32,7 @@ public class ASTMod extends ASTFunctionCall {
     }
 
     public ASTMod(Expression expression, Expression divisor) {
-        super("MOD", expression, divisor);
+        super(ExpressionParserTreeConstants.JJTMOD, "MOD", expression, divisor);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSqrt.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSqrt.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSqrt.java
index d311444..71e8e32 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSqrt.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSqrt.java
@@ -32,7 +32,7 @@ public class ASTSqrt extends ASTFunctionCall {
     }
 
     public ASTSqrt(Expression expression) {
-        super("SQRT", expression);
+        super(ExpressionParserTreeConstants.JJTSQRT, "SQRT", expression);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSubstring.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSubstring.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSubstring.java
index c6ae864..33ac4e0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSubstring.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSubstring.java
@@ -33,7 +33,7 @@ public class ASTSubstring extends ASTFunctionCall {
     }
 
     public ASTSubstring(Expression path, Expression length, Expression offset) {
-        super("SUBSTRING", path, length, offset);
+        super(ExpressionParserTreeConstants.JJTSUBSTRING, "SUBSTRING", path, length, offset);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSum.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSum.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSum.java
index bcc5e12..73e0b8c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSum.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTSum.java
@@ -31,7 +31,7 @@ public class ASTSum extends ASTAggregateFunctionCall {
     }
 
     public ASTSum(Expression expression) {
-        super("SUM", expression);
+        super(0, "SUM", expression);
     }
 
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTTrim.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTTrim.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTTrim.java
index 2a0077a..f037dd0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTTrim.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTTrim.java
@@ -32,7 +32,7 @@ public class ASTTrim extends ASTFunctionCall {
     }
 
     public ASTTrim(Expression path) {
-        super("TRIM", path);
+        super(ExpressionParserTreeConstants.JJTTRIM, "TRIM", path);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTUpper.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTUpper.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTUpper.java
index fad6026..60716fc 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTUpper.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTUpper.java
@@ -32,7 +32,7 @@ public class ASTUpper extends ASTFunctionCall {
     }
 
     public ASTUpper(Expression expression) {
-        super("UPPER", expression);
+        super(ExpressionParserTreeConstants.JJTUPPER, "UPPER", expression);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParser.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParser.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParser.java
index 77fea61..20a6f42 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParser.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParser.java
@@ -163,13 +163,23 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
     case 25:
     case 26:
     case 29:
-    case 30:
-    case 31:
-    case 32:
-    case 33:
     case NULL:
     case TRUE:
     case FALSE:
+    case CONCAT:
+    case SUBSTRING:
+    case TRIM:
+    case LOWER:
+    case UPPER:
+    case LENGTH:
+    case LOCATE:
+    case ABS:
+    case SQRT:
+    case MOD:
+    case 55:
+    case 56:
+    case 57:
+    case 58:
     case PROPERTY_PATH:
     case SINGLE_QUOTED_STRING:
     case DOUBLE_QUOTED_STRING:
@@ -214,17 +224,27 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
     case 25:
     case 26:
     case 29:
-    case 30:
-    case 31:
-    case 32:
-    case 33:
     case NULL:
+    case CONCAT:
+    case SUBSTRING:
+    case TRIM:
+    case LOWER:
+    case UPPER:
+    case LENGTH:
+    case LOCATE:
+    case ABS:
+    case SQRT:
+    case MOD:
+    case 55:
+    case 56:
+    case 57:
+    case 58:
     case PROPERTY_PATH:
     case SINGLE_QUOTED_STRING:
     case DOUBLE_QUOTED_STRING:
     case INT_LITERAL:
     case FLOAT_LITERAL:
-      scalarConditionExpression();
+      conditionExpression();
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
       case 3:
       case 4:
@@ -241,10 +261,6 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
       case 15:
       case 18:
         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case 3:
-        case 4:
-          simpleNotCondition();
-          break;
         case 5:
         case 6:
           switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
@@ -492,7 +508,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
                   jjtree.openNodeScope(jjtn011);
           try {
             switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-            case 30:
+            case 55:
               namedParameter();
               break;
             case 16:
@@ -554,6 +570,10 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
                                                       }
           }
           break;
+        case 3:
+        case 4:
+          simpleNotCondition();
+          break;
         default:
           jj_la1[7] = jj_gen;
           jj_consume_token(-1);
@@ -647,7 +667,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
                   jjtree.openNodeScope(jjtn003);
       try {
         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case 30:
+        case 55:
           namedParameter();
           break;
         case 16:
@@ -756,21 +776,80 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
     }
   }
 
-  final public void scalarConditionExpression() throws ParseException {
+  final public void conditionExpression() throws ParseException {
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case 16:
     case 25:
     case 26:
     case 29:
-    case 30:
-    case 31:
-    case 32:
-    case 33:
+    case LENGTH:
+    case LOCATE:
+    case ABS:
+    case SQRT:
+    case MOD:
+    case 55:
+    case 56:
+    case 57:
+    case 58:
     case PROPERTY_PATH:
     case INT_LITERAL:
     case FLOAT_LITERAL:
-      scalarNumericExpression();
+      numericExpression();
+      break;
+    case CONCAT:
+    case SUBSTRING:
+    case TRIM:
+    case LOWER:
+    case UPPER:
+    case SINGLE_QUOTED_STRING:
+    case DOUBLE_QUOTED_STRING:
+      stringExpression();
+      break;
+    case NULL:
+                  ASTScalar jjtn001 = new ASTScalar(JJTSCALAR);
+                  boolean jjtc001 = true;
+                  jjtree.openNodeScope(jjtn001);
+        try {
+          jj_consume_token(NULL);
+        } finally {
+                  if (jjtc001) {
+                    jjtree.closeNodeScope(jjtn001,  0);
+                  }
+      }
       break;
+    default:
+      jj_la1[14] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+  }
+
+  final public void stringParameter() throws ParseException {
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case 56:
+    case 57:
+    case 58:
+    case PROPERTY_PATH:
+      pathExpression();
+      break;
+    case CONCAT:
+    case SUBSTRING:
+    case TRIM:
+    case LOWER:
+    case UPPER:
+    case SINGLE_QUOTED_STRING:
+    case DOUBLE_QUOTED_STRING:
+      stringExpression();
+      break;
+    default:
+      jj_la1[15] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+  }
+
+  final public void stringExpression() throws ParseException {
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case SINGLE_QUOTED_STRING:
       jj_consume_token(SINGLE_QUOTED_STRING);
                                          ASTScalar jjtn001 = new ASTScalar(JJTSCALAR);
@@ -801,20 +880,15 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
                                          }
       }
       break;
-    case NULL:
-                  ASTScalar jjtn003 = new ASTScalar(JJTSCALAR);
-                  boolean jjtc003 = true;
-                  jjtree.openNodeScope(jjtn003);
-      try {
-        jj_consume_token(NULL);
-      } finally {
-                  if (jjtc003) {
-                    jjtree.closeNodeScope(jjtn003,  0);
-                  }
-      }
+    case CONCAT:
+    case SUBSTRING:
+    case TRIM:
+    case LOWER:
+    case UPPER:
+      functionsReturningStrings();
       break;
     default:
-      jj_la1[14] = jj_gen;
+      jj_la1[16] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
@@ -826,17 +900,27 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
     case 25:
     case 26:
     case 29:
-    case 30:
-    case 31:
-    case 32:
-    case 33:
     case NULL:
+    case CONCAT:
+    case SUBSTRING:
+    case TRIM:
+    case LOWER:
+    case UPPER:
+    case LENGTH:
+    case LOCATE:
+    case ABS:
+    case SQRT:
+    case MOD:
+    case 55:
+    case 56:
+    case 57:
+    case 58:
     case PROPERTY_PATH:
     case SINGLE_QUOTED_STRING:
     case DOUBLE_QUOTED_STRING:
     case INT_LITERAL:
     case FLOAT_LITERAL:
-      scalarConditionExpression();
+      conditionExpression();
       break;
     case TRUE:
       jj_consume_token(TRUE);
@@ -869,7 +953,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
       }
       break;
     default:
-      jj_la1[15] = jj_gen;
+      jj_la1[17] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
@@ -907,7 +991,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
                                    }
       }
       break;
-    case 30:
+    case 55:
       namedParameter();
       break;
     case INT_LITERAL:
@@ -971,13 +1055,13 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
       }
       break;
     default:
-      jj_la1[16] = jj_gen;
+      jj_la1[18] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
   }
 
-  final public void scalarNumericExpression() throws ParseException {
+  final public void numericExpression() throws ParseException {
     bitwiseOr();
   }
 
@@ -990,7 +1074,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
         ;
         break;
       default:
-        jj_la1[17] = jj_gen;
+        jj_la1[19] = jj_gen;
         break label_4;
       }
       jj_consume_token(20);
@@ -1030,7 +1114,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
         ;
         break;
       default:
-        jj_la1[18] = jj_gen;
+        jj_la1[20] = jj_gen;
         break label_5;
       }
       jj_consume_token(21);
@@ -1070,7 +1154,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
         ;
         break;
       default:
-        jj_la1[19] = jj_gen;
+        jj_la1[21] = jj_gen;
         break label_6;
       }
       jj_consume_token(22);
@@ -1111,7 +1195,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
         ;
         break;
       default:
-        jj_la1[20] = jj_gen;
+        jj_la1[22] = jj_gen;
         break label_7;
       }
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
@@ -1170,7 +1254,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
         }
         break;
       default:
-        jj_la1[21] = jj_gen;
+        jj_la1[23] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
       }
@@ -1187,7 +1271,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
         ;
         break;
       default:
-        jj_la1[22] = jj_gen;
+        jj_la1[24] = jj_gen;
         break label_8;
       }
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
@@ -1246,7 +1330,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
         }
         break;
       default:
-        jj_la1[23] = jj_gen;
+        jj_la1[25] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
       }
@@ -1263,7 +1347,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
         ;
         break;
       default:
-        jj_la1[24] = jj_gen;
+        jj_la1[26] = jj_gen;
         break label_9;
       }
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
@@ -1322,7 +1406,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
         }
         break;
       default:
-        jj_la1[25] = jj_gen;
+        jj_la1[27] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
       }
@@ -1334,10 +1418,15 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
     case 16:
     case 25:
     case 26:
-    case 30:
-    case 31:
-    case 32:
-    case 33:
+    case LENGTH:
+    case LOCATE:
+    case ABS:
+    case SQRT:
+    case MOD:
+    case 55:
+    case 56:
+    case 57:
+    case 58:
     case PROPERTY_PATH:
     case INT_LITERAL:
     case FLOAT_LITERAL:
@@ -1371,7 +1460,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
       }
       break;
     default:
-      jj_la1[26] = jj_gen;
+      jj_la1[28] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
@@ -1381,10 +1470,15 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case 16:
     case 25:
-    case 30:
-    case 31:
-    case 32:
-    case 33:
+    case LENGTH:
+    case LOCATE:
+    case ABS:
+    case SQRT:
+    case MOD:
+    case 55:
+    case 56:
+    case 57:
+    case 58:
     case PROPERTY_PATH:
     case INT_LITERAL:
     case FLOAT_LITERAL:
@@ -1393,7 +1487,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
         jj_consume_token(25);
         break;
       default:
-        jj_la1[27] = jj_gen;
+        jj_la1[29] = jj_gen;
         ;
       }
       numericPrimary();
@@ -1426,7 +1520,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
       }
       break;
     default:
-      jj_la1[28] = jj_gen;
+      jj_la1[30] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
@@ -1439,15 +1533,6 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
       orCondition();
       jj_consume_token(17);
       break;
-    case 31:
-    case 32:
-    case 33:
-    case PROPERTY_PATH:
-      pathExpression();
-      break;
-    case 30:
-      namedParameter();
-      break;
     case INT_LITERAL:
       jj_consume_token(INT_LITERAL);
                            ASTScalar jjtn001 = new ASTScalar(JJTSCALAR);
@@ -1478,16 +1563,416 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
                             }
       }
       break;
+    case 55:
+      namedParameter();
+      break;
+    case LENGTH:
+    case LOCATE:
+    case ABS:
+    case SQRT:
+    case MOD:
+      functionsReturningNumerics();
+      break;
+    case 56:
+    case 57:
+    case 58:
+    case PROPERTY_PATH:
+      pathExpression();
+      break;
+    default:
+      jj_la1[31] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+  }
+
+  final public void functionsReturningStrings() throws ParseException {
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case CONCAT:
+      concat();
+      break;
+    case SUBSTRING:
+      substring();
+      break;
+    case TRIM:
+      trim();
+      break;
+    case LOWER:
+      lower();
+      break;
+    case UPPER:
+      upper();
+      break;
     default:
-      jj_la1[29] = jj_gen;
+      jj_la1[32] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
   }
 
+  final public void concat() throws ParseException {
+                         /*@bgen(jjtree) Concat */
+  ASTConcat jjtn000 = new ASTConcat(JJTCONCAT);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+    try {
+      jj_consume_token(CONCAT);
+      jj_consume_token(16);
+      stringParameter();
+      jj_consume_token(19);
+      stringParameter();
+      jj_consume_token(17);
+    } 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 substring() throws ParseException {
+                               /*@bgen(jjtree) Substring */
+  ASTSubstring jjtn000 = new ASTSubstring(JJTSUBSTRING);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+    try {
+      jj_consume_token(SUBSTRING);
+      jj_consume_token(16);
+      stringParameter();
+      jj_consume_token(19);
+      numericExpression();
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case 19:
+        jj_consume_token(19);
+        numericExpression();
+        break;
+      default:
+        jj_la1[33] = jj_gen;
+        ;
+      }
+      jj_consume_token(17);
+    } 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 trim() throws ParseException {
+                     /*@bgen(jjtree) Trim */
+  ASTTrim jjtn000 = new ASTTrim(JJTTRIM);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+    try {
+      jj_consume_token(TRIM);
+      jj_consume_token(16);
+      stringParameter();
+      jj_consume_token(17);
+    } 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 lower() throws ParseException {
+                       /*@bgen(jjtree) Lower */
+  ASTLower jjtn000 = new ASTLower(JJTLOWER);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+    try {
+      jj_consume_token(LOWER);
+      jj_consume_token(16);
+      stringParameter();
+      jj_consume_token(17);
+    } 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 upper() throws ParseException {
+                       /*@bgen(jjtree) Upper */
+  ASTUpper jjtn000 = new ASTUpper(JJTUPPER);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+    try {
+      jj_consume_token(UPPER);
+      jj_consume_token(16);
+      stringParameter();
+      jj_consume_token(17);
+    } 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 functionsReturningNumerics() throws ParseException {
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case LENGTH:
+      length();
+      break;
+    case LOCATE:
+      locate();
+      break;
+    case ABS:
+      abs();
+      break;
+    case SQRT:
+      sqrt();
+      break;
+    case MOD:
+      mod();
+      break;
+    default:
+      jj_la1[34] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+  }
+
+  final public void length() throws ParseException {
+                         /*@bgen(jjtree) Length */
+  ASTLength jjtn000 = new ASTLength(JJTLENGTH);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+    try {
+      jj_consume_token(LENGTH);
+      jj_consume_token(16);
+      stringParameter();
+      jj_consume_token(17);
+    } 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 locate() throws ParseException {
+                         /*@bgen(jjtree) Locate */
+  ASTLocate jjtn000 = new ASTLocate(JJTLOCATE);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+    try {
+      jj_consume_token(LOCATE);
+      jj_consume_token(16);
+      stringParameter();
+      jj_consume_token(19);
+      stringParameter();
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case 19:
+        jj_consume_token(19);
+        numericExpression();
+        break;
+      default:
+        jj_la1[35] = jj_gen;
+        ;
+      }
+      jj_consume_token(17);
+    } 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 abs() throws ParseException {
+                   /*@bgen(jjtree) Abs */
+  ASTAbs jjtn000 = new ASTAbs(JJTABS);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+    try {
+      jj_consume_token(ABS);
+      jj_consume_token(16);
+      numericExpression();
+      jj_consume_token(17);
+    } 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 sqrt() throws ParseException {
+                     /*@bgen(jjtree) Sqrt */
+  ASTSqrt jjtn000 = new ASTSqrt(JJTSQRT);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+    try {
+      jj_consume_token(SQRT);
+      jj_consume_token(16);
+      numericExpression();
+      jj_consume_token(17);
+    } 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 mod() throws ParseException {
+                   /*@bgen(jjtree) Mod */
+  ASTMod jjtn000 = new ASTMod(JJTMOD);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+    try {
+      jj_consume_token(MOD);
+      jj_consume_token(16);
+      numericExpression();
+      jj_consume_token(19);
+      numericExpression();
+      jj_consume_token(17);
+    } 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 namedParameter() throws ParseException {
         Token t;
-    jj_consume_token(30);
+    jj_consume_token(55);
     t = jj_consume_token(PROPERTY_PATH);
                                   ASTNamedParameter jjtn001 = new ASTNamedParameter(JJTNAMEDPARAMETER);
                                   boolean jjtc001 = true;
@@ -1521,8 +2006,8 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
                            }
       }
       break;
-    case 31:
-      jj_consume_token(31);
+    case 56:
+      jj_consume_token(56);
       t = jj_consume_token(PROPERTY_PATH);
                            ASTObjPath jjtn002 = new ASTObjPath(JJTOBJPATH);
                            boolean jjtc002 = true;
@@ -1537,8 +2022,8 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
                            }
       }
       break;
-    case 32:
-      jj_consume_token(32);
+    case 57:
+      jj_consume_token(57);
       t = jj_consume_token(PROPERTY_PATH);
                            ASTDbPath jjtn003 = new ASTDbPath(JJTDBPATH);
                            boolean jjtc003 = true;
@@ -1553,8 +2038,8 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
                            }
       }
       break;
-    case 33:
-      jj_consume_token(33);
+    case 58:
+      jj_consume_token(58);
       t = jj_consume_token(PROPERTY_PATH);
                            ASTScalar jjtn004 = new ASTScalar(JJTSCALAR);
                            boolean jjtc004 = true;
@@ -1570,7 +2055,7 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
       }
       break;
     default:
-      jj_la1[30] = jj_gen;
+      jj_la1[36] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
@@ -1585,18 +2070,23 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
   public Token jj_nt;
   private int jj_ntk;
   private int jj_gen;
-  final private int[] jj_la1 = new int[31];
+  final private int[] jj_la1 = new int[37];
   static private int[] jj_la1_0;
   static private int[] jj_la1_1;
+  static private int[] jj_la1_2;
   static {
       jj_la1_init_0();
       jj_la1_init_1();
+      jj_la1_init_2();
    }
    private static void jj_la1_init_0() {
-      jj_la1_0 = new int[] {0x2,0x4,0x18,0xe6010018,0x60,0x180,0x40010000,0x4fff8,0x4fff8,0xe6010000,0x18,0x40010000,0x4e000,0x80000,0xe6010000,0xe6010000,0x40000000,0x100000,0x200000,0x400000,0x1800000,0x1800000,0x6000000,0x6000000,0x18000000,0x18000000,0xe6010000,0x2000000,0xc6010000,0xc0010000,0x80000000,};
+      jj_la1_0 = new int[] {0x2,0x4,0x18,0x26010018,0x60,0x180,0x10000,0x4fff8,0x4fff8,0x26010000,0x18,0x10000,0x4e000,0x80000,0x26010000,0x0,0x0,0x26010000,0x0,0x100000,0x200000,0x400000,0x1800000,0x1800000,0x6000000,0x6000000,0x18000000,0x18000000,0x26010000,0x2000000,0x6010000,0x10000,0x0,0x80000,0x0,0x80000,0x0,};
    }
    private static void jj_la1_init_1() {
-      jj_la1_1 = new int[] {0x0,0x0,0x0,0x7203c3,0x0,0x0,0x0,0x0,0x0,0x7203c3,0x0,0x0,0x0,0x0,0x720243,0x7203c3,0x720180,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600203,0x0,0x600203,0x600203,0x203,};
+      jj_la1_1 = new int[] {0x0,0x0,0x0,0xf8ffc1c,0x0,0x0,0x800000,0x0,0x0,0xf8ffc1c,0x0,0x800000,0x0,0x0,0xf8ffc04,0xf007c00,0x7c00,0xf8ffc1c,0x800018,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf8f8000,0x0,0xf8f8000,0xf8f8000,0x7c00,0x0,0xf8000,0x0,0xf000000,};
+   }
+   private static void jj_la1_init_2() {
+      jj_la1_2 = new int[] {0x0,0x0,0x0,0x1c8,0x0,0x0,0x0,0x0,0x0,0x1c8,0x0,0x0,0x0,0x0,0x1c8,0x48,0x48,0x1c8,0x1c8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x180,0x0,0x180,0x180,0x0,0x0,0x0,0x0,0x0,};
    }
 
   /** Constructor with InputStream. */
@@ -1610,7 +2100,22 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
     token = new Token();
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 31; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 37; 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 < 37; i++) jj_la1[i] = -1;
   }
 
   /** Constructor. */
@@ -1620,7 +2125,18 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
     token = new Token();
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 31; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 37; 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 < 37; i++) jj_la1[i] = -1;
   }
 
   /** Constructor with generated Token Manager. */
@@ -1629,7 +2145,17 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
     token = new Token();
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 31; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 37; i++) jj_la1[i] = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(ExpressionParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jjtree.reset();
+    jj_gen = 0;
+    for (int i = 0; i < 37; i++) jj_la1[i] = -1;
   }
 
   private Token jj_consume_token(int kind) throws ParseException {
@@ -1680,12 +2206,12 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
   /** Generate ParseException. */
   public ParseException generateParseException() {
     jj_expentries.clear();
-    boolean[] la1tokens = new boolean[59];
+    boolean[] la1tokens = new boolean[77];
     if (jj_kind >= 0) {
       la1tokens[jj_kind] = true;
       jj_kind = -1;
     }
-    for (int i = 0; i < 31; i++) {
+    for (int i = 0; i < 37; i++) {
       if (jj_la1[i] == jj_gen) {
         for (int j = 0; j < 32; j++) {
           if ((jj_la1_0[i] & (1<<j)) != 0) {
@@ -1694,10 +2220,13 @@ public class ExpressionParser/*@bgen(jjtree)*/implements ExpressionParserTreeCon
           if ((jj_la1_1[i] & (1<<j)) != 0) {
             la1tokens[32+j] = true;
           }
+          if ((jj_la1_2[i] & (1<<j)) != 0) {
+            la1tokens[64+j] = true;
+          }
         }
       }
     }
-    for (int i = 0; i < 59; i++) {
+    for (int i = 0; i < 77; i++) {
       if (la1tokens[i]) {
         jj_expentry = new int[1];
         jj_expentry[0] = i;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserConstants.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserConstants.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserConstants.java
index d8bf198..7d50af0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserConstants.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserConstants.java
@@ -31,39 +31,75 @@ public interface ExpressionParserConstants {
   /** End of File. */
   int EOF = 0;
   /** RegularExpression Id. */
-  int NULL = 38;
+  int NULL = 34;
   /** RegularExpression Id. */
-  int TRUE = 39;
+  int TRUE = 35;
   /** RegularExpression Id. */
-  int FALSE = 40;
+  int FALSE = 36;
   /** RegularExpression Id. */
-  int PROPERTY_PATH = 41;
+  int AVG = 37;
   /** RegularExpression Id. */
-  int IDENTIFIER = 42;
+  int MIN = 38;
   /** RegularExpression Id. */
-  int LETTER = 43;
+  int MAX = 39;
   /** RegularExpression Id. */
-  int DIGIT = 44;
+  int SUM = 40;
   /** RegularExpression Id. */
-  int ESC = 47;
+  int COUNT = 41;
   /** RegularExpression Id. */
-  int SINGLE_QUOTED_STRING = 49;
+  int CONCAT = 42;
   /** RegularExpression Id. */
-  int STRING_ESC = 50;
+  int SUBSTRING = 43;
   /** RegularExpression Id. */
-  int DOUBLE_QUOTED_STRING = 52;
+  int TRIM = 44;
   /** RegularExpression Id. */
-  int INT_LITERAL = 53;
+  int LOWER = 45;
   /** RegularExpression Id. */
-  int FLOAT_LITERAL = 54;
+  int UPPER = 46;
   /** RegularExpression Id. */
-  int DEC_FLT = 55;
+  int LENGTH = 47;
   /** RegularExpression Id. */
-  int DEC_DIGITS = 56;
+  int LOCATE = 48;
   /** RegularExpression Id. */
-  int EXPONENT = 57;
+  int ABS = 49;
   /** RegularExpression Id. */
-  int FLT_SUFF = 58;
+  int SQRT = 50;
+  /** RegularExpression Id. */
+  int MOD = 51;
+  /** RegularExpression Id. */
+  int CURRENT_DATE = 52;
+  /** RegularExpression Id. */
+  int CURRENT_TIME = 53;
+  /** RegularExpression Id. */
+  int CURRENT_TIMESTAMP = 54;
+  /** RegularExpression Id. */
+  int PROPERTY_PATH = 59;
+  /** RegularExpression Id. */
+  int IDENTIFIER = 60;
+  /** RegularExpression Id. */
+  int LETTER = 61;
+  /** RegularExpression Id. */
+  int DIGIT = 62;
+  /** RegularExpression Id. */
+  int ESC = 65;
+  /** RegularExpression Id. */
+  int SINGLE_QUOTED_STRING = 67;
+  /** RegularExpression Id. */
+  int STRING_ESC = 68;
+  /** RegularExpression Id. */
+  int DOUBLE_QUOTED_STRING = 70;
+  /** RegularExpression Id. */
+  int INT_LITERAL = 71;
+  /** RegularExpression Id. */
+  int FLOAT_LITERAL = 72;
+  /** RegularExpression Id. */
+  int DEC_FLT = 73;
+  /** RegularExpression Id. */
+  int DEC_DIGITS = 74;
+  /** RegularExpression Id. */
+  int EXPONENT = 75;
+  /** RegularExpression Id. */
+  int FLT_SUFF = 76;
 
   /** Lexical state. */
   int DEFAULT = 0;
@@ -104,10 +140,6 @@ public interface ExpressionParserConstants {
     "\"*\"",
     "\"/\"",
     "\"~\"",
-    "\"$\"",
-    "\"obj:\"",
-    "\"db:\"",
-    "\"enum:\"",
     "\" \"",
     "\"\\t\"",
     "\"\\n\"",
@@ -115,6 +147,28 @@ public interface ExpressionParserConstants {
     "<NULL>",
     "<TRUE>",
     "<FALSE>",
+    "\"AVG\"",
+    "\"MIN\"",
+    "\"MAX\"",
+    "\"SUM\"",
+    "\"COUNT\"",
+    "\"CONCAT\"",
+    "\"SUBSTRING\"",
+    "\"TRIM\"",
+    "\"LOWER\"",
+    "\"UPPER\"",
+    "\"LENGTH\"",
+    "\"LOCATE\"",
+    "\"ABS\"",
+    "\"SQRT\"",
+    "\"MOD\"",
+    "\"CURRENT_DATE\"",
+    "\"CURRENT_TIME\"",
+    "\"CURRENT_TIMESTAMP\"",
+    "\"$\"",
+    "\"obj:\"",
+    "\"db:\"",
+    "\"enum:\"",
     "<PROPERTY_PATH>",
     "<IDENTIFIER>",
     "<LETTER>",
@@ -122,10 +176,10 @@ public interface ExpressionParserConstants {
     "\"\\\'\"",
     "\"\\\"\"",
     "<ESC>",
-    "<token of kind 48>",
+    "<token of kind 66>",
     "\"\\\'\"",
     "<STRING_ESC>",
-    "<token of kind 51>",
+    "<token of kind 69>",
     "\"\\\"\"",
     "<INT_LITERAL>",
     "<FLOAT_LITERAL>",


[2/3] cayenne git commit: CAY-2196 Support for new function expressions in expression parser - updated and refactored grammar for parser - add token id to AST* function call nodes - escape in parse exception message - tests

Posted by nt...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTokenManager.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTokenManager.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTokenManager.java
index ad5e218..79285ff 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTokenManager.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTokenManager.java
@@ -101,140 +101,9 @@ public class ExpressionParserTokenManager implements ExpressionParserConstants
     }
 
   /** Debug output. */
-  public  java.io.PrintStream debugStream = System.out;
+  public  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 & 0x8L) != 0L)
-         {
-            jjmatchedKind = 41;
-            return 2;
-         }
-         if ((active0 & 0x38004e006L) != 0L)
-         {
-            jjmatchedKind = 41;
-            return 56;
-         }
-         return -1;
-      case 1:
-         if ((active0 & 0x38004600cL) != 0L)
-         {
-            jjmatchedKind = 41;
-            jjmatchedPos = 1;
-            return 56;
-         }
-         if ((active0 & 0x8002L) != 0L)
-            return 56;
-         return -1;
-      case 2:
-         if ((active0 & 0x280046000L) != 0L)
-         {
-            jjmatchedKind = 41;
-            jjmatchedPos = 2;
-            return 56;
-         }
-         if ((active0 & 0xcL) != 0L)
-            return 56;
-         return -1;
-      case 3:
-         if ((active0 & 0x200040000L) != 0L)
-         {
-            if (jjmatchedPos != 3)
-            {
-               jjmatchedKind = 41;
-               jjmatchedPos = 3;
-            }
-            return 56;
-         }
-         if ((active0 & 0x6000L) != 0L)
-            return 56;
-         return -1;
-      case 4:
-         if ((active0 & 0x44000L) != 0L)
-         {
-            jjmatchedKind = 41;
-            jjmatchedPos = 4;
-            return 56;
-         }
-         return -1;
-      case 5:
-         if ((active0 & 0x44000L) != 0L)
-         {
-            jjmatchedKind = 41;
-            jjmatchedPos = 5;
-            return 56;
-         }
-         return -1;
-      case 6:
-         if ((active0 & 0x4000L) != 0L)
-         {
-            jjmatchedKind = 41;
-            jjmatchedPos = 6;
-            return 56;
-         }
-         if ((active0 & 0x40000L) != 0L)
-            return 56;
-         return -1;
-      case 7:
-         if ((active0 & 0x4000L) != 0L)
-         {
-            jjmatchedKind = 41;
-            jjmatchedPos = 7;
-            return 56;
-         }
-         return -1;
-      case 8:
-         if ((active0 & 0x4000L) != 0L)
-         {
-            jjmatchedKind = 41;
-            jjmatchedPos = 8;
-            return 56;
-         }
-         return -1;
-      case 9:
-         if ((active0 & 0x4000L) != 0L)
-         {
-            jjmatchedKind = 41;
-            jjmatchedPos = 9;
-            return 56;
-         }
-         return -1;
-      case 10:
-         if ((active0 & 0x4000L) != 0L)
-         {
-            jjmatchedKind = 41;
-            jjmatchedPos = 10;
-            return 56;
-         }
-         return -1;
-      case 11:
-         if ((active0 & 0x4000L) != 0L)
-         {
-            jjmatchedKind = 41;
-            jjmatchedPos = 11;
-            return 56;
-         }
-         return -1;
-      case 12:
-         if ((active0 & 0x4000L) != 0L)
-         {
-            jjmatchedKind = 41;
-            jjmatchedPos = 12;
-            return 56;
-         }
-         return -1;
-      default :
-         return -1;
-   }
-}
-private final int jjStartNfa_0(int pos, long active0)
-{
-   return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
-}
+  public  void setDebugStream(PrintStream ds) { debugStream = ds; }
 private int jjStopAtPos(int pos, int kind)
 {
    jjmatchedKind = kind;
@@ -245,31 +114,54 @@ private int jjMoveStringLiteralDfa0_0()
 {
    switch(curChar)
    {
+      case 9:
+         jjmatchedKind = 31;
+         return jjMoveNfa_0(3, 0);
+      case 10:
+         jjmatchedKind = 32;
+         return jjMoveNfa_0(3, 0);
+      case 13:
+         jjmatchedKind = 33;
+         return jjMoveNfa_0(3, 0);
+      case 32:
+         jjmatchedKind = 30;
+         return jjMoveNfa_0(3, 0);
       case 33:
          jjmatchedKind = 4;
          return jjMoveStringLiteralDfa1_0(0x80L);
       case 34:
-         return jjStopAtPos(0, 46);
+         jjmatchedKind = 64;
+         return jjMoveNfa_0(3, 0);
       case 36:
-         return jjStopAtPos(0, 30);
+         jjmatchedKind = 55;
+         return jjMoveNfa_0(3, 0);
       case 38:
-         return jjStopAtPos(0, 22);
+         jjmatchedKind = 22;
+         return jjMoveNfa_0(3, 0);
       case 39:
-         return jjStopAtPos(0, 45);
+         jjmatchedKind = 63;
+         return jjMoveNfa_0(3, 0);
       case 40:
-         return jjStopAtPos(0, 16);
+         jjmatchedKind = 16;
+         return jjMoveNfa_0(3, 0);
       case 41:
-         return jjStopAtPos(0, 17);
+         jjmatchedKind = 17;
+         return jjMoveNfa_0(3, 0);
       case 42:
-         return jjStopAtPos(0, 27);
+         jjmatchedKind = 27;
+         return jjMoveNfa_0(3, 0);
       case 43:
-         return jjStopAtPos(0, 25);
+         jjmatchedKind = 25;
+         return jjMoveNfa_0(3, 0);
       case 44:
-         return jjStopAtPos(0, 19);
+         jjmatchedKind = 19;
+         return jjMoveNfa_0(3, 0);
       case 45:
-         return jjStopAtPos(0, 26);
+         jjmatchedKind = 26;
+         return jjMoveNfa_0(3, 0);
       case 47:
-         return jjStopAtPos(0, 28);
+         jjmatchedKind = 28;
+         return jjMoveNfa_0(3, 0);
       case 60:
          jjmatchedKind = 10;
          return jjMoveStringLiteralDfa1_0(0x800300L);
@@ -279,28 +171,55 @@ private int jjMoveStringLiteralDfa0_0()
       case 62:
          jjmatchedKind = 11;
          return jjMoveStringLiteralDfa1_0(0x1001000L);
+      case 65:
+         return jjMoveStringLiteralDfa1_0(0x2002000000000L);
+      case 67:
+         return jjMoveStringLiteralDfa1_0(0x70060000000000L);
+      case 76:
+         return jjMoveStringLiteralDfa1_0(0x1a00000000000L);
+      case 77:
+         return jjMoveStringLiteralDfa1_0(0x800c000000000L);
+      case 83:
+         return jjMoveStringLiteralDfa1_0(0x4090000000000L);
+      case 84:
+         return jjMoveStringLiteralDfa1_0(0x100000000000L);
+      case 85:
+         return jjMoveStringLiteralDfa1_0(0x400000000000L);
       case 94:
-         return jjStopAtPos(0, 21);
+         jjmatchedKind = 21;
+         return jjMoveNfa_0(3, 0);
       case 97:
-         return jjMoveStringLiteralDfa1_0(0x4L);
+         return jjMoveStringLiteralDfa1_0(0x2002000000004L);
       case 98:
          return jjMoveStringLiteralDfa1_0(0x40000L);
+      case 99:
+         return jjMoveStringLiteralDfa1_0(0x70060000000000L);
       case 100:
-         return jjMoveStringLiteralDfa1_0(0x100000000L);
+         return jjMoveStringLiteralDfa1_0(0x200000000000000L);
       case 101:
-         return jjMoveStringLiteralDfa1_0(0x200000000L);
+         return jjMoveStringLiteralDfa1_0(0x400000000000000L);
       case 105:
          return jjMoveStringLiteralDfa1_0(0x8000L);
       case 108:
-         return jjMoveStringLiteralDfa1_0(0x6000L);
+         return jjMoveStringLiteralDfa1_0(0x1a00000006000L);
+      case 109:
+         return jjMoveStringLiteralDfa1_0(0x800c000000000L);
       case 110:
          return jjMoveStringLiteralDfa1_0(0x8L);
       case 111:
-         return jjMoveStringLiteralDfa1_0(0x80000002L);
+         return jjMoveStringLiteralDfa1_0(0x100000000000002L);
+      case 115:
+         return jjMoveStringLiteralDfa1_0(0x4090000000000L);
+      case 116:
+         return jjMoveStringLiteralDfa1_0(0x100000000000L);
+      case 117:
+         return jjMoveStringLiteralDfa1_0(0x400000000000L);
       case 124:
-         return jjStopAtPos(0, 20);
+         jjmatchedKind = 20;
+         return jjMoveNfa_0(3, 0);
       case 126:
-         return jjStopAtPos(0, 29);
+         jjmatchedKind = 29;
+         return jjMoveNfa_0(3, 0);
       default :
          return jjMoveNfa_0(3, 0);
    }
@@ -308,320 +227,785 @@ private int jjMoveStringLiteralDfa0_0()
 private int jjMoveStringLiteralDfa1_0(long active0)
 {
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_0(0, active0);
-      return 1;
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 0);
    }
    switch(curChar)
    {
       case 60:
          if ((active0 & 0x800000L) != 0L)
-            return jjStopAtPos(1, 23);
+         {
+            jjmatchedKind = 23;
+            jjmatchedPos = 1;
+         }
          break;
       case 61:
          if ((active0 & 0x40L) != 0L)
-            return jjStopAtPos(1, 6);
+         {
+            jjmatchedKind = 6;
+            jjmatchedPos = 1;
+         }
          else if ((active0 & 0x80L) != 0L)
-            return jjStopAtPos(1, 7);
+         {
+            jjmatchedKind = 7;
+            jjmatchedPos = 1;
+         }
          else if ((active0 & 0x200L) != 0L)
-            return jjStopAtPos(1, 9);
+         {
+            jjmatchedKind = 9;
+            jjmatchedPos = 1;
+         }
          else if ((active0 & 0x1000L) != 0L)
-            return jjStopAtPos(1, 12);
+         {
+            jjmatchedKind = 12;
+            jjmatchedPos = 1;
+         }
          break;
       case 62:
          if ((active0 & 0x100L) != 0L)
-            return jjStopAtPos(1, 8);
+         {
+            jjmatchedKind = 8;
+            jjmatchedPos = 1;
+         }
          else if ((active0 & 0x1000000L) != 0L)
-            return jjStopAtPos(1, 24);
+         {
+            jjmatchedKind = 24;
+            jjmatchedPos = 1;
+         }
          break;
+      case 65:
+         return jjMoveStringLiteralDfa2_0(active0, 0x8000000000L);
+      case 66:
+         return jjMoveStringLiteralDfa2_0(active0, 0x2000000000000L);
+      case 69:
+         return jjMoveStringLiteralDfa2_0(active0, 0x800000000000L);
+      case 73:
+         return jjMoveStringLiteralDfa2_0(active0, 0x4000000000L);
+      case 79:
+         return jjMoveStringLiteralDfa2_0(active0, 0x9260000000000L);
+      case 80:
+         return jjMoveStringLiteralDfa2_0(active0, 0x400000000000L);
+      case 81:
+         return jjMoveStringLiteralDfa2_0(active0, 0x4000000000000L);
+      case 82:
+         return jjMoveStringLiteralDfa2_0(active0, 0x100000000000L);
+      case 85:
+         return jjMoveStringLiteralDfa2_0(active0, 0x70090000000000L);
+      case 86:
+         return jjMoveStringLiteralDfa2_0(active0, 0x2000000000L);
+      case 97:
+         return jjMoveStringLiteralDfa2_0(active0, 0x8000000000L);
       case 98:
-         return jjMoveStringLiteralDfa2_0(active0, 0x180000000L);
+         return jjMoveStringLiteralDfa2_0(active0, 0x302000000000000L);
       case 101:
-         return jjMoveStringLiteralDfa2_0(active0, 0x40000L);
+         return jjMoveStringLiteralDfa2_0(active0, 0x800000040000L);
       case 105:
-         return jjMoveStringLiteralDfa2_0(active0, 0x6000L);
+         return jjMoveStringLiteralDfa2_0(active0, 0x4000006000L);
       case 110:
          if ((active0 & 0x8000L) != 0L)
-            return jjStartNfaWithStates_0(1, 15, 56);
-         return jjMoveStringLiteralDfa2_0(active0, 0x200000004L);
+         {
+            jjmatchedKind = 15;
+            jjmatchedPos = 1;
+         }
+         return jjMoveStringLiteralDfa2_0(active0, 0x400000000000004L);
       case 111:
-         return jjMoveStringLiteralDfa2_0(active0, 0x8L);
+         return jjMoveStringLiteralDfa2_0(active0, 0x9260000000008L);
+      case 112:
+         return jjMoveStringLiteralDfa2_0(active0, 0x400000000000L);
+      case 113:
+         return jjMoveStringLiteralDfa2_0(active0, 0x4000000000000L);
       case 114:
          if ((active0 & 0x2L) != 0L)
-            return jjStartNfaWithStates_0(1, 1, 56);
-         break;
+         {
+            jjmatchedKind = 1;
+            jjmatchedPos = 1;
+         }
+         return jjMoveStringLiteralDfa2_0(active0, 0x100000000000L);
+      case 117:
+         return jjMoveStringLiteralDfa2_0(active0, 0x70090000000000L);
+      case 118:
+         return jjMoveStringLiteralDfa2_0(active0, 0x2000000000L);
       default :
          break;
    }
-   return jjStartNfa_0(0, active0);
+   return jjMoveNfa_0(3, 1);
 }
 private int jjMoveStringLiteralDfa2_0(long old0, long active0)
 {
    if (((active0 &= old0)) == 0L)
-      return jjStartNfa_0(0, old0);
+      return jjMoveNfa_0(3, 1);
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_0(1, active0);
-      return 2;
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 1);
    }
    switch(curChar)
    {
       case 58:
-         if ((active0 & 0x100000000L) != 0L)
-            return jjStopAtPos(2, 32);
+         if ((active0 & 0x200000000000000L) != 0L)
+         {
+            jjmatchedKind = 57;
+            jjmatchedPos = 2;
+         }
          break;
+      case 66:
+         return jjMoveStringLiteralDfa3_0(active0, 0x80000000000L);
+      case 67:
+         return jjMoveStringLiteralDfa3_0(active0, 0x1000000000000L);
+      case 68:
+         if ((active0 & 0x8000000000000L) != 0L)
+         {
+            jjmatchedKind = 51;
+            jjmatchedPos = 2;
+         }
+         break;
+      case 71:
+         if ((active0 & 0x2000000000L) != 0L)
+         {
+            jjmatchedKind = 37;
+            jjmatchedPos = 2;
+         }
+         break;
+      case 73:
+         return jjMoveStringLiteralDfa3_0(active0, 0x100000000000L);
+      case 77:
+         if ((active0 & 0x10000000000L) != 0L)
+         {
+            jjmatchedKind = 40;
+            jjmatchedPos = 2;
+         }
+         break;
+      case 78:
+         if ((active0 & 0x4000000000L) != 0L)
+         {
+            jjmatchedKind = 38;
+            jjmatchedPos = 2;
+         }
+         return jjMoveStringLiteralDfa3_0(active0, 0x840000000000L);
+      case 80:
+         return jjMoveStringLiteralDfa3_0(active0, 0x400000000000L);
+      case 82:
+         return jjMoveStringLiteralDfa3_0(active0, 0x74000000000000L);
+      case 83:
+         if ((active0 & 0x2000000000000L) != 0L)
+         {
+            jjmatchedKind = 49;
+            jjmatchedPos = 2;
+         }
+         break;
+      case 85:
+         return jjMoveStringLiteralDfa3_0(active0, 0x20000000000L);
+      case 87:
+         return jjMoveStringLiteralDfa3_0(active0, 0x200000000000L);
+      case 88:
+         if ((active0 & 0x8000000000L) != 0L)
+         {
+            jjmatchedKind = 39;
+            jjmatchedPos = 2;
+         }
+         break;
+      case 98:
+         return jjMoveStringLiteralDfa3_0(active0, 0x80000000000L);
+      case 99:
+         return jjMoveStringLiteralDfa3_0(active0, 0x1000000000000L);
       case 100:
          if ((active0 & 0x4L) != 0L)
-            return jjStartNfaWithStates_0(2, 2, 56);
+         {
+            jjmatchedKind = 2;
+            jjmatchedPos = 2;
+         }
+         else if ((active0 & 0x8000000000000L) != 0L)
+         {
+            jjmatchedKind = 51;
+            jjmatchedPos = 2;
+         }
          break;
+      case 103:
+         if ((active0 & 0x2000000000L) != 0L)
+         {
+            jjmatchedKind = 37;
+            jjmatchedPos = 2;
+         }
+         break;
+      case 105:
+         return jjMoveStringLiteralDfa3_0(active0, 0x100000000000L);
       case 106:
-         return jjMoveStringLiteralDfa3_0(active0, 0x80000000L);
+         return jjMoveStringLiteralDfa3_0(active0, 0x100000000000000L);
       case 107:
          return jjMoveStringLiteralDfa3_0(active0, 0x6000L);
+      case 109:
+         if ((active0 & 0x10000000000L) != 0L)
+         {
+            jjmatchedKind = 40;
+            jjmatchedPos = 2;
+         }
+         break;
+      case 110:
+         if ((active0 & 0x4000000000L) != 0L)
+         {
+            jjmatchedKind = 38;
+            jjmatchedPos = 2;
+         }
+         return jjMoveStringLiteralDfa3_0(active0, 0x840000000000L);
+      case 112:
+         return jjMoveStringLiteralDfa3_0(active0, 0x400000000000L);
+      case 114:
+         return jjMoveStringLiteralDfa3_0(active0, 0x74000000000000L);
+      case 115:
+         if ((active0 & 0x2000000000000L) != 0L)
+         {
+            jjmatchedKind = 49;
+            jjmatchedPos = 2;
+         }
+         break;
       case 116:
          if ((active0 & 0x8L) != 0L)
-            return jjStartNfaWithStates_0(2, 3, 56);
+         {
+            jjmatchedKind = 3;
+            jjmatchedPos = 2;
+         }
          return jjMoveStringLiteralDfa3_0(active0, 0x40000L);
       case 117:
-         return jjMoveStringLiteralDfa3_0(active0, 0x200000000L);
+         return jjMoveStringLiteralDfa3_0(active0, 0x400020000000000L);
+      case 119:
+         return jjMoveStringLiteralDfa3_0(active0, 0x200000000000L);
+      case 120:
+         if ((active0 & 0x8000000000L) != 0L)
+         {
+            jjmatchedKind = 39;
+            jjmatchedPos = 2;
+         }
+         break;
       default :
          break;
    }
-   return jjStartNfa_0(1, active0);
+   return jjMoveNfa_0(3, 2);
 }
 private int jjMoveStringLiteralDfa3_0(long old0, long active0)
 {
    if (((active0 &= old0)) == 0L)
-      return jjStartNfa_0(1, old0);
+      return jjMoveNfa_0(3, 2);
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_0(2, active0);
-      return 3;
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 2);
    }
    switch(curChar)
    {
       case 58:
-         if ((active0 & 0x80000000L) != 0L)
-            return jjStopAtPos(3, 31);
+         if ((active0 & 0x100000000000000L) != 0L)
+         {
+            jjmatchedKind = 56;
+            jjmatchedPos = 3;
+         }
+         break;
+      case 65:
+         return jjMoveStringLiteralDfa4_0(active0, 0x1000000000000L);
+      case 67:
+         return jjMoveStringLiteralDfa4_0(active0, 0x40000000000L);
+      case 69:
+         return jjMoveStringLiteralDfa4_0(active0, 0x600000000000L);
+      case 71:
+         return jjMoveStringLiteralDfa4_0(active0, 0x800000000000L);
+      case 77:
+         if ((active0 & 0x100000000000L) != 0L)
+         {
+            jjmatchedKind = 44;
+            jjmatchedPos = 3;
+         }
+         break;
+      case 78:
+         return jjMoveStringLiteralDfa4_0(active0, 0x20000000000L);
+      case 82:
+         return jjMoveStringLiteralDfa4_0(active0, 0x70000000000000L);
+      case 83:
+         return jjMoveStringLiteralDfa4_0(active0, 0x80000000000L);
+      case 84:
+         if ((active0 & 0x4000000000000L) != 0L)
+         {
+            jjmatchedKind = 50;
+            jjmatchedPos = 3;
+         }
          break;
+      case 97:
+         return jjMoveStringLiteralDfa4_0(active0, 0x1000000000000L);
+      case 99:
+         return jjMoveStringLiteralDfa4_0(active0, 0x40000000000L);
       case 101:
          if ((active0 & 0x2000L) != 0L)
          {
             jjmatchedKind = 13;
             jjmatchedPos = 3;
          }
-         return jjMoveStringLiteralDfa4_0(active0, 0x4000L);
+         return jjMoveStringLiteralDfa4_0(active0, 0x600000004000L);
+      case 103:
+         return jjMoveStringLiteralDfa4_0(active0, 0x800000000000L);
       case 109:
-         return jjMoveStringLiteralDfa4_0(active0, 0x200000000L);
+         if ((active0 & 0x100000000000L) != 0L)
+         {
+            jjmatchedKind = 44;
+            jjmatchedPos = 3;
+         }
+         return jjMoveStringLiteralDfa4_0(active0, 0x400000000000000L);
+      case 110:
+         return jjMoveStringLiteralDfa4_0(active0, 0x20000000000L);
+      case 114:
+         return jjMoveStringLiteralDfa4_0(active0, 0x70000000000000L);
+      case 115:
+         return jjMoveStringLiteralDfa4_0(active0, 0x80000000000L);
+      case 116:
+         if ((active0 & 0x4000000000000L) != 0L)
+         {
+            jjmatchedKind = 50;
+            jjmatchedPos = 3;
+         }
+         break;
       case 119:
          return jjMoveStringLiteralDfa4_0(active0, 0x40000L);
       default :
          break;
    }
-   return jjStartNfa_0(2, active0);
+   return jjMoveNfa_0(3, 3);
 }
 private int jjMoveStringLiteralDfa4_0(long old0, long active0)
 {
    if (((active0 &= old0)) == 0L)
-      return jjStartNfa_0(2, old0);
+      return jjMoveNfa_0(3, 3);
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_0(3, active0);
-      return 4;
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 3);
    }
    switch(curChar)
    {
       case 58:
-         if ((active0 & 0x200000000L) != 0L)
-            return jjStopAtPos(4, 33);
+         if ((active0 & 0x400000000000000L) != 0L)
+         {
+            jjmatchedKind = 58;
+            jjmatchedPos = 4;
+         }
          break;
+      case 65:
+         return jjMoveStringLiteralDfa5_0(active0, 0x40000000000L);
+      case 69:
+         return jjMoveStringLiteralDfa5_0(active0, 0x70000000000000L);
       case 73:
          return jjMoveStringLiteralDfa5_0(active0, 0x4000L);
+      case 82:
+         if ((active0 & 0x200000000000L) != 0L)
+         {
+            jjmatchedKind = 45;
+            jjmatchedPos = 4;
+         }
+         else if ((active0 & 0x400000000000L) != 0L)
+         {
+            jjmatchedKind = 46;
+            jjmatchedPos = 4;
+         }
+         break;
+      case 84:
+         if ((active0 & 0x20000000000L) != 0L)
+         {
+            jjmatchedKind = 41;
+            jjmatchedPos = 4;
+         }
+         return jjMoveStringLiteralDfa5_0(active0, 0x1880000000000L);
+      case 97:
+         return jjMoveStringLiteralDfa5_0(active0, 0x40000000000L);
       case 101:
-         return jjMoveStringLiteralDfa5_0(active0, 0x40000L);
+         return jjMoveStringLiteralDfa5_0(active0, 0x70000000040000L);
+      case 114:
+         if ((active0 & 0x200000000000L) != 0L)
+         {
+            jjmatchedKind = 45;
+            jjmatchedPos = 4;
+         }
+         else if ((active0 & 0x400000000000L) != 0L)
+         {
+            jjmatchedKind = 46;
+            jjmatchedPos = 4;
+         }
+         break;
+      case 116:
+         if ((active0 & 0x20000000000L) != 0L)
+         {
+            jjmatchedKind = 41;
+            jjmatchedPos = 4;
+         }
+         return jjMoveStringLiteralDfa5_0(active0, 0x1880000000000L);
       default :
          break;
    }
-   return jjStartNfa_0(3, active0);
+   return jjMoveNfa_0(3, 4);
 }
 private int jjMoveStringLiteralDfa5_0(long old0, long active0)
 {
    if (((active0 &= old0)) == 0L)
-      return jjStartNfa_0(3, old0);
+      return jjMoveNfa_0(3, 4);
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_0(4, active0);
-      return 5;
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 4);
    }
    switch(curChar)
    {
+      case 69:
+         if ((active0 & 0x1000000000000L) != 0L)
+         {
+            jjmatchedKind = 48;
+            jjmatchedPos = 5;
+         }
+         break;
+      case 72:
+         if ((active0 & 0x800000000000L) != 0L)
+         {
+            jjmatchedKind = 47;
+            jjmatchedPos = 5;
+         }
+         break;
+      case 78:
+         return jjMoveStringLiteralDfa6_0(active0, 0x70000000000000L);
+      case 82:
+         return jjMoveStringLiteralDfa6_0(active0, 0x80000000000L);
+      case 84:
+         if ((active0 & 0x40000000000L) != 0L)
+         {
+            jjmatchedKind = 42;
+            jjmatchedPos = 5;
+         }
+         break;
       case 101:
+         if ((active0 & 0x1000000000000L) != 0L)
+         {
+            jjmatchedKind = 48;
+            jjmatchedPos = 5;
+         }
          return jjMoveStringLiteralDfa6_0(active0, 0x40000L);
       case 103:
          return jjMoveStringLiteralDfa6_0(active0, 0x4000L);
+      case 104:
+         if ((active0 & 0x800000000000L) != 0L)
+         {
+            jjmatchedKind = 47;
+            jjmatchedPos = 5;
+         }
+         break;
+      case 110:
+         return jjMoveStringLiteralDfa6_0(active0, 0x70000000000000L);
+      case 114:
+         return jjMoveStringLiteralDfa6_0(active0, 0x80000000000L);
+      case 116:
+         if ((active0 & 0x40000000000L) != 0L)
+         {
+            jjmatchedKind = 42;
+            jjmatchedPos = 5;
+         }
+         break;
       default :
          break;
    }
-   return jjStartNfa_0(4, active0);
+   return jjMoveNfa_0(3, 5);
 }
 private int jjMoveStringLiteralDfa6_0(long old0, long active0)
 {
    if (((active0 &= old0)) == 0L)
-      return jjStartNfa_0(4, old0);
+      return jjMoveNfa_0(3, 5);
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_0(5, active0);
-      return 6;
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 5);
    }
    switch(curChar)
    {
+      case 73:
+         return jjMoveStringLiteralDfa7_0(active0, 0x80000000000L);
+      case 84:
+         return jjMoveStringLiteralDfa7_0(active0, 0x70000000000000L);
+      case 105:
+         return jjMoveStringLiteralDfa7_0(active0, 0x80000000000L);
       case 110:
          if ((active0 & 0x40000L) != 0L)
-            return jjStartNfaWithStates_0(6, 18, 56);
+         {
+            jjmatchedKind = 18;
+            jjmatchedPos = 6;
+         }
          return jjMoveStringLiteralDfa7_0(active0, 0x4000L);
+      case 116:
+         return jjMoveStringLiteralDfa7_0(active0, 0x70000000000000L);
       default :
          break;
    }
-   return jjStartNfa_0(5, active0);
+   return jjMoveNfa_0(3, 6);
 }
 private int jjMoveStringLiteralDfa7_0(long old0, long active0)
 {
    if (((active0 &= old0)) == 0L)
-      return jjStartNfa_0(5, old0);
+      return jjMoveNfa_0(3, 6);
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_0(6, active0);
-      return 7;
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 6);
    }
    switch(curChar)
    {
+      case 78:
+         return jjMoveStringLiteralDfa8_0(active0, 0x80000000000L);
+      case 95:
+         return jjMoveStringLiteralDfa8_0(active0, 0x70000000000000L);
+      case 110:
+         return jjMoveStringLiteralDfa8_0(active0, 0x80000000000L);
       case 111:
          return jjMoveStringLiteralDfa8_0(active0, 0x4000L);
       default :
          break;
    }
-   return jjStartNfa_0(6, active0);
+   return jjMoveNfa_0(3, 7);
 }
 private int jjMoveStringLiteralDfa8_0(long old0, long active0)
 {
    if (((active0 &= old0)) == 0L)
-      return jjStartNfa_0(6, old0);
+      return jjMoveNfa_0(3, 7);
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_0(7, active0);
-      return 8;
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 7);
    }
    switch(curChar)
    {
+      case 68:
+         return jjMoveStringLiteralDfa9_0(active0, 0x10000000000000L);
+      case 71:
+         if ((active0 & 0x80000000000L) != 0L)
+         {
+            jjmatchedKind = 43;
+            jjmatchedPos = 8;
+         }
+         break;
+      case 84:
+         return jjMoveStringLiteralDfa9_0(active0, 0x60000000000000L);
+      case 100:
+         return jjMoveStringLiteralDfa9_0(active0, 0x10000000000000L);
+      case 103:
+         if ((active0 & 0x80000000000L) != 0L)
+         {
+            jjmatchedKind = 43;
+            jjmatchedPos = 8;
+         }
+         break;
       case 114:
          return jjMoveStringLiteralDfa9_0(active0, 0x4000L);
+      case 116:
+         return jjMoveStringLiteralDfa9_0(active0, 0x60000000000000L);
       default :
          break;
    }
-   return jjStartNfa_0(7, active0);
+   return jjMoveNfa_0(3, 8);
 }
 private int jjMoveStringLiteralDfa9_0(long old0, long active0)
 {
    if (((active0 &= old0)) == 0L)
-      return jjStartNfa_0(7, old0);
+      return jjMoveNfa_0(3, 8);
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_0(8, active0);
-      return 9;
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 8);
    }
    switch(curChar)
    {
+      case 65:
+         return jjMoveStringLiteralDfa10_0(active0, 0x10000000000000L);
+      case 73:
+         return jjMoveStringLiteralDfa10_0(active0, 0x60000000000000L);
+      case 97:
+         return jjMoveStringLiteralDfa10_0(active0, 0x10000000000000L);
       case 101:
          return jjMoveStringLiteralDfa10_0(active0, 0x4000L);
+      case 105:
+         return jjMoveStringLiteralDfa10_0(active0, 0x60000000000000L);
       default :
          break;
    }
-   return jjStartNfa_0(8, active0);
+   return jjMoveNfa_0(3, 9);
 }
 private int jjMoveStringLiteralDfa10_0(long old0, long active0)
 {
    if (((active0 &= old0)) == 0L)
-      return jjStartNfa_0(8, old0);
+      return jjMoveNfa_0(3, 9);
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_0(9, active0);
-      return 10;
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 9);
    }
    switch(curChar)
    {
       case 67:
          return jjMoveStringLiteralDfa11_0(active0, 0x4000L);
+      case 77:
+         return jjMoveStringLiteralDfa11_0(active0, 0x60000000000000L);
+      case 84:
+         return jjMoveStringLiteralDfa11_0(active0, 0x10000000000000L);
+      case 109:
+         return jjMoveStringLiteralDfa11_0(active0, 0x60000000000000L);
+      case 116:
+         return jjMoveStringLiteralDfa11_0(active0, 0x10000000000000L);
       default :
          break;
    }
-   return jjStartNfa_0(9, active0);
+   return jjMoveNfa_0(3, 10);
 }
 private int jjMoveStringLiteralDfa11_0(long old0, long active0)
 {
    if (((active0 &= old0)) == 0L)
-      return jjStartNfa_0(9, old0);
+      return jjMoveNfa_0(3, 10);
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_0(10, active0);
-      return 11;
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 10);
    }
    switch(curChar)
    {
+      case 69:
+         if ((active0 & 0x10000000000000L) != 0L)
+         {
+            jjmatchedKind = 52;
+            jjmatchedPos = 11;
+         }
+         else if ((active0 & 0x20000000000000L) != 0L)
+         {
+            jjmatchedKind = 53;
+            jjmatchedPos = 11;
+         }
+         return jjMoveStringLiteralDfa12_0(active0, 0x40000000000000L);
       case 97:
          return jjMoveStringLiteralDfa12_0(active0, 0x4000L);
+      case 101:
+         if ((active0 & 0x10000000000000L) != 0L)
+         {
+            jjmatchedKind = 52;
+            jjmatchedPos = 11;
+         }
+         else if ((active0 & 0x20000000000000L) != 0L)
+         {
+            jjmatchedKind = 53;
+            jjmatchedPos = 11;
+         }
+         return jjMoveStringLiteralDfa12_0(active0, 0x40000000000000L);
       default :
          break;
    }
-   return jjStartNfa_0(10, active0);
+   return jjMoveNfa_0(3, 11);
 }
 private int jjMoveStringLiteralDfa12_0(long old0, long active0)
 {
    if (((active0 &= old0)) == 0L)
-      return jjStartNfa_0(10, old0);
+      return jjMoveNfa_0(3, 11);
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_0(11, active0);
-      return 12;
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 11);
    }
    switch(curChar)
    {
+      case 83:
+         return jjMoveStringLiteralDfa13_0(active0, 0x40000000000000L);
       case 115:
-         return jjMoveStringLiteralDfa13_0(active0, 0x4000L);
+         return jjMoveStringLiteralDfa13_0(active0, 0x40000000004000L);
       default :
          break;
    }
-   return jjStartNfa_0(11, active0);
+   return jjMoveNfa_0(3, 12);
 }
 private int jjMoveStringLiteralDfa13_0(long old0, long active0)
 {
    if (((active0 &= old0)) == 0L)
-      return jjStartNfa_0(11, old0);
+      return jjMoveNfa_0(3, 12);
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_0(12, active0);
-      return 13;
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 12);
    }
    switch(curChar)
    {
+      case 84:
+         return jjMoveStringLiteralDfa14_0(active0, 0x40000000000000L);
       case 101:
          if ((active0 & 0x4000L) != 0L)
-            return jjStartNfaWithStates_0(13, 14, 56);
+         {
+            jjmatchedKind = 14;
+            jjmatchedPos = 13;
+         }
          break;
+      case 116:
+         return jjMoveStringLiteralDfa14_0(active0, 0x40000000000000L);
       default :
          break;
    }
-   return jjStartNfa_0(12, active0);
+   return jjMoveNfa_0(3, 13);
 }
-private int jjStartNfaWithStates_0(int pos, int kind, int state)
+private int jjMoveStringLiteralDfa14_0(long old0, long active0)
 {
-   jjmatchedKind = kind;
-   jjmatchedPos = pos;
+   if (((active0 &= old0)) == 0L)
+      return jjMoveNfa_0(3, 13);
+   try { curChar = input_stream.readChar(); }
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 13);
+   }
+   switch(curChar)
+   {
+      case 65:
+         return jjMoveStringLiteralDfa15_0(active0, 0x40000000000000L);
+      case 97:
+         return jjMoveStringLiteralDfa15_0(active0, 0x40000000000000L);
+      default :
+         break;
+   }
+   return jjMoveNfa_0(3, 14);
+}
+private int jjMoveStringLiteralDfa15_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjMoveNfa_0(3, 14);
    try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) { return pos + 1; }
-   return jjMoveNfa_0(state, pos + 1);
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 14);
+   }
+   switch(curChar)
+   {
+      case 77:
+         return jjMoveStringLiteralDfa16_0(active0, 0x40000000000000L);
+      case 109:
+         return jjMoveStringLiteralDfa16_0(active0, 0x40000000000000L);
+      default :
+         break;
+   }
+   return jjMoveNfa_0(3, 15);
+}
+private int jjMoveStringLiteralDfa16_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjMoveNfa_0(3, 15);
+   try { curChar = input_stream.readChar(); }
+   catch(IOException e) {
+   return jjMoveNfa_0(3, 15);
+   }
+   switch(curChar)
+   {
+      case 80:
+         if ((active0 & 0x40000000000000L) != 0L)
+         {
+            jjmatchedKind = 54;
+            jjmatchedPos = 16;
+         }
+         break;
+      case 112:
+         if ((active0 & 0x40000000000000L) != 0L)
+         {
+            jjmatchedKind = 54;
+            jjmatchedPos = 16;
+         }
+         break;
+      default :
+         break;
+   }
+   return jjMoveNfa_0(3, 16);
 }
 private int jjMoveNfa_0(int startState, int curPos)
 {
+   int strKind = jjmatchedKind;
+   int strPos = jjmatchedPos;
+   int seenUpto;
+   input_stream.backup(seenUpto = curPos + 1);
+   try { curChar = input_stream.readChar(); }
+   catch(IOException e) { throw new Error("Internal Error"); }
+   curPos = 0;
    int startsAt = 0;
    jjnewStateCnt = 56;
    int i = 1;
@@ -638,90 +1022,36 @@ private int jjMoveNfa_0(int startState, int curPos)
          {
             switch(jjstateSet[--i])
             {
-               case 56:
-                  if ((0x3ff000000000000L & l) != 0L)
-                  {
-                     if (kind > 42)
-                        kind = 42;
-                     jjCheckNAddTwoStates(54, 55);
-                  }
-                  else if (curChar == 43)
-                  {
-                     if (kind > 42)
-                        kind = 42;
-                  }
-                  else if (curChar == 46)
-                     jjstateSet[jjnewStateCnt++] = 52;
-                  if ((0x3ff000000000000L & l) != 0L)
-                  {
-                     if (kind > 41)
-                        kind = 41;
-                     jjCheckNAddStates(0, 2);
-                  }
-                  else if (curChar == 43)
-                  {
-                     if (kind > 41)
-                        kind = 41;
-                     jjCheckNAdd(51);
-                  }
-                  break;
                case 3:
                   if ((0x3ff000000000000L & l) != 0L)
-                     jjCheckNAddStates(3, 8);
+                     jjCheckNAddStates(0, 5);
                   else if (curChar == 46)
                      jjCheckNAdd(30);
                   if ((0x3fe000000000000L & l) != 0L)
                   {
-                     if (kind > 53)
-                        kind = 53;
+                     if (kind > 71)
+                        kind = 71;
                      jjCheckNAddTwoStates(27, 28);
                   }
                   else if (curChar == 48)
                   {
-                     if (kind > 53)
-                        kind = 53;
-                     jjCheckNAddStates(9, 11);
-                  }
-                  break;
-               case 2:
-                  if ((0x3ff000000000000L & l) != 0L)
-                  {
-                     if (kind > 42)
-                        kind = 42;
-                     jjCheckNAddTwoStates(54, 55);
-                  }
-                  else if (curChar == 43)
-                  {
-                     if (kind > 42)
-                        kind = 42;
-                  }
-                  else if (curChar == 46)
-                     jjstateSet[jjnewStateCnt++] = 52;
-                  if ((0x3ff000000000000L & l) != 0L)
-                  {
-                     if (kind > 41)
-                        kind = 41;
-                     jjCheckNAddStates(0, 2);
-                  }
-                  else if (curChar == 43)
-                  {
-                     if (kind > 41)
-                        kind = 41;
-                     jjCheckNAdd(51);
+                     if (kind > 71)
+                        kind = 71;
+                     jjCheckNAddStates(6, 8);
                   }
                   break;
                case 26:
                   if ((0x3fe000000000000L & l) == 0L)
                      break;
-                  if (kind > 53)
-                     kind = 53;
+                  if (kind > 71)
+                     kind = 71;
                   jjCheckNAddTwoStates(27, 28);
                   break;
                case 27:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 53)
-                     kind = 53;
+                  if (kind > 71)
+                     kind = 71;
                   jjCheckNAddTwoStates(27, 28);
                   break;
                case 29:
@@ -731,9 +1061,9 @@ private int jjMoveNfa_0(int startState, int curPos)
                case 30:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 54)
-                     kind = 54;
-                  jjCheckNAddStates(12, 14);
+                  if (kind > 72)
+                     kind = 72;
+                  jjCheckNAddStates(9, 11);
                   break;
                case 32:
                   if ((0x280000000000L & l) != 0L)
@@ -742,13 +1072,13 @@ private int jjMoveNfa_0(int startState, int curPos)
                case 33:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 54)
-                     kind = 54;
+                  if (kind > 72)
+                     kind = 72;
                   jjCheckNAddTwoStates(33, 34);
                   break;
                case 35:
                   if ((0x3ff000000000000L & l) != 0L)
-                     jjCheckNAddStates(3, 8);
+                     jjCheckNAddStates(0, 5);
                   break;
                case 36:
                   if ((0x3ff000000000000L & l) != 0L)
@@ -757,16 +1087,16 @@ private int jjMoveNfa_0(int startState, int curPos)
                case 37:
                   if (curChar != 46)
                      break;
-                  if (kind > 54)
-                     kind = 54;
-                  jjCheckNAddStates(15, 17);
+                  if (kind > 72)
+                     kind = 72;
+                  jjCheckNAddStates(12, 14);
                   break;
                case 38:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 54)
-                     kind = 54;
-                  jjCheckNAddStates(15, 17);
+                  if (kind > 72)
+                     kind = 72;
+                  jjCheckNAddStates(12, 14);
                   break;
                case 39:
                   if ((0x3ff000000000000L & l) != 0L)
@@ -779,8 +1109,8 @@ private int jjMoveNfa_0(int startState, int curPos)
                case 42:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 54)
-                     kind = 54;
+                  if (kind > 72)
+                     kind = 72;
                   jjCheckNAddTwoStates(42, 34);
                   break;
                case 43:
@@ -790,36 +1120,36 @@ private int jjMoveNfa_0(int startState, int curPos)
                case 44:
                   if (curChar != 48)
                      break;
-                  if (kind > 53)
-                     kind = 53;
-                  jjCheckNAddStates(9, 11);
+                  if (kind > 71)
+                     kind = 71;
+                  jjCheckNAddStates(6, 8);
                   break;
                case 45:
                   if ((0xff000000000000L & l) == 0L)
                      break;
-                  if (kind > 53)
-                     kind = 53;
+                  if (kind > 71)
+                     kind = 71;
                   jjCheckNAddTwoStates(45, 28);
                   break;
                case 47:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 53)
-                     kind = 53;
+                  if (kind > 71)
+                     kind = 71;
                   jjCheckNAddTwoStates(47, 28);
                   break;
                case 49:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 41)
-                     kind = 41;
-                  jjCheckNAddStates(0, 2);
+                  if (kind > 59)
+                     kind = 59;
+                  jjCheckNAddStates(15, 17);
                   break;
                case 50:
                   if (curChar != 43)
                      break;
-                  if (kind > 41)
-                     kind = 41;
+                  if (kind > 59)
+                     kind = 59;
                   jjCheckNAdd(51);
                   break;
                case 51:
@@ -829,20 +1159,20 @@ private int jjMoveNfa_0(int startState, int curPos)
                case 53:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 41)
-                     kind = 41;
+                  if (kind > 59)
+                     kind = 59;
                   jjCheckNAddStates(18, 20);
                   break;
                case 54:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 42)
-                     kind = 42;
-                  jjCheckNAddTwoStates(54, 55);
+                  if (kind > 60)
+                     kind = 60;
+                  jjAddStates(21, 22);
                   break;
                case 55:
-                  if (curChar == 43 && kind > 42)
-                     kind = 42;
+                  if (curChar == 43 && kind > 60)
+                     kind = 60;
                   break;
                default : break;
             }
@@ -855,26 +1185,12 @@ private int jjMoveNfa_0(int startState, int curPos)
          {
             switch(jjstateSet[--i])
             {
-               case 56:
-                  if ((0x7fffffe87fffffeL & l) != 0L)
-                  {
-                     if (kind > 42)
-                        kind = 42;
-                     jjCheckNAddTwoStates(54, 55);
-                  }
-                  if ((0x7fffffe87fffffeL & l) != 0L)
-                  {
-                     if (kind > 41)
-                        kind = 41;
-                     jjCheckNAddStates(0, 2);
-                  }
-                  break;
                case 3:
                   if ((0x7fffffe87fffffeL & l) != 0L)
                   {
-                     if (kind > 41)
-                        kind = 41;
-                     jjCheckNAddStates(21, 25);
+                     if (kind > 59)
+                        kind = 59;
+                     jjCheckNAddStates(23, 27);
                   }
                   if (curChar == 70)
                      jjstateSet[jjnewStateCnt++] = 24;
@@ -889,33 +1205,21 @@ private int jjMoveNfa_0(int startState, int curPos)
                   else if (curChar == 110)
                      jjstateSet[jjnewStateCnt++] = 2;
                   break;
-               case 2:
-                  if ((0x7fffffe87fffffeL & l) != 0L)
-                  {
-                     if (kind > 42)
-                        kind = 42;
-                     jjCheckNAddTwoStates(54, 55);
-                  }
-                  if ((0x7fffffe87fffffeL & l) != 0L)
-                  {
-                     if (kind > 41)
-                        kind = 41;
-                     jjCheckNAddStates(0, 2);
-                  }
-                  if (curChar == 117)
-                     jjstateSet[jjnewStateCnt++] = 1;
-                  break;
                case 0:
-                  if (curChar == 108 && kind > 38)
-                     kind = 38;
+                  if (curChar == 108 && kind > 34)
+                     kind = 34;
                   break;
                case 1:
                   if (curChar == 108)
                      jjstateSet[jjnewStateCnt++] = 0;
                   break;
+               case 2:
+                  if (curChar == 117)
+                     jjstateSet[jjnewStateCnt++] = 1;
+                  break;
                case 4:
-                  if (curChar == 76 && kind > 38)
-                     kind = 38;
+                  if (curChar == 76 && kind > 34)
+                     kind = 34;
                   break;
                case 5:
                   if (curChar == 76)
@@ -930,8 +1234,8 @@ private int jjMoveNfa_0(int startState, int curPos)
                      jjstateSet[jjnewStateCnt++] = 6;
                   break;
                case 8:
-                  if (curChar == 101 && kind > 39)
-                     kind = 39;
+                  if (curChar == 101 && kind > 35)
+                     kind = 35;
                   break;
                case 9:
                   if (curChar == 117)
@@ -946,8 +1250,8 @@ private int jjMoveNfa_0(int startState, int curPos)
                      jjstateSet[jjnewStateCnt++] = 10;
                   break;
                case 12:
-                  if (curChar == 69 && kind > 39)
-                     kind = 39;
+                  if (curChar == 69 && kind > 35)
+                     kind = 35;
                   break;
                case 13:
                   if (curChar == 85)
@@ -962,8 +1266,8 @@ private int jjMoveNfa_0(int startState, int curPos)
                      jjstateSet[jjnewStateCnt++] = 14;
                   break;
                case 16:
-                  if (curChar == 101 && kind > 40)
-                     kind = 40;
+                  if (curChar == 101 && kind > 36)
+                     kind = 36;
                   break;
                case 17:
                   if (curChar == 115)
@@ -982,8 +1286,8 @@ private int jjMoveNfa_0(int startState, int curPos)
                      jjstateSet[jjnewStateCnt++] = 19;
                   break;
                case 21:
-                  if (curChar == 69 && kind > 40)
-                     kind = 40;
+                  if (curChar == 69 && kind > 36)
+                     kind = 36;
                   break;
                case 22:
                   if (curChar == 83)
@@ -1002,20 +1306,20 @@ private int jjMoveNfa_0(int startState, int curPos)
                      jjstateSet[jjnewStateCnt++] = 24;
                   break;
                case 28:
-                  if ((0x110000001100L & l) != 0L && kind > 53)
-                     kind = 53;
+                  if ((0x110000001100L & l) != 0L && kind > 71)
+                     kind = 71;
                   break;
                case 31:
                   if ((0x2000000020L & l) != 0L)
-                     jjAddStates(26, 27);
+                     jjAddStates(28, 29);
                   break;
                case 34:
-                  if ((0x5400000054L & l) != 0L && kind > 54)
-                     kind = 54;
+                  if ((0x5400000054L & l) != 0L && kind > 72)
+                     kind = 72;
                   break;
                case 40:
                   if ((0x2000000020L & l) != 0L)
-                     jjAddStates(28, 29);
+                     jjAddStates(30, 31);
                   break;
                case 46:
                   if ((0x100000001000000L & l) != 0L)
@@ -1024,37 +1328,37 @@ private int jjMoveNfa_0(int startState, int curPos)
                case 47:
                   if ((0x7e0000007eL & l) == 0L)
                      break;
-                  if (kind > 53)
-                     kind = 53;
+                  if (kind > 71)
+                     kind = 71;
                   jjCheckNAddTwoStates(47, 28);
                   break;
                case 48:
                   if ((0x7fffffe87fffffeL & l) == 0L)
                      break;
-                  if (kind > 41)
-                     kind = 41;
-                  jjCheckNAddStates(21, 25);
+                  if (kind > 59)
+                     kind = 59;
+                  jjCheckNAddStates(23, 27);
                   break;
                case 49:
                   if ((0x7fffffe87fffffeL & l) == 0L)
                      break;
-                  if (kind > 41)
-                     kind = 41;
-                  jjCheckNAddStates(0, 2);
+                  if (kind > 59)
+                     kind = 59;
+                  jjCheckNAddStates(15, 17);
                   break;
                case 52:
                case 53:
                   if ((0x7fffffe87fffffeL & l) == 0L)
                      break;
-                  if (kind > 41)
-                     kind = 41;
+                  if (kind > 59)
+                     kind = 59;
                   jjCheckNAddStates(18, 20);
                   break;
                case 54:
                   if ((0x7fffffe87fffffeL & l) == 0L)
                      break;
-                  if (kind > 42)
-                     kind = 42;
+                  if (kind > 60)
+                     kind = 60;
                   jjCheckNAddTwoStates(54, 55);
                   break;
                default : break;
@@ -1084,12 +1388,31 @@ private int jjMoveNfa_0(int startState, int curPos)
       }
       ++curPos;
       if ((i = jjnewStateCnt) == (startsAt = 56 - (jjnewStateCnt = startsAt)))
-         return curPos;
+         break;
       try { curChar = input_stream.readChar(); }
-      catch(java.io.IOException e) { return curPos; }
+      catch(IOException e) { break; }
    }
+   if (jjmatchedPos > strPos)
+      return curPos;
+
+   int toRet = Math.max(curPos, seenUpto);
+
+   if (curPos < toRet)
+      for (i = toRet - Math.min(curPos, seenUpto); i-- > 0; )
+         try { curChar = input_stream.readChar(); }
+         catch(IOException e) { throw new Error("Internal Error : Please send a bug report."); }
+
+   if (jjmatchedPos < strPos)
+   {
+      jjmatchedKind = strKind;
+      jjmatchedPos = strPos;
+   }
+   else if (jjmatchedPos == strPos && jjmatchedKind > strKind)
+      jjmatchedKind = strKind;
+
+   return toRet;
 }
-private final int jjStopStringLiteralDfa_1(int pos, long active0)
+private final int jjStopStringLiteralDfa_1(int pos, long active0, long active1)
 {
    switch (pos)
    {
@@ -1097,16 +1420,16 @@ private final int jjStopStringLiteralDfa_1(int pos, long active0)
          return -1;
    }
 }
-private final int jjStartNfa_1(int pos, long active0)
+private final int jjStartNfa_1(int pos, long active0, long active1)
 {
-   return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1);
+   return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0, active1), pos + 1);
 }
 private int jjMoveStringLiteralDfa0_1()
 {
    switch(curChar)
    {
       case 39:
-         return jjStopAtPos(0, 49);
+         return jjStopAtPos(0, 67);
       default :
          return jjMoveNfa_1(0, 0);
    }
@@ -1136,12 +1459,12 @@ private int jjMoveNfa_1(int startState, int curPos)
             switch(jjstateSet[--i])
             {
                case 0:
-                  if ((0xffffff7fffffffffL & l) != 0L && kind > 48)
-                     kind = 48;
+                  if ((0xffffff7fffffffffL & l) != 0L && kind > 66)
+                     kind = 66;
                   break;
                case 1:
-                  if ((0x8400000000L & l) != 0L && kind > 47)
-                     kind = 47;
+                  if ((0x8400000000L & l) != 0L && kind > 65)
+                     kind = 65;
                   break;
                case 2:
                   if ((0xf000000000000L & l) != 0L)
@@ -1150,13 +1473,13 @@ private int jjMoveNfa_1(int startState, int curPos)
                case 3:
                   if ((0xff000000000000L & l) == 0L)
                      break;
-                  if (kind > 47)
-                     kind = 47;
+                  if (kind > 65)
+                     kind = 65;
                   jjstateSet[jjnewStateCnt++] = 4;
                   break;
                case 4:
-                  if ((0xff000000000000L & l) != 0L && kind > 47)
-                     kind = 47;
+                  if ((0xff000000000000L & l) != 0L && kind > 65)
+                     kind = 65;
                   break;
                default : break;
             }
@@ -1172,19 +1495,19 @@ private int jjMoveNfa_1(int startState, int curPos)
                case 0:
                   if ((0xffffffffefffffffL & l) != 0L)
                   {
-                     if (kind > 48)
-                        kind = 48;
+                     if (kind > 66)
+                        kind = 66;
                   }
                   else if (curChar == 92)
-                     jjAddStates(30, 32);
+                     jjAddStates(32, 34);
                   break;
                case 1:
-                  if ((0x14404510000000L & l) != 0L && kind > 47)
-                     kind = 47;
+                  if ((0x14404510000000L & l) != 0L && kind > 65)
+                     kind = 65;
                   break;
                case 5:
-                  if ((0xffffffffefffffffL & l) != 0L && kind > 48)
-                     kind = 48;
+                  if ((0xffffffffefffffffL & l) != 0L && kind > 66)
+                     kind = 66;
                   break;
                default : break;
             }
@@ -1202,8 +1525,8 @@ private int jjMoveNfa_1(int startState, int curPos)
             switch(jjstateSet[--i])
             {
                case 0:
-                  if (jjCanMove_0(hiByte, i1, i2, l1, l2) && kind > 48)
-                     kind = 48;
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2) && kind > 66)
+                     kind = 66;
                   break;
                default : break;
             }
@@ -1219,10 +1542,10 @@ private int jjMoveNfa_1(int startState, int curPos)
       if ((i = jjnewStateCnt) == (startsAt = 6 - (jjnewStateCnt = startsAt)))
          return curPos;
       try { curChar = input_stream.readChar(); }
-      catch(java.io.IOException e) { return curPos; }
+      catch(IOException e) { return curPos; }
    }
 }
-private final int jjStopStringLiteralDfa_2(int pos, long active0)
+private final int jjStopStringLiteralDfa_2(int pos, long active0, long active1)
 {
    switch (pos)
    {
@@ -1230,16 +1553,16 @@ private final int jjStopStringLiteralDfa_2(int pos, long active0)
          return -1;
    }
 }
-private final int jjStartNfa_2(int pos, long active0)
+private final int jjStartNfa_2(int pos, long active0, long active1)
 {
-   return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
+   return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0, active1), pos + 1);
 }
 private int jjMoveStringLiteralDfa0_2()
 {
    switch(curChar)
    {
       case 34:
-         return jjStopAtPos(0, 52);
+         return jjStopAtPos(0, 70);
       default :
          return jjMoveNfa_2(0, 0);
    }
@@ -1263,12 +1586,12 @@ private int jjMoveNfa_2(int startState, int curPos)
             switch(jjstateSet[--i])
             {
                case 0:
-                  if ((0xfffffffbffffffffL & l) != 0L && kind > 51)
-                     kind = 51;
+                  if ((0xfffffffbffffffffL & l) != 0L && kind > 69)
+                     kind = 69;
                   break;
                case 1:
-                  if ((0x8400000000L & l) != 0L && kind > 50)
-                     kind = 50;
+                  if ((0x8400000000L & l) != 0L && kind > 68)
+                     kind = 68;
                   break;
                case 2:
                   if ((0xf000000000000L & l) != 0L)
@@ -1277,13 +1600,13 @@ private int jjMoveNfa_2(int startState, int curPos)
                case 3:
                   if ((0xff000000000000L & l) == 0L)
                      break;
-                  if (kind > 50)
-                     kind = 50;
+                  if (kind > 68)
+                     kind = 68;
                   jjstateSet[jjnewStateCnt++] = 4;
                   break;
                case 4:
-                  if ((0xff000000000000L & l) != 0L && kind > 50)
-                     kind = 50;
+                  if ((0xff000000000000L & l) != 0L && kind > 68)
+                     kind = 68;
                   break;
                default : break;
             }
@@ -1299,19 +1622,19 @@ private int jjMoveNfa_2(int startState, int curPos)
                case 0:
                   if ((0xffffffffefffffffL & l) != 0L)
                   {
-                     if (kind > 51)
-                        kind = 51;
+                     if (kind > 69)
+                        kind = 69;
                   }
                   else if (curChar == 92)
-                     jjAddStates(30, 32);
+                     jjAddStates(32, 34);
                   break;
                case 1:
-                  if ((0x14404510000000L & l) != 0L && kind > 50)
-                     kind = 50;
+                  if ((0x14404510000000L & l) != 0L && kind > 68)
+                     kind = 68;
                   break;
                case 5:
-                  if ((0xffffffffefffffffL & l) != 0L && kind > 51)
-                     kind = 51;
+                  if ((0xffffffffefffffffL & l) != 0L && kind > 69)
+                     kind = 69;
                   break;
                default : break;
             }
@@ -1329,8 +1652,8 @@ private int jjMoveNfa_2(int startState, int curPos)
             switch(jjstateSet[--i])
             {
                case 0:
-                  if (jjCanMove_0(hiByte, i1, i2, l1, l2) && kind > 51)
-                     kind = 51;
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2) && kind > 69)
+                     kind = 69;
                   break;
                default : break;
             }
@@ -1346,13 +1669,13 @@ private int jjMoveNfa_2(int startState, int curPos)
       if ((i = jjnewStateCnt) == (startsAt = 6 - (jjnewStateCnt = startsAt)))
          return curPos;
       try { curChar = input_stream.readChar(); }
-      catch(java.io.IOException e) { return curPos; }
+      catch(IOException e) { return curPos; }
    }
 }
 static final int[] jjnextStates = {
-   49, 50, 51, 36, 37, 39, 40, 43, 34, 45, 46, 28, 30, 31, 34, 38, 
-   31, 34, 51, 53, 50, 49, 50, 51, 54, 55, 32, 33, 41, 42, 1, 2, 
-   3, 
+   36, 37, 39, 40, 43, 34, 45, 46, 28, 30, 31, 34, 38, 31, 34, 49, 
+   50, 51, 51, 53, 50, 54, 55, 49, 50, 51, 54, 55, 32, 33, 41, 42, 
+   1, 2, 3, 
 };
 private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
 {
@@ -1372,10 +1695,11 @@ public static final String[] jjstrLiteralImages = {
 "", "\157\162", "\141\156\144", "\156\157\164", "\41", "\75", "\75\75", 
 "\41\75", "\74\76", "\74\75", "\74", "\76", "\76\75", "\154\151\153\145", 
 "\154\151\153\145\111\147\156\157\162\145\103\141\163\145", "\151\156", "\50", "\51", "\142\145\164\167\145\145\156", "\54", "\174", 
-"\136", "\46", "\74\74", "\76\76", "\53", "\55", "\52", "\57", "\176", "\44", 
-"\157\142\152\72", "\144\142\72", "\145\156\165\155\72", null, null, null, null, null, null, null, 
+"\136", "\46", "\74\74", "\76\76", "\53", "\55", "\52", "\57", "\176", null, null, 
 null, null, null, null, null, null, null, null, null, null, null, null, null, null, 
-null, null, null, null, };
+null, null, null, null, null, null, null, null, null, "\44", "\157\142\152\72", 
+"\144\142\72", "\145\156\165\155\72", null, null, null, null, null, null, null, null, null, 
+null, null, null, null, null, null, null, null, null, };
 
 /** Lexer state names. */
 public static final String[] lexStateNames = {
@@ -1387,17 +1711,18 @@ public static final String[] lexStateNames = {
 /** 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, -1, -1, -1, -1, -1, -1, -1, 
-   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, -1, -1, 0, 
-   -1, -1, 0, -1, -1, -1, -1, -1, -1, 
+   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, -1, -1, 0, -1, -1, 0, -1, -1, -1, -1, 
+   -1, -1, 
 };
 static final long[] jjtoToken = {
-   0x7207c3ffffffffL, 
+   0x1ffffffc3fffffffL, 0x1c8L, 
 };
 static final long[] jjtoSkip = {
-   0x3c00000000L, 
+   0x3c0000000L, 0x0L, 
 };
 static final long[] jjtoMore = {
-   0xde00000000000L, 
+   0x8000000000000000L, 0x37L, 
 };
 protected JavaCharStream input_stream;
 private final int[] jjrounds = new int[56];
@@ -1496,7 +1821,7 @@ public Token getNextToken()
    {
       curChar = input_stream.BeginToken();
    }
-   catch(java.io.IOException e)
+   catch(IOException e)
    {
       jjmatchedKind = 0;
       matchedToken = jjFillToken();
@@ -1511,11 +1836,6 @@ public Token getNextToken()
      switch(curLexState)
      {
        case 0:
-         try { input_stream.backup(0);
-            while (curChar <= 32 && (0x100002600L & (1L << curChar)) != 0L)
-               curChar = input_stream.BeginToken();
-         }
-         catch (java.io.IOException e1) { continue EOFLoop; }
          jjmatchedKind = 0x7fffffff;
          jjmatchedPos = 0;
          curPos = jjMoveStringLiteralDfa0_0();
@@ -1558,14 +1878,14 @@ public Token getNextToken()
            curChar = input_stream.readChar();
            continue;
         }
-        catch (java.io.IOException e1) { }
+        catch (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) {
+     catch (IOException e1) {
         EOFSeen = true;
         error_after = curPos <= 1 ? "" : input_stream.GetImage();
         if (curChar == '\n' || curChar == '\r') {
@@ -1589,32 +1909,32 @@ void MoreLexicalActions()
    jjimageLen += (lengthOfMatch = jjmatchedPos + 1);
    switch(jjmatchedKind)
    {
-      case 45 :
+      case 63 :
          image.append(input_stream.GetSuffix(jjimageLen));
          jjimageLen = 0;
            stringBuffer = new StringBuffer();
          break;
-      case 46 :
+      case 64 :
          image.append(input_stream.GetSuffix(jjimageLen));
          jjimageLen = 0;
             stringBuffer = new StringBuffer();
          break;
-      case 47 :
+      case 65 :
          image.append(input_stream.GetSuffix(jjimageLen));
          jjimageLen = 0;
           stringBuffer.append( escapeChar() );
          break;
-      case 48 :
+      case 66 :
          image.append(input_stream.GetSuffix(jjimageLen));
          jjimageLen = 0;
           stringBuffer.append( image.charAt(image.length()-1) );
          break;
-      case 50 :
+      case 68 :
          image.append(input_stream.GetSuffix(jjimageLen));
          jjimageLen = 0;
           stringBuffer.append( escapeChar() );
          break;
-      case 51 :
+      case 69 :
          image.append(input_stream.GetSuffix(jjimageLen));
          jjimageLen = 0;
           stringBuffer.append( image.charAt(image.length()-1) );
@@ -1627,19 +1947,19 @@ void TokenLexicalActions(Token matchedToken)
 {
    switch(jjmatchedKind)
    {
-      case 49 :
+      case 67 :
         image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
           literalValue = stringBuffer.toString();
          break;
-      case 52 :
+      case 70 :
         image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
           literalValue = stringBuffer.toString();
          break;
-      case 53 :
+      case 71 :
         image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
           literalValue = makeInt();
          break;
-      case 54 :
+      case 72 :
         image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
           literalValue = makeFloat();
          break;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTreeConstants.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTreeConstants.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTreeConstants.java
index 2a4aefa..62fa5a3 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTreeConstants.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ExpressionParserTreeConstants.java
@@ -1,4 +1,23 @@
 /* Generated By:JavaCC: Do not edit this line. ExpressionParserTreeConstants.java Version 5.0 */
+/*****************************************************************
+ *   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.exp.parser;
 
 public interface ExpressionParserTreeConstants
@@ -36,9 +55,19 @@ public interface ExpressionParserTreeConstants
   public int JJTDIVIDE = 30;
   public int JJTBITWISENOT = 31;
   public int JJTNEGATE = 32;
-  public int JJTNAMEDPARAMETER = 33;
-  public int JJTOBJPATH = 34;
-  public int JJTDBPATH = 35;
+  public int JJTCONCAT = 33;
+  public int JJTSUBSTRING = 34;
+  public int JJTTRIM = 35;
+  public int JJTLOWER = 36;
+  public int JJTUPPER = 37;
+  public int JJTLENGTH = 38;
+  public int JJTLOCATE = 39;
+  public int JJTABS = 40;
+  public int JJTSQRT = 41;
+  public int JJTMOD = 42;
+  public int JJTNAMEDPARAMETER = 43;
+  public int JJTOBJPATH = 44;
+  public int JJTDBPATH = 45;
 
 
   public String[] jjtNodeName = {
@@ -75,9 +104,19 @@ public interface ExpressionParserTreeConstants
     "Divide",
     "BitwiseNot",
     "Negate",
+    "Concat",
+    "Substring",
+    "Trim",
+    "Lower",
+    "Upper",
+    "Length",
+    "Locate",
+    "Abs",
+    "Sqrt",
+    "Mod",
     "NamedParameter",
     "ObjPath",
     "DbPath",
   };
 }
-/* JavaCC - OriginalChecksum=c9c4fb7fe11d6ed9456e027ce61531d5 (do not edit this line) */
+/* JavaCC - OriginalChecksum=3658f423e33338225cd28f666e76c706 (do not edit this line) */

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c44ccfde/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JJTExpressionParserState.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JJTExpressionParserState.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JJTExpressionParserState.java
index 349ac96..aab8be9 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JJTExpressionParserState.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/JJTExpressionParserState.java
@@ -1,4 +1,23 @@
 /* Generated By:JavaCC: Do not edit this line. JJTExpressionParserState.java Version 5.0 */
+/*****************************************************************
+ *   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.exp.parser;
 
 public class JJTExpressionParserState {