diff --git a/pom.xml b/pom.xml
index 47c6b9c..98fe796 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,7 +1,9 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<properties>
-		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>	
+		<currentDevelopmentVersion>6.1.0</currentDevelopmentVersion>
+		<currentDevelopmentRelease>20160802</currentDevelopmentRelease>	
 	</properties>
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>dev.meertens.mtas</groupId>
@@ -23,11 +25,11 @@
 	<developers>
 		<developer>
 			<name>Matthijs Brouwer</name>
-			<url>https://www.meertens.knaw.nl/cms/nl/medewerkers/144373-matthijsb</url>
+			<url>https://nl.linkedin.com/in/brouwermatthijs/</url>
 		</developer>
 		<developer>
 			<name>Marc Kemps-Snijders</name>
-			<url>https://www.meertens.knaw.nl/cms/nl/medewerkers/143329-marck</url>
+			<url>https://nl.linkedin.com/in/marc-kemps-snijders-1b33753</url>
 		</developer>
 	</developers>
 	<build>
@@ -64,7 +66,7 @@
 						<addMavenDescriptor>false</addMavenDescriptor>
 					</archive>
 				</configuration>
-			</plugin>			
+			</plugin>						
 		</plugins>
 	</build>
 	<reporting>
diff --git a/src/mtas/analysis/parser/MtasCRMParser.java b/src/mtas/analysis/parser/MtasCRMParser.java
index 677dfb4..e5fac31 100644
--- a/src/mtas/analysis/parser/MtasCRMParser.java
+++ b/src/mtas/analysis/parser/MtasCRMParser.java
@@ -18,6 +18,9 @@ import mtas.analysis.util.MtasConfigException;
 import mtas.analysis.util.MtasConfiguration;
 import mtas.analysis.util.MtasParserException;
 
+/**
+ * The Class MtasCRMParser.
+ */
 public class MtasCRMParser extends MtasBasicParser {
 
   /** The word type. */
@@ -26,8 +29,14 @@ public class MtasCRMParser extends MtasBasicParser {
   /** The word annotation types. */
   private HashMap<String, MtasParserType> wordAnnotationTypes = new HashMap<String, MtasParserType>();
 
+  /** The functions. */
   private HashMap<String, MtasCRMParserFunction> functions = new HashMap<String, MtasCRMParserFunction>();
 
+  /**
+   * Instantiates a new mtas crm parser.
+   *
+   * @param config the config
+   */
   public MtasCRMParser(MtasConfiguration config) {
     super(config);
     try {
@@ -38,6 +47,9 @@ public class MtasCRMParser extends MtasBasicParser {
     }
   }
 
+  /* (non-Javadoc)
+   * @see mtas.analysis.parser.MtasParser#initParser()
+   */
   @Override
   protected void initParser() throws MtasConfigException {
     super.initParser();
@@ -128,6 +140,9 @@ public class MtasCRMParser extends MtasBasicParser {
     }
   }
 
+  /* (non-Javadoc)
+   * @see mtas.analysis.parser.MtasParser#createTokenCollection(java.io.Reader)
+   */
   @Override
   public MtasTokenCollection createTokenCollection(Reader reader)
       throws MtasParserException, MtasConfigException {
@@ -252,6 +267,22 @@ public class MtasCRMParser extends MtasBasicParser {
 
   }
 
+  /**
+   * Process word annotation.
+   *
+   * @param name the name
+   * @param text the text
+   * @param previousOffset the previous offset
+   * @param currentOffset the current offset
+   * @param functionOutputList the function output list
+   * @param unknownAncestors the unknown ancestors
+   * @param currentList the current list
+   * @param updateList the update list
+   * @param idPositions the id positions
+   * @param idOffsets the id offsets
+   * @throws MtasParserException the mtas parser exception
+   * @throws MtasConfigException the mtas config exception
+   */
   private void processWordAnnotation(String name, String text,
       Integer previousOffset, Integer currentOffset,
       ArrayList<MtasCRMParserFunctionOutput> functionOutputList,
@@ -318,6 +349,9 @@ public class MtasCRMParser extends MtasBasicParser {
     }
   }
 
+  /* (non-Javadoc)
+   * @see mtas.analysis.parser.MtasParser#printConfig()
+   */
   @Override
   public String printConfig() {
     String text = "";
@@ -328,6 +362,12 @@ public class MtasCRMParser extends MtasBasicParser {
     return text;
   }
 
+  /**
+   * Prints the config types.
+   *
+   * @param types the types
+   * @return the string
+   */
   private String printConfigTypes(HashMap<?, MtasParserType> types) {
     String text = "";
     for (Entry<?, MtasParserType> entry : types.entrySet()) {
@@ -340,12 +380,25 @@ public class MtasCRMParser extends MtasBasicParser {
     return text;
   }
 
+  /**
+   * The Class MtasCRMParserFunction.
+   */
   private class MtasCRMParserFunction {
 
+    /** The type. */
     public String type;
+    
+    /** The split. */
     public String split;
+    
+    /** The output. */
     public HashMap<String, ArrayList<MtasCRMParserFunctionOutput>> output;
 
+    /**
+     * Instantiates a new mtas crm parser function.
+     *
+     * @param split the split
+     */
     public MtasCRMParserFunction(String split) {
       this.split = split;
       output = new HashMap<String, ArrayList<MtasCRMParserFunctionOutput>>();
@@ -353,21 +406,37 @@ public class MtasCRMParser extends MtasBasicParser {
 
   }
 
+  /**
+   * The Class MtasCRMParserFunctionOutput.
+   */
   private class MtasCRMParserFunctionOutput {
+    
+    /** The name. */
     public String name;
+    
+    /** The value. */
     public String value;
 
+    /**
+     * Instantiates a new mtas crm parser function output.
+     *
+     * @param name the name
+     * @param value the value
+     */
     public MtasCRMParserFunctionOutput(String name, String value) {
       this.name = name;
       this.value = value;
     }
   }
 
+  /**
+   * The Class MtasCRMParserMappingWordAnnotation.
+   */
   private class MtasCRMParserMappingWordAnnotation
       extends MtasParserMapping<MtasCRMParserMappingWordAnnotation> {
 
     /**
-     * Instantiates a new mtas sketch parser mapping word annotation.
+     * Instantiates a new mtas crm parser mapping word annotation.
      */
     public MtasCRMParserMappingWordAnnotation() {
       super();
diff --git a/src/mtas/codec/MtasFieldsConsumer.java b/src/mtas/codec/MtasFieldsConsumer.java
index 53efda5..5f3a494 100644
--- a/src/mtas/codec/MtasFieldsConsumer.java
+++ b/src/mtas/codec/MtasFieldsConsumer.java
@@ -45,277 +45,6 @@ import org.apache.solr.update.processor.LogUpdateProcessorFactory;
 
 /**
  * The Class MtasFieldsConsumer.
- *
- * 
- * The Class MtasFieldsConsumer constructs several temporal and permanent files
- * to provide a forward index
- *
- * <ul>
- * <li><b>Temporary files</b><br>
- * <ul>
- * <li><b>Temporary file {@link #mtasTmpFieldFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_TMP_FIELD_EXTENSION} </b><br>
- * Contains for each field a reference to the list of documents. Structure of
- * content:
- * <ul>
- * <li><b>String</b>: field</li>
- * <li><b>VLong</b>: reference to {@link #mtasDocFileName}</li>
- * <li><b>VInt</b>: number of documents</li>
- * <li><b>VLong</b>: reference to {@link #mtasTermFileName}</li>
- * <li><b>VInt</b>: number of terms</li>
- * <li><b>VLong</b>: reference to {@link #mtasPrefixFileName}</li>
- * <li><b>VInt</b>: number of prefixes</li>
- * </ul>
- * </li>
- * <li><b>Temporary file {@link #mtasTmpObjectFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_TMP_OBJECT_EXTENSION}</b><br>
- * Contains for a specific field all objects constructed by
- * {@link createObjectAndRegisterPrefix}. For all fields, the objects are later
- * on copied to {@link #mtasObjectFileName} while statistics are collected.
- * Structure of content identical to {@link #mtasObjectFileName}.</li>
- * <li><b>Temporary file {@link #mtasTmpDocsFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_TMP_DOCS_EXTENSION}</b> <br>
- * Contains for a specific field for each doc multiple fragments. Each occurring
- * term results in a fragment. Structure of content:
- * <ul>
- * <li><b>VInt</b>: docId</li>
- * <li><b>VInt</b>: number of objects in this fragment</li>
- * <li><b>VLong</b>: offset references to {@link #mtasTmpObjectFileName}</li>
- * <li><b>VInt</b>,<b>VLong</b>: mtasId object, reference temporary object in
- * {@link #mtasTmpObjectFileName} minus offset</li>
- * <li><b>VInt</b>,<b>VLong</b>: ...</li>
- * </ul>
- * </li>
- * <li><b>Temporary file {@link #mtasTmpDocsChainedFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_TMP_DOCS_CHAINED_EXTENSION}
- * </b><br>
- * Contains for a specific field for each doc multiple chained fragments.
- * Structure of content:
- * <ul>
- * <li><b>VInt</b>: docId</li>
- * <li><b>VInt</b>: number of objects in this fragment</li>
- * <li><b>VLong</b>: offset references to {@link #mtasTmpObjectFileName}</li>
- * <li><b>VInt</b>,<b>VLong</b>: mtasId object, reference temporary object in
- * {@link #mtasTmpObjectFileName} minus offset</li>
- * <li><b>VInt</b>,<b>VLong</b>: ...</li>
- * <li><b>VLong</b>: reference to next fragment in
- * {@link #mtasTmpDocsChainedFileName}, self reference indicates end of chain
- * </ul>
- * </li>
- * <li><b>Temporary file {@link #mtasTmpDocFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_TMP_DOC_EXTENSION}</b><br>
- * For each document
- * <ul>
- * <li><b>VInt</b>: docId</li>
- * <li><b>VLong</b>: reference to {@link #mtasIndexObjectIdFileName}</li>
- * <li><b>VLong</b>: reference first object, used as offset for tree index
- * <li><b>VInt</b>: slope used in approximation reference objects index on id
- * </li>
- * <li><b>ZLong</b>: offset used in approximation reference objects index on id
- * </li>
- * <li><b>Byte</b>: flag indicating how corrections on the approximation
- * references objects for the index on id are stored:
- * {@link MtasCodecPostingsFormat#MTAS_STORAGE_BYTE},
- * {@link MtasCodecPostingsFormat#MTAS_STORAGE_SHORT},
- * {@link MtasCodecPostingsFormat#MTAS_STORAGE_INTEGER} or
- * {@link MtasCodecPostingsFormat#MTAS_STORAGE_LONG}</li>
- * <li><b>VInt</b>: number of objects in this document</li>
- * <li><b>VInt</b>: first position</li>
- * <li><b>VInt</b>: last position</li>
- * </ul>
- * </li>
- * </ul>
- * </li>
- * <li><b>Final files</b><br>
- * <ul>
- * <li><b>File {@link #mtasIndexFieldFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_FIELD_EXTENSION}</b><br>
- * Contains for each field a reference to the list of documents and the
- * prefixes. Structure of content:
- * <ul>
- * <li><b>String</b>: field</li>
- * <li><b>VLong</b>: reference to {@link #mtasDocFileName}</li>
- * <li><b>VLong</b>: reference to {@link #mtasIndexDocIdFileName}</li>
- * <li><b>VInt</b>: number of documents</li>
- * <li><b>VLong</b>: reference to {@link #mtasTermFileName}</li>
- * <li><b>VInt</b>: number of terms</li>
- * <li><b>VLong</b>: reference to {@link #mtasPrefixFileName}</li>
- * <li><b>VInt</b>: number of prefixes</li>
- * </ul>
- * </li>
- * <li><b>File {@link #mtasTermFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_TERM_EXTENSION}</b><br>
- * For each field, all unique terms are stored here. Structure of content:
- * <ul>
- * <li><b>String</b>: term</li>
- * </ul>
- * </li>
- * <li><b>File {@link #mtasPrefixFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_PREFIX_EXTENSION}</b><br>
- * For each field, all unique prefixes are stored here. Structure of content:
- * <ul>
- * <li><b>String</b>: prefix</li>
- * </ul>
- * </li>
- * <li><b>File {@link #mtasObjectFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_OBJECT_EXTENSION}</b><br>
- * Contains all objects for all fields. Structure of content:
- * <ul>
- * <li><b>VInt</b>: mtasId</li>
- * <li><b>VInt</b>: objectFlags
- * <ul>
- * <li>{@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_PARENT}</li>
- * <li>{@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_POSITION_RANGE}</li>
- * <li>{@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_POSITION_SET}</li>
- * <li>{@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_OFFSET}</li>
- * <li>{@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_REALOFFSET}</li>
- * <li>{@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_PAYLOAD}</li>
- * </ul>
- * </li>
- * <li>Only if {@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_PARENT}<br>
- * <b>VInt</b>: parentId
- * <li>Only if
- * {@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_POSITION_RANGE}<br>
- * <b>VInt</b>,<b>VInt</b>: startPosition and (endPosition-startPosition)
- * <li>Only if {@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_POSITION_SET}<br>
- * <b>VInt</b>,<b>VInt</b>,<b>VInt</b>,...: number of positions, firstPosition,
- * (position-previousPosition),...
- * <li>Only if no {@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_POSITION_RANGE}
- * or {@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_POSITION_SET}<br>
- * <b>VInt</b>: position
- * <li>Only if {@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_OFFSET}<br>
- * <b>VInt</b>,<b>VInt</b>: startOffset, (endOffset-startOffset)
- * <li>Only if {@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_REALOFFSET}<br>
- * <b>VInt</b>,<b>VInt</b>: startRealOffset, (endRealOffset-startRealOffset)
- * <li>Only if {@link MtasCodecPostingsFormat#MTAS_OBJECT_HAS_PAYLOAD}<br>
- * <b>VInt</b>,<b>Bytes</b>: number of bytes, payload
- * <li><b>VLong</b>: reference to Term in {@link #mtasTermFileName}</li>
- * </ul>
- * </li>
- * <li><b>File {@link #mtasIndexDocIdFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_INDEX_DOC_ID_EXTENSION}
- * </b><br>
- * Contains for each field a tree structure {@link MtasTree} to search reference
- * to {@link #mtasDocFileName} by id. Structure of content for each node:
- * <ul>
- * <li><b>VLong</b>: offset references to {@link #mtasIndexDocIdFileName}, only
- * available in root node</li>
- * <li><b>Byte</b>: flag, should be zero for this tree, only available in root
- * node</li>
- * <li><b>VInt</b>: left</li>
- * <li><b>VInt</b>: right</li>
- * <li><b>VInt</b>: max</li>
- * <li><b>VLong</b>: left reference to {@link #mtasIndexDocIdFileName} minus the
- * offset stored in the root node</li>
- * <li><b>VLong</b>: right reference to {@link #mtasIndexDocIdFileName} minus
- * the offset stored in the root node</li>
- * <li><b>VInt</b>: number of objects on this node (always 1 for this tree)</li>
- * <li><b>VLong</b>: reference to {@link #mtasDocFileName} minus offset</li>
- * </ul>
- * </li>
- * <li><b>File {@link #mtasDocFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_DOC_EXTENSION}</b><br>
- * For each document
- * <ul>
- * <li><b>VInt</b>: docId</li>
- * <li><b>VLong</b>: reference to {@link #mtasIndexObjectIdFileName}</li>
- * <li><b>VLong</b>: reference to {@link #mtasIndexObjectPositionFileName}</li>
- * <li><b>VLong</b>: reference to {@link #mtasIndexObjectParentFileName}</li>
- * <li><b>VLong</b>: reference first object, used as offset for tree index
- * <li><b>VInt</b>: slope used in approximation reference objects index on id
- * </li>
- * <li><b>ZLong</b>: offset used in approximation reference objects index on id
- * </li>
- * <li><b>Byte</b>: flag indicating how corrections on the approximation
- * references objects for the index on id are stored:
- * {@link MtasCodecPostingsFormat#MTAS_STORAGE_BYTE},
- * {@link MtasCodecPostingsFormat#MTAS_STORAGE_SHORT},
- * {@link MtasCodecPostingsFormat#MTAS_STORAGE_INTEGER} or
- * {@link MtasCodecPostingsFormat#MTAS_STORAGE_LONG}</li>
- * <li><b>VInt</b>: number of objects</li>
- * <li><b>VInt</b>: first position</li>
- * <li><b>VInt</b>: last position</li>
- * </ul>
- * </li>
- * <li><b>File {@link #mtasIndexObjectIdFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_INDEX_OBJECT_ID_EXTENSION}
- * </b><br>
- * Provides for each mtasId the reference to {@link #mtasObjectFileName}. These
- * references are grouped by document, sorted by mtasId, and because the
- * mtasId's for each document will always start with 0 and are sequential
- * without gaps, a reference can be computed if the position of the first
- * reference for a document is known from {@link #mtasDocFileName}. The
- * reference is approximated by the reference to the first object plus the
- * mtasId times a slope. Only a correction to this approximation is stored.
- * Structure of content:
- * <ul>
- * <li><b>Byte</b>/<b>Short</b>/<b>Int</b>/<b>Long</b>: correction reference to
- * {@link #mtasObjectFileName}</li>
- * </ul>
- * </li>
- * <li><b>File {@link #mtasIndexObjectPositionFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_INDEX_OBJECT_POSITION_EXTENSION}
- * </b><br>
- * Contains for each document a tree structure {@link MtasTree} to search
- * objects by position. Structure of content for each node:
- * <ul>
- * <li><b>VLong</b>: offset references to
- * {@link #mtasIndexObjectPositionFileName}, only available in root node</li>
- * <li><b>Byte</b>: flag, should be zero for this tree, only available in root
- * node</li>
- * <li><b>VInt</b>: left</li>
- * <li><b>VInt</b>: right</li>
- * <li><b>VInt</b>: max</li>
- * <li><b>VLong</b>: left reference to {@link #mtasIndexObjectPositionFileName}
- * minus the offset stored in the root node</li>
- * <li><b>VLong</b>: right reference to {@link #mtasIndexObjectPositionFileName}
- * minus the offset stored in the root node</li>
- * <li><b>VInt</b>: number of objects on this node</li>
- * <li><b>VLong</b>,<b>VInt</b>,<b>VLong</b>: set of the first reference to
- * {@link #mtasObjectFileName} minus offset, the prefixId referring to the
- * position the prefix in {@link #mtasPrefixFileName} and the reference to
- * {@link #mtasTermFileName} minus offset</li>
- * <li><b>VLong</b>,<b>VInt</b>,<b>VLong</b>,...: for optional other sets of
- * reference to {@link #mtasObjectFileName}, position of the prefix in
- * {@link #mtasPrefixFileName} and the reference to {@link #mtasTermFileName};
- * for the first item the difference between this reference minus the previous
- * reference is stored</li>
- * </ul>
- * </li>
- * <li><b>File {@link #mtasIndexObjectParentFileName} with extension
- * {@value mtas.codec.MtasCodecPostingsFormat#MTAS_INDEX_OBJECT_PARENT_EXTENSION}
- * </b><br>
- * Contains for each document a tree structure {@link MtasTree} to search
- * objects by parent. Structure of content for each node:
- * <ul>
- * <li><b>VLong</b>: offset references to {@link #mtasIndexObjectParentFileName}
- * , only available in root node</li>
- * <li><b>Byte</b>: flag, for this tree equal to
- * {@link mtas.codec.tree.MtasTree#SINGLE_POSITION_TREE} indicating a tree with
- * exactly one point at each node, only available in root node</li>
- * <li><b>VInt</b>: left</li>
- * <li><b>VInt</b>: right</li>
- * <li><b>VInt</b>: max</li>
- * <li><b>VLong</b>: left reference to {@link #mtasIndexObjectParentFileName}
- * minus the offset stored in the root node</li>
- * <li><b>VLong</b>: right reference to {@link #mtasIndexObjectParentFileName}
- * minus the offset stored in the root node</li>
- * <li><b>VInt</b>: number of objects on this node</li>
- * <li><b>VLong</b>,<b>VInt</b>,<b>VLong</b>: set of the first reference to
- * {@link #mtasObjectFileName} minus offset, the prefixId referring to the
- * position the prefix in {@link #mtasPrefixFileName} and the reference to
- * {@link #mtasTermFileName} minus offset</li>
- * <li><b>VLong</b>,<b>VInt</b>,<b>VLong</b>,...: for optional other sets of
- * reference to {@link #mtasObjectFileName}, position of the prefix in
- * {@link #mtasPrefixFileName} and the reference to {@link #mtasTermFileName};
- * for the first item the difference between this reference minus the previous
- * reference is stored</li>
- * </ul>
- * </li>
- * </ul>
- * </li>
- * </ul>
- * 
  */
 
 public class MtasFieldsConsumer extends FieldsConsumer {
@@ -366,14 +95,10 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Instantiates a new mtas fields consumer.
    *
-   * @param fieldsConsumer
-   *          the fields consumer
-   * @param state
-   *          the state
-   * @param name
-   *          the name
-   * @param delegatePostingsFormatName
-   *          the delegate postings format name
+   * @param fieldsConsumer the fields consumer
+   * @param state the state
+   * @param name the name
+   * @param delegatePostingsFormatName the delegate postings format name
    */
   public MtasFieldsConsumer(FieldsConsumer fieldsConsumer,
       SegmentWriteState state, String name, String delegatePostingsFormatName) {
@@ -430,14 +155,10 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Register prefix.
    *
-   * @param field
-   *          the field
-   * @param prefix
-   *          the prefix
-   * @param outPrefix
-   *          the out prefix
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param field the field
+   * @param prefix the prefix
+   * @param outPrefix the out prefix
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void registerPrefix(String field, String prefix,
       IndexOutput outPrefix) throws IOException {
@@ -456,14 +177,10 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Register prefix stats single position value.
    *
-   * @param field
-   *          the field
-   * @param value
-   *          the value
-   * @param outPrefix
-   *          the out prefix
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param field the field
+   * @param value the value
+   * @param outPrefix the out prefix
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   public void registerPrefixStatsSinglePositionValue(String field, String value,
       IndexOutput outPrefix) throws IOException {
@@ -478,14 +195,10 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Register prefix stats range position value.
    *
-   * @param field
-   *          the field
-   * @param value
-   *          the value
-   * @param outPrefix
-   *          the out prefix
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param field the field
+   * @param value the value
+   * @param outPrefix the out prefix
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   public void registerPrefixStatsRangePositionValue(String field, String value,
       IndexOutput outPrefix) throws IOException {
@@ -499,14 +212,10 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Register prefix stats set position value.
    *
-   * @param field
-   *          the field
-   * @param value
-   *          the value
-   * @param outPrefix
-   *          the out prefix
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param field the field
+   * @param value the value
+   * @param outPrefix the out prefix
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   public void registerPrefixStatsSetPositionValue(String field, String value,
       IndexOutput outPrefix) throws IOException {
@@ -521,8 +230,7 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Inits the prefix stats field.
    *
-   * @param field
-   *          the field
+   * @param field the field
    */
   private void initPrefixStatsField(String field) {
     if (!singlePositionPrefix.containsKey(field)) {
@@ -539,8 +247,7 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Gets the prefix stats single position prefix attribute.
    *
-   * @param field
-   *          the field
+   * @param field the field
    * @return the prefix stats single position prefix attribute
    */
   public String getPrefixStatsSinglePositionPrefixAttribute(String field) {
@@ -551,8 +258,7 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Gets the prefix stats multiple position prefix attribute.
    *
-   * @param field
-   *          the field
+   * @param field the field
    * @return the prefix stats multiple position prefix attribute
    */
   public String getPrefixStatsMultiplePositionPrefixAttribute(String field) {
@@ -563,8 +269,7 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Gets the prefix stats set position prefix attribute.
    *
-   * @param field
-   *          the field
+   * @param field the field
    * @return the prefix stats set position prefix attribute
    */
   public String getPrefixStatsSetPositionPrefixAttribute(String field) {
@@ -589,6 +294,9 @@ public class MtasFieldsConsumer extends FieldsConsumer {
     return text;
   }
 
+  /* (non-Javadoc)
+   * @see org.apache.lucene.codecs.FieldsConsumer#merge(org.apache.lucene.index.MergeState)
+   */
   @Override
   public void merge(MergeState mergeState) throws IOException {
     delegateFieldsConsumer.merge(mergeState);
@@ -609,12 +317,9 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Write.
    *
-   * @param fieldInfos
-   *          the field infos
-   * @param fields
-   *          the fields
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param fieldInfos the field infos
+   * @param fields the fields
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void write(FieldInfos fieldInfos, Fields fields) throws IOException {
     IndexOutput outField, outDoc, outIndexDocId, outIndexObjectId,
@@ -1204,23 +909,15 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Creates the object and register prefix.
    *
-   * @param field
-   *          the field
-   * @param out
-   *          the out
-   * @param term
-   *          the term
-   * @param termRef
-   *          the term ref
-   * @param startPosition
-   *          the start position
-   * @param payload
-   *          the payload
-   * @param outPrefix
-   *          the out prefix
+   * @param field the field
+   * @param out the out
+   * @param term the term
+   * @param termRef the term ref
+   * @param startPosition the start position
+   * @param payload the payload
+   * @param outPrefix the out prefix
    * @return the integer
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private Integer createObjectAndRegisterPrefix(String field, IndexOutput out,
       BytesRef term, Long termRef, int startPosition, BytesRef payload,
@@ -1232,27 +929,17 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Creates the object and register prefix.
    *
-   * @param field
-   *          the field
-   * @param out
-   *          the out
-   * @param term
-   *          the term
-   * @param termRef
-   *          the term ref
-   * @param startPosition
-   *          the start position
-   * @param payload
-   *          the payload
-   * @param startOffset
-   *          the start offset
-   * @param endOffset
-   *          the end offset
-   * @param outPrefix
-   *          the out prefix
+   * @param field the field
+   * @param out the out
+   * @param term the term
+   * @param termRef the term ref
+   * @param startPosition the start position
+   * @param payload the payload
+   * @param startOffset the start offset
+   * @param endOffset the end offset
+   * @param outPrefix the out prefix
    * @return the integer
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private Integer createObjectAndRegisterPrefix(String field, IndexOutput out,
       BytesRef term, Long termRef, int startPosition, BytesRef payload,
@@ -1363,15 +1050,11 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Store tree.
    *
-   * @param tree
-   *          the tree
-   * @param out
-   *          the out
-   * @param refApproxOffset
-   *          the ref approx offset
+   * @param tree the tree
+   * @param out the out
+   * @param refApproxOffset the ref approx offset
    * @return the long
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private Long storeTree(MtasTree<?> tree, IndexOutput out,
       long refApproxOffset) throws IOException {
@@ -1382,21 +1065,14 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Store tree.
    *
-   * @param node
-   *          the node
-   * @param isSinglePoint
-   *          the is single point
-   * @param storeAdditionalInformation
-   *          the store additional information
-   * @param out
-   *          the out
-   * @param nodeRefApproxOffset
-   *          the node ref approx offset
-   * @param refApproxOffset
-   *          the ref approx offset
+   * @param node the node
+   * @param isSinglePoint the is single point
+   * @param storeAdditionalInformation the store additional information
+   * @param out the out
+   * @param nodeRefApproxOffset the node ref approx offset
+   * @param refApproxOffset the ref approx offset
    * @return the long
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private Long storeTree(MtasTreeNode<?> node, boolean isSinglePoint,
       boolean storeAdditionalInformation, IndexOutput out,
@@ -1481,10 +1157,8 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Token stats add.
    *
-   * @param min
-   *          the min
-   * @param max
-   *          the max
+   * @param min the min
+   * @param max the max
    */
   private void tokenStatsAdd(int min, int max) {
     tokenStatsNumber++;
@@ -1503,16 +1177,11 @@ public class MtasFieldsConsumer extends FieldsConsumer {
   /**
    * Copy object and update stats.
    *
-   * @param id
-   *          the id
-   * @param in
-   *          the in
-   * @param inRef
-   *          the in ref
-   * @param out
-   *          the out
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param id the id
+   * @param in the in
+   * @param inRef the in ref
+   * @param out the out
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void copyObjectAndUpdateStats(int id, IndexInput in, Long inRef,
       IndexOutput out) throws IOException {
diff --git a/src/mtas/parser/cql/MtasCQLParser.java b/src/mtas/parser/cql/MtasCQLParser.java
new file mode 100644
index 0000000..9eaefa4
--- /dev/null
+++ b/src/mtas/parser/cql/MtasCQLParser.java
@@ -0,0 +1,2257 @@
+/* Generated By:JavaCC: Do not edit this line. MtasCQLParser.java */
+package mtas.parser.cql;
+import mtas.analysis.token.MtasToken;
+import mtas.parser.cql.util.MtasCQLParserGroupCondition;
+import mtas.parser.cql.util.MtasCQLParserGroupFullCondition;
+import mtas.parser.cql.util.MtasCQLParserWordCondition;
+import mtas.parser.cql.util.MtasCQLParserWordPositionQuery;
+import mtas.parser.cql.util.MtasCQLParserWordFullCondition;
+import mtas.parser.cql.util.MtasCQLParserBasicSentenceCondition;
+import mtas.parser.cql.util.MtasCQLParserSentenceCondition;
+import mtas.parser.cql.util.MtasCQLParserSentencePartCondition;
+import mtas.parser.cql.util.MtasCQLParserGroupQuery;
+import mtas.parser.cql.util.MtasCQLParserWordQuery;
+import mtas.parser.cql.util.MtasCQLParserDefaultPrefixCondition;
+import org.apache.lucene.search.spans.SpanContainingQuery;
+import org.apache.lucene.search.spans.SpanNotQuery;
+import org.apache.lucene.search.spans.SpanQuery;
+import org.apache.lucene.search.spans.SpanWithinQuery;
+import org.apache.lucene.index.Term;
+import mtas.search.spans.MtasSpanSequenceItem;
+import mtas.search.spans.MtasSpanSequenceQuery;
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class MtasCQLParser implements MtasCQLParserConstants {
+  public SpanQuery parse(String field, String defaultPrefix) throws ParseException
+  {
+    return cql(field, defaultPrefix);
+  }
+
+  private String unquoteString(String unfiltered)
+  {
+    if (unfiltered.startsWith("\u005c"") && unfiltered.endsWith("\u005c""))
+    {
+      unfiltered = unfiltered.substring(1, unfiltered.length());
+      unfiltered = unfiltered.substring(0, unfiltered.length() - 1);
+    }
+    return unfiltered;
+  }
+
+  final private SpanQuery cql(String field, String defaultPrefix) throws ParseException, ParseException {
+  SpanQuery q;
+  ArrayList < MtasSpanSequenceItem > itemList = new ArrayList < MtasSpanSequenceItem > ();
+    q = cqlBlock(field, defaultPrefix);
+    itemList.add(new MtasSpanSequenceItem(q, false));
+    label_1:
+    while (true) {
+      if (jj_2_1(1000)) {
+        ;
+      } else {
+        break label_1;
+      }
+      q = cqlBlock(field, defaultPrefix);
+      itemList.add(new MtasSpanSequenceItem(q, false));
+    }
+    jj_consume_token(0);
+    if (itemList.size() > 1)
+    {
+      {if (true) return new MtasSpanSequenceQuery(itemList);}
+    }
+    else
+    {
+      {if (true) return itemList.get(0).getQuery();}
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final private SpanQuery cqlBlock(String field, String defaultPrefix) throws ParseException, ParseException {
+  MtasCQLParserSentenceCondition s1 = null, s2 = null;
+  SpanQuery q1 = null, q2 = null;
+  Token end = null;
+  String operator = null;
+  String OPERATOR_CONTAINING = "containing";
+  String OPERATOR_NOT_CONTAINING = "not_containing";
+  String OPERATOR_WITHIN = "within";
+  String OPERATOR_NOT_WITHIN = "not_within";
+    if (jj_2_2(1000)) {
+      s1 = sentence(field, defaultPrefix);
+    } else if (jj_2_3(1000)) {
+      jj_consume_token(BRACKET_START);
+      q1 = cqlBlock(field, defaultPrefix);
+      jj_consume_token(BRACKET_END);
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    if (jj_2_10(1000)) {
+      if (jj_2_4(1000)) {
+        jj_consume_token(CONTAINING);
+        operator = OPERATOR_CONTAINING;
+      } else if (jj_2_5(1000)) {
+        jj_consume_token(NOT_CONTAINING);
+        operator = OPERATOR_NOT_CONTAINING;
+      } else if (jj_2_6(1000)) {
+        jj_consume_token(WITHIN);
+        operator = OPERATOR_WITHIN;
+      } else if (jj_2_7(1000)) {
+        jj_consume_token(NOT_WITHIN);
+        operator = OPERATOR_NOT_WITHIN;
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+      if (jj_2_8(1000)) {
+        s2 = sentence(field, defaultPrefix);
+      } else if (jj_2_9(1000)) {
+        jj_consume_token(BRACKET_START);
+        q2 = cqlBlock(field, defaultPrefix);
+        jj_consume_token(BRACKET_END);
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+    } else {
+      ;
+    }
+    if (s1 != null)
+    {
+      q1 = s1.getQuery();
+    }
+    if (operator != null)
+    {
+      if (s2 != null)
+      {
+        q2 = s2.getQuery();
+      }
+      if (operator.equals(OPERATOR_CONTAINING))
+      {
+        {if (true) return new SpanContainingQuery(q1, q2);}
+      }
+      else if (operator.equals(OPERATOR_NOT_CONTAINING))
+      {
+        {if (true) return new SpanNotQuery(q1, new SpanContainingQuery(q1, q2));}
+      }
+      else if (operator.equals(OPERATOR_WITHIN))
+      {
+        {if (true) return new SpanWithinQuery(q2, q1);}
+      }
+      else if (operator.equals(OPERATOR_NOT_WITHIN))
+      {
+        {if (true) return new SpanNotQuery(q1, new SpanWithinQuery(q2, q1));}
+      }
+      else
+      {
+        {if (true) throw new ParseException("unexpected operator " + operator);}
+      }
+    }
+    else
+    {
+      {if (true) return q1;}
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final private MtasCQLParserSentenceCondition sentence(String field, String defaultPrefix) throws ParseException, ParseException {
+  MtasCQLParserSentenceCondition sentenceCondition;
+  MtasCQLParserSentencePartCondition condition;
+  Token questionMark = null;
+  Token minValue = null;
+  Token maxValue = null;
+  int minimumOccurence = 1;
+  int maximumOccurence = 1;
+    condition = sentencePart(field, defaultPrefix);
+    sentenceCondition = condition.createFullSentence();
+    {if (true) return sentenceCondition;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final private MtasCQLParserSentencePartCondition sentencePart(String field, String defaultPrefix) throws ParseException, ParseException {
+  Token operator;
+  MtasCQLParserSentencePartCondition condition, sentencePart;
+  MtasCQLParserBasicSentenceCondition basicSentence;
+  Token questionMark = null;
+  Token minValue = null;
+  Token maxValue = null;
+  int minimumOccurence = 1;
+  int maximumOccurence = 1;
+    if (jj_2_15(1000)) {
+      basicSentence = basicSentence(field, defaultPrefix);
+      condition = new MtasCQLParserSentencePartCondition(basicSentence);
+    } else if (jj_2_16(1000)) {
+      jj_consume_token(BRACKET_START);
+      sentencePart = sentencePart(field, defaultPrefix);
+      jj_consume_token(BRACKET_END);
+      if (jj_2_14(1000)) {
+          questionMark = null;
+        if (jj_2_11(1000)) {
+          jj_consume_token(CURLY_BRACKET_START);
+          minValue = jj_consume_token(NUMBER);
+          jj_consume_token(KOMMA);
+          maxValue = jj_consume_token(NUMBER);
+          jj_consume_token(CURLY_BRACKET_END);
+        } else if (jj_2_12(1000)) {
+          jj_consume_token(CURLY_BRACKET_START);
+          minValue = jj_consume_token(NUMBER);
+          jj_consume_token(CURLY_BRACKET_END);
+        } else if (jj_2_13(1000)) {
+          questionMark = jj_consume_token(QUESTION_MARK);
+        } else {
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+      } else {
+        ;
+      }
+        condition = new MtasCQLParserSentencePartCondition(sentencePart.createFullSentence());
+        if (questionMark != null)
+        {
+          minimumOccurence = 0;
+          maximumOccurence = 1;
+        }
+        else if (minValue != null)
+        {
+          minimumOccurence = Integer.parseInt(minValue.image);
+          if (maxValue != null)
+          {
+            maximumOccurence = Integer.parseInt(maxValue.image);
+          }
+          else
+          {
+            maximumOccurence = minimumOccurence;
+          }
+        }
+        condition.setFirstOccurence(minimumOccurence, maximumOccurence);
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    if (jj_2_18(1000)) {
+      operator = null;
+      if (jj_2_17(1000)) {
+        operator = jj_consume_token(OR);
+      } else {
+        ;
+      }
+      sentencePart = sentencePart(field, defaultPrefix);
+        if (operator == null)
+        {
+          condition.setOr(false);
+        }
+        else
+        {
+          condition.setOr(true);
+        }
+        condition.setSecondPart(sentencePart);
+    } else {
+      ;
+    }
+    {if (true) return condition;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final private MtasCQLParserBasicSentenceCondition basicSentence(String field, String defaultPrefix) throws ParseException, ParseException {
+  MtasCQLParserWordFullCondition subWordCondition;
+  MtasCQLParserGroupFullCondition subGroupCondition;
+  MtasCQLParserBasicSentenceCondition condition = new MtasCQLParserBasicSentenceCondition();
+    if (jj_2_19(1000)) {
+      subWordCondition = word(field, defaultPrefix);
+      condition.addWord(subWordCondition);
+    } else if (jj_2_20(1000)) {
+      subGroupCondition = group(field);
+      condition.addGroup(subGroupCondition);
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    label_2:
+    while (true) {
+      if (jj_2_21(1000)) {
+        ;
+      } else {
+        break label_2;
+      }
+      if (jj_2_22(1000)) {
+        subWordCondition = word(field, defaultPrefix);
+        condition.addWord(subWordCondition);
+      } else if (jj_2_23(1000)) {
+        subGroupCondition = group(field);
+        condition.addGroup(subGroupCondition);
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+    }
+    {if (true) return condition;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final private MtasCQLParserGroupFullCondition group(String field) throws ParseException, ParseException {
+  Token questionMark = null;
+  MtasCQLParserGroupFullCondition groupCondition;
+  MtasCQLParserGroupCondition condition;
+  Boolean startGroup, endGroup;
+  Token minValue = null;
+  Token maxValue = null;
+  Token slash = null;
+  int minimumOccurence = 1;
+  int maximumOccurence = 1;
+    jj_consume_token(GROUP_START);
+    if (jj_2_25(1000)) {
+      condition = groupCondition(field);
+      if (jj_2_24(1000)) {
+        slash = jj_consume_token(SLASH);
+      } else {
+        ;
+      }
+      if (slash == null)
+      {
+        startGroup = true;
+      }
+      else
+      {
+        startGroup = false;
+      }
+      endGroup = false;
+    } else if (jj_2_26(1000)) {
+      jj_consume_token(SLASH);
+      condition = groupCondition(field);
+      startGroup = true;
+      endGroup = false;
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    jj_consume_token(GROUP_END);
+    if (jj_2_30(1000)) {
+      questionMark = null;
+      if (jj_2_27(1000)) {
+        jj_consume_token(CURLY_BRACKET_START);
+        minValue = jj_consume_token(NUMBER);
+        jj_consume_token(KOMMA);
+        maxValue = jj_consume_token(NUMBER);
+        jj_consume_token(CURLY_BRACKET_END);
+      } else if (jj_2_28(1000)) {
+        jj_consume_token(CURLY_BRACKET_START);
+        minValue = jj_consume_token(NUMBER);
+        jj_consume_token(CURLY_BRACKET_END);
+      } else if (jj_2_29(1000)) {
+        questionMark = jj_consume_token(QUESTION_MARK);
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+    } else {
+      ;
+    }
+    if (startGroup)
+    {
+      groupCondition = new MtasCQLParserGroupFullCondition(condition, MtasCQLParserGroupFullCondition.GROUP_START);
+    }
+    else if (endGroup)
+    {
+      groupCondition = new MtasCQLParserGroupFullCondition(condition, MtasCQLParserGroupFullCondition.GROUP_END);
+    }
+    else
+    {
+      groupCondition = new MtasCQLParserGroupFullCondition(condition, MtasCQLParserGroupFullCondition.GROUP_FULL);
+    }
+    if (questionMark != null)
+    {
+      minimumOccurence = 0;
+      maximumOccurence = 1;
+    }
+    else if (minValue != null)
+    {
+      minimumOccurence = Integer.parseInt(minValue.image);
+      if (maxValue != null)
+      {
+        maximumOccurence = Integer.parseInt(maxValue.image);
+      }
+      else
+      {
+        maximumOccurence = minimumOccurence;
+      }
+    }
+    groupCondition.setOccurence(minimumOccurence, maximumOccurence);
+    {if (true) return groupCondition;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final private MtasCQLParserGroupCondition groupCondition(String field) throws ParseException, ParseException {
+  Token prefix;
+  Token value = null;
+    if (jj_2_31(1000)) {
+      prefix = jj_consume_token(UNQUOTED_VALUE);
+      jj_consume_token(TOKEN_EQUALS);
+      value = jj_consume_token(QUOTED_VALUE);
+    } else if (jj_2_32(1000)) {
+      prefix = jj_consume_token(UNQUOTED_VALUE);
+      value = null;
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    if (value != null)
+    {
+      SpanQuery q = new MtasCQLParserGroupQuery(field, prefix.image, unquoteString(value.image));
+      MtasCQLParserGroupCondition condition = new MtasCQLParserGroupCondition(field, q);
+      {if (true) return condition;}
+    }
+    else
+    {
+      SpanQuery q = new MtasCQLParserGroupQuery(field, prefix.image, null);
+      MtasCQLParserGroupCondition condition = new MtasCQLParserGroupCondition(field, q);
+      {if (true) return condition;}
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final private MtasCQLParserWordFullCondition word(String field, String defaultPrefix) throws ParseException, ParseException {
+  Token questionMark = null;
+  Token value;
+  MtasCQLParserWordFullCondition wordCondition;
+  MtasCQLParserWordCondition condition, subCondition;
+  Token minValue = null;
+  Token maxValue = null;
+  int minimumOccurence = 1;
+  int maximumOccurence = 1;
+    if (jj_2_39(1000)) {
+      value = jj_consume_token(QUOTED_VALUE);
+      condition = new MtasCQLParserDefaultPrefixCondition(field, defaultPrefix, unquoteString(value.image));
+    } else if (jj_2_40(1000)) {
+      jj_consume_token(WORD_START);
+      if (jj_2_37(1000)) {
+        subCondition = wordCondition(field);
+        if (jj_2_35(1000)) {
+          jj_consume_token(AND);
+          condition = new MtasCQLParserWordCondition(field, MtasCQLParserWordCondition.TYPE_AND);
+          condition.addCondition(subCondition);
+          subCondition = wordCondition(field);
+          condition.addCondition(subCondition);
+          label_3:
+          while (true) {
+            if (jj_2_33(1000)) {
+              ;
+            } else {
+              break label_3;
+            }
+            jj_consume_token(AND);
+            subCondition = wordCondition(field);
+            condition.addCondition(subCondition);
+          }
+        } else if (jj_2_36(1000)) {
+          jj_consume_token(OR);
+          condition = new MtasCQLParserWordCondition(field, MtasCQLParserWordCondition.TYPE_OR);
+          condition.addCondition(subCondition);
+          subCondition = wordCondition(field);
+          condition.addCondition(subCondition);
+          label_4:
+          while (true) {
+            if (jj_2_34(1000)) {
+              ;
+            } else {
+              break label_4;
+            }
+            jj_consume_token(OR);
+            subCondition = wordCondition(field);
+            condition.addCondition(subCondition);
+          }
+        } else {
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+      } else if (jj_2_38(1000)) {
+        condition = wordCondition(field);
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+      jj_consume_token(WORD_END);
+    } else if (jj_2_41(1000)) {
+      condition = new MtasCQLParserWordCondition(field, MtasCQLParserWordCondition.TYPE_AND);
+      jj_consume_token(WORD_START);
+      jj_consume_token(WORD_END);
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    if (jj_2_45(1000)) {
+      questionMark = null;
+      if (jj_2_42(1000)) {
+        jj_consume_token(CURLY_BRACKET_START);
+        minValue = jj_consume_token(NUMBER);
+        jj_consume_token(KOMMA);
+        maxValue = jj_consume_token(NUMBER);
+        jj_consume_token(CURLY_BRACKET_END);
+      } else if (jj_2_43(1000)) {
+        jj_consume_token(CURLY_BRACKET_START);
+        minValue = jj_consume_token(NUMBER);
+        jj_consume_token(CURLY_BRACKET_END);
+      } else if (jj_2_44(1000)) {
+        questionMark = jj_consume_token(QUESTION_MARK);
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+    } else {
+      ;
+    }
+    condition.simplify();
+    wordCondition = new MtasCQLParserWordFullCondition(condition);
+    if (questionMark != null)
+    {
+      minimumOccurence = 0;
+      maximumOccurence = 1;
+    }
+    else if (minValue != null)
+    {
+      minimumOccurence = Integer.parseInt(minValue.image);
+      if (maxValue != null)
+      {
+        maximumOccurence = Integer.parseInt(maxValue.image);
+      }
+      else
+      {
+        maximumOccurence = minimumOccurence;
+      }
+    }
+    wordCondition.setOccurence(minimumOccurence, maximumOccurence);
+    //System.out.println(wordCondition + "\n");
+    {if (true) return wordCondition;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final private MtasCQLParserWordCondition wordCondition(String field) throws ParseException, ParseException {
+  Token negation = null;
+  MtasCQLParserWordCondition condition, subCondition;
+    if (jj_2_66(1000)) {
+      if (jj_2_46(1000)) {
+        negation = jj_consume_token(NEGATION);
+      } else {
+        ;
+      }
+      jj_consume_token(BRACKET_START);
+      if (jj_2_63(1000)) {
+        condition = new MtasCQLParserWordCondition(field, MtasCQLParserWordCondition.TYPE_AND);
+        if (jj_2_47(1000)) {
+          subCondition = wordAtomCondition(field);
+        } else if (jj_2_48(1000)) {
+          subCondition = wordCondition(field);
+        } else {
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+        condition.addCondition(subCondition);
+        jj_consume_token(AND);
+        if (jj_2_49(1000)) {
+          subCondition = wordAtomCondition(field);
+        } else if (jj_2_50(1000)) {
+          subCondition = wordCondition(field);
+        } else {
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+        condition.addCondition(subCondition);
+        label_5:
+        while (true) {
+          if (jj_2_51(1000)) {
+            ;
+          } else {
+            break label_5;
+          }
+          jj_consume_token(AND);
+          if (jj_2_52(1000)) {
+            subCondition = wordAtomCondition(field);
+          } else if (jj_2_53(1000)) {
+            subCondition = wordCondition(field);
+          } else {
+            jj_consume_token(-1);
+            throw new ParseException();
+          }
+          condition.addCondition(subCondition);
+        }
+      } else if (jj_2_64(1000)) {
+        condition = new MtasCQLParserWordCondition(field, MtasCQLParserWordCondition.TYPE_OR);
+        if (jj_2_54(1000)) {
+          subCondition = wordAtomCondition(field);
+        } else if (jj_2_55(1000)) {
+          subCondition = wordCondition(field);
+        } else {
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+        condition.addCondition(subCondition);
+        jj_consume_token(OR);
+        if (jj_2_56(1000)) {
+          subCondition = wordAtomCondition(field);
+        } else if (jj_2_57(1000)) {
+          subCondition = wordCondition(field);
+        } else {
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+        condition.addCondition(subCondition);
+        label_6:
+        while (true) {
+          if (jj_2_58(1000)) {
+            ;
+          } else {
+            break label_6;
+          }
+          jj_consume_token(OR);
+          if (jj_2_59(1000)) {
+            subCondition = wordAtomCondition(field);
+          } else if (jj_2_60(1000)) {
+            subCondition = wordCondition(field);
+          } else {
+            jj_consume_token(-1);
+            throw new ParseException();
+          }
+          condition.addCondition(subCondition);
+        }
+      } else if (jj_2_65(1000)) {
+        if (jj_2_61(1000)) {
+          condition = wordAtomCondition(field);
+        } else if (jj_2_62(1000)) {
+          condition = wordCondition(field);
+        } else {
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+      jj_consume_token(BRACKET_END);
+      if (negation != null)
+      {
+        condition.swapNot();
+      }
+      //System.out.println("=== wordCondition ===\n" + condition + "\n");
+      {if (true) return condition;}
+    } else if (jj_2_67(1000)) {
+      //plain atom is a valid condition
+          subCondition = wordAtomCondition(field);
+      //System.out.println("=== wordCondition ===\n" + subCondition + "\n");
+      {if (true) return subCondition;}
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    //System.out.println("=== wordCondition ===\n" + condition + "\n");
+    {if (true) return null;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final private MtasCQLParserWordCondition wordAtomCondition(String field) throws ParseException, ParseException {
+  Token negation = null;
+  Token nequals = null;
+  Token prefix;
+  Token value;
+    if (jj_2_68(1000)) {
+      negation = jj_consume_token(NEGATION);
+    } else {
+      ;
+    }
+    if (jj_2_73(1000)) {
+      jj_consume_token(OCTOTHORPE);
+      if (jj_2_69(1000)) {
+        value = jj_consume_token(NUMBER);
+      } else if (jj_2_70(1000)) {
+        value = jj_consume_token(UNQUOTED_VALUE);
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+        Integer startPosition = null;
+        Integer endPosition = null;
+        Pattern range = Pattern.compile("([0-9]+)(\u005c\u005c-([0-9]+))?");
+        Matcher m = range.matcher(value.image);
+        if (m.find())
+        {
+          startPosition = m.group(1) != null ? Integer.parseInt(m.group(1)) : null;
+          endPosition = m.group(3) != null ? Integer.parseInt(m.group(3)) : null;
+        }
+        else
+        {
+          {if (true) throw new ParseException("invalid range '" + value.image + "'");}
+        }
+        MtasCQLParserWordCondition condition = new MtasCQLParserWordCondition(field, MtasCQLParserWordCondition.TYPE_AND);
+        if (startPosition != null && endPosition != null)
+        {
+          SpanQuery q = new MtasCQLParserWordPositionQuery(field, startPosition, endPosition);
+          condition.addPositiveQuery(q);
+        }
+        else if (startPosition != null)
+        {
+          SpanQuery q = new MtasCQLParserWordPositionQuery(field, startPosition, startPosition);
+          condition.addPositiveQuery(q);
+        }
+        else
+        {
+          //should not happen
+          {if (true) throw new ParseException("invalid range");}
+        }
+        {if (true) return condition;}
+    } else if (jj_2_74(1000)) {
+      prefix = jj_consume_token(UNQUOTED_VALUE);
+      if (jj_2_71(1000)) {
+        nequals = jj_consume_token(TOKEN_NOTEQUALS);
+      } else if (jj_2_72(1000)) {
+        jj_consume_token(TOKEN_EQUALS);
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+      value = jj_consume_token(QUOTED_VALUE);
+        if (nequals != null)
+        {
+          //use RegexpQuery combined with SpanMultiTermQueryWrapper
+          {if (true) throw new ParseException("TODO: not implemented '" + prefix.image + nequals.image + value.image + "'");}
+        }
+        else
+        {
+          MtasCQLParserWordCondition condition = new MtasCQLParserWordCondition(field, MtasCQLParserWordCondition.TYPE_AND);
+          Term term = new Term(field, prefix.image + MtasToken.DELIMITER + unquoteString(value.image));
+          SpanQuery q = new MtasCQLParserWordQuery(field, prefix.image, unquoteString(value.image), MtasCQLParserWordQuery.MTAS_CQL_REGEXP_QUERY);
+          if (negation != null)
+          {
+            condition.swapNot();
+          }
+          condition.addPositiveQuery(q);
+          //System.out.println("=== wordAtomCondition ===\n" + condition + "\n");
+          {if (true) return condition;}
+        }
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  private boolean jj_2_1(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_1(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(0, xla); }
+  }
+
+  private boolean jj_2_2(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_2(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(1, xla); }
+  }
+
+  private boolean jj_2_3(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_3(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(2, xla); }
+  }
+
+  private boolean jj_2_4(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_4(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(3, xla); }
+  }
+
+  private boolean jj_2_5(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_5(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(4, xla); }
+  }
+
+  private boolean jj_2_6(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_6(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(5, xla); }
+  }
+
+  private boolean jj_2_7(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_7(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(6, xla); }
+  }
+
+  private boolean jj_2_8(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_8(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(7, xla); }
+  }
+
+  private boolean jj_2_9(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_9(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(8, xla); }
+  }
+
+  private boolean jj_2_10(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_10(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(9, xla); }
+  }
+
+  private boolean jj_2_11(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_11(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(10, xla); }
+  }
+
+  private boolean jj_2_12(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_12(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(11, xla); }
+  }
+
+  private boolean jj_2_13(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_13(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(12, xla); }
+  }
+
+  private boolean jj_2_14(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_14(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(13, xla); }
+  }
+
+  private boolean jj_2_15(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_15(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(14, xla); }
+  }
+
+  private boolean jj_2_16(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_16(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(15, xla); }
+  }
+
+  private boolean jj_2_17(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_17(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(16, xla); }
+  }
+
+  private boolean jj_2_18(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_18(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(17, xla); }
+  }
+
+  private boolean jj_2_19(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_19(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(18, xla); }
+  }
+
+  private boolean jj_2_20(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_20(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(19, xla); }
+  }
+
+  private boolean jj_2_21(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_21(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(20, xla); }
+  }
+
+  private boolean jj_2_22(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_22(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(21, xla); }
+  }
+
+  private boolean jj_2_23(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_23(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(22, xla); }
+  }
+
+  private boolean jj_2_24(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_24(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(23, xla); }
+  }
+
+  private boolean jj_2_25(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_25(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(24, xla); }
+  }
+
+  private boolean jj_2_26(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_26(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(25, xla); }
+  }
+
+  private boolean jj_2_27(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_27(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(26, xla); }
+  }
+
+  private boolean jj_2_28(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_28(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(27, xla); }
+  }
+
+  private boolean jj_2_29(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_29(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(28, xla); }
+  }
+
+  private boolean jj_2_30(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_30(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(29, xla); }
+  }
+
+  private boolean jj_2_31(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_31(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(30, xla); }
+  }
+
+  private boolean jj_2_32(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_32(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(31, xla); }
+  }
+
+  private boolean jj_2_33(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_33(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(32, xla); }
+  }
+
+  private boolean jj_2_34(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_34(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(33, xla); }
+  }
+
+  private boolean jj_2_35(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_35(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(34, xla); }
+  }
+
+  private boolean jj_2_36(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_36(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(35, xla); }
+  }
+
+  private boolean jj_2_37(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_37(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(36, xla); }
+  }
+
+  private boolean jj_2_38(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_38(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(37, xla); }
+  }
+
+  private boolean jj_2_39(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_39(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(38, xla); }
+  }
+
+  private boolean jj_2_40(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_40(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(39, xla); }
+  }
+
+  private boolean jj_2_41(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_41(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(40, xla); }
+  }
+
+  private boolean jj_2_42(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_42(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(41, xla); }
+  }
+
+  private boolean jj_2_43(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_43(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(42, xla); }
+  }
+
+  private boolean jj_2_44(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_44(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(43, xla); }
+  }
+
+  private boolean jj_2_45(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_45(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(44, xla); }
+  }
+
+  private boolean jj_2_46(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_46(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(45, xla); }
+  }
+
+  private boolean jj_2_47(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_47(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(46, xla); }
+  }
+
+  private boolean jj_2_48(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_48(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(47, xla); }
+  }
+
+  private boolean jj_2_49(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_49(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(48, xla); }
+  }
+
+  private boolean jj_2_50(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_50(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(49, xla); }
+  }
+
+  private boolean jj_2_51(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_51(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(50, xla); }
+  }
+
+  private boolean jj_2_52(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_52(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(51, xla); }
+  }
+
+  private boolean jj_2_53(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_53(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(52, xla); }
+  }
+
+  private boolean jj_2_54(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_54(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(53, xla); }
+  }
+
+  private boolean jj_2_55(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_55(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(54, xla); }
+  }
+
+  private boolean jj_2_56(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_56(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(55, xla); }
+  }
+
+  private boolean jj_2_57(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_57(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(56, xla); }
+  }
+
+  private boolean jj_2_58(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_58(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(57, xla); }
+  }
+
+  private boolean jj_2_59(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_59(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(58, xla); }
+  }
+
+  private boolean jj_2_60(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_60(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(59, xla); }
+  }
+
+  private boolean jj_2_61(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_61(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(60, xla); }
+  }
+
+  private boolean jj_2_62(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_62(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(61, xla); }
+  }
+
+  private boolean jj_2_63(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_63(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(62, xla); }
+  }
+
+  private boolean jj_2_64(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_64(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(63, xla); }
+  }
+
+  private boolean jj_2_65(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_65(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(64, xla); }
+  }
+
+  private boolean jj_2_66(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_66(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(65, xla); }
+  }
+
+  private boolean jj_2_67(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_67(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(66, xla); }
+  }
+
+  private boolean jj_2_68(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_68(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(67, xla); }
+  }
+
+  private boolean jj_2_69(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_69(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(68, xla); }
+  }
+
+  private boolean jj_2_70(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_70(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(69, xla); }
+  }
+
+  private boolean jj_2_71(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_71(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(70, xla); }
+  }
+
+  private boolean jj_2_72(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_72(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(71, xla); }
+  }
+
+  private boolean jj_2_73(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_73(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(72, xla); }
+  }
+
+  private boolean jj_2_74(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_74(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(73, xla); }
+  }
+
+  private boolean jj_3R_11() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_39()) {
+    jj_scanpos = xsp;
+    if (jj_3_40()) {
+    jj_scanpos = xsp;
+    if (jj_3_41()) return true;
+    }
+    }
+    xsp = jj_scanpos;
+    if (jj_3_45()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3_68() {
+    if (jj_scan_token(NEGATION)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_15() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_68()) jj_scanpos = xsp;
+    xsp = jj_scanpos;
+    if (jj_3_73()) {
+    jj_scanpos = xsp;
+    if (jj_3_74()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3_13() {
+    if (jj_scan_token(QUESTION_MARK)) return true;
+    return false;
+  }
+
+  private boolean jj_3_12() {
+    if (jj_scan_token(CURLY_BRACKET_START)) return true;
+    if (jj_scan_token(NUMBER)) return true;
+    if (jj_scan_token(CURLY_BRACKET_END)) return true;
+    return false;
+  }
+
+  private boolean jj_3_11() {
+    if (jj_scan_token(CURLY_BRACKET_START)) return true;
+    if (jj_scan_token(NUMBER)) return true;
+    if (jj_scan_token(KOMMA)) return true;
+    if (jj_scan_token(NUMBER)) return true;
+    if (jj_scan_token(CURLY_BRACKET_END)) return true;
+    return false;
+  }
+
+  private boolean jj_3_14() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_11()) {
+    jj_scanpos = xsp;
+    if (jj_3_12()) {
+    jj_scanpos = xsp;
+    if (jj_3_13()) return true;
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3_67() {
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3_16() {
+    if (jj_scan_token(BRACKET_START)) return true;
+    if (jj_3R_10()) return true;
+    if (jj_scan_token(BRACKET_END)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_14()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3_15() {
+    if (jj_3R_9()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_10() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_15()) {
+    jj_scanpos = xsp;
+    if (jj_3_16()) return true;
+    }
+    xsp = jj_scanpos;
+    if (jj_3_18()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3_62() {
+    if (jj_3R_14()) return true;
+    return false;
+  }
+
+  private boolean jj_3_61() {
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3_32() {
+    if (jj_scan_token(UNQUOTED_VALUE)) return true;
+    return false;
+  }
+
+  private boolean jj_3_31() {
+    if (jj_scan_token(UNQUOTED_VALUE)) return true;
+    if (jj_scan_token(TOKEN_EQUALS)) return true;
+    if (jj_scan_token(QUOTED_VALUE)) return true;
+    return false;
+  }
+
+  private boolean jj_3_65() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_61()) {
+    jj_scanpos = xsp;
+    if (jj_3_62()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_13() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_31()) {
+    jj_scanpos = xsp;
+    if (jj_3_32()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3_60() {
+    if (jj_3R_14()) return true;
+    return false;
+  }
+
+  private boolean jj_3_59() {
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3_58() {
+    if (jj_scan_token(OR)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_59()) {
+    jj_scanpos = xsp;
+    if (jj_3_60()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3_57() {
+    if (jj_3R_14()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_8() {
+    if (jj_3R_10()) return true;
+    return false;
+  }
+
+  private boolean jj_3_56() {
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3_55() {
+    if (jj_3R_14()) return true;
+    return false;
+  }
+
+  private boolean jj_3_54() {
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3_64() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_54()) {
+    jj_scanpos = xsp;
+    if (jj_3_55()) return true;
+    }
+    if (jj_scan_token(OR)) return true;
+    xsp = jj_scanpos;
+    if (jj_3_56()) {
+    jj_scanpos = xsp;
+    if (jj_3_57()) return true;
+    }
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3_58()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3_53() {
+    if (jj_3R_14()) return true;
+    return false;
+  }
+
+  private boolean jj_3_52() {
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3_24() {
+    if (jj_scan_token(SLASH)) return true;
+    return false;
+  }
+
+  private boolean jj_3_51() {
+    if (jj_scan_token(AND)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_52()) {
+    jj_scanpos = xsp;
+    if (jj_3_53()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3_29() {
+    if (jj_scan_token(QUESTION_MARK)) return true;
+    return false;
+  }
+
+  private boolean jj_3_28() {
+    if (jj_scan_token(CURLY_BRACKET_START)) return true;
+    if (jj_scan_token(NUMBER)) return true;
+    if (jj_scan_token(CURLY_BRACKET_END)) return true;
+    return false;
+  }
+
+  private boolean jj_3_50() {
+    if (jj_3R_14()) return true;
+    return false;
+  }
+
+  private boolean jj_3_27() {
+    if (jj_scan_token(CURLY_BRACKET_START)) return true;
+    if (jj_scan_token(NUMBER)) return true;
+    if (jj_scan_token(KOMMA)) return true;
+    if (jj_scan_token(NUMBER)) return true;
+    if (jj_scan_token(CURLY_BRACKET_END)) return true;
+    return false;
+  }
+
+  private boolean jj_3_49() {
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3_30() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_27()) {
+    jj_scanpos = xsp;
+    if (jj_3_28()) {
+    jj_scanpos = xsp;
+    if (jj_3_29()) return true;
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3_48() {
+    if (jj_3R_14()) return true;
+    return false;
+  }
+
+  private boolean jj_3_47() {
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3_26() {
+    if (jj_scan_token(SLASH)) return true;
+    if (jj_3R_13()) return true;
+    return false;
+  }
+
+  private boolean jj_3_63() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_47()) {
+    jj_scanpos = xsp;
+    if (jj_3_48()) return true;
+    }
+    if (jj_scan_token(AND)) return true;
+    xsp = jj_scanpos;
+    if (jj_3_49()) {
+    jj_scanpos = xsp;
+    if (jj_3_50()) return true;
+    }
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3_51()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3_46() {
+    if (jj_scan_token(NEGATION)) return true;
+    return false;
+  }
+
+  private boolean jj_3_66() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_46()) jj_scanpos = xsp;
+    if (jj_scan_token(BRACKET_START)) return true;
+    xsp = jj_scanpos;
+    if (jj_3_63()) {
+    jj_scanpos = xsp;
+    if (jj_3_64()) {
+    jj_scanpos = xsp;
+    if (jj_3_65()) return true;
+    }
+    }
+    if (jj_scan_token(BRACKET_END)) return true;
+    return false;
+  }
+
+  private boolean jj_3_9() {
+    if (jj_scan_token(BRACKET_START)) return true;
+    if (jj_3R_7()) return true;
+    if (jj_scan_token(BRACKET_END)) return true;
+    return false;
+  }
+
+  private boolean jj_3_8() {
+    if (jj_3R_8()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_14() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_66()) {
+    jj_scanpos = xsp;
+    if (jj_3_67()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3_25() {
+    if (jj_3R_13()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_24()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3_7() {
+    if (jj_scan_token(NOT_WITHIN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_12() {
+    if (jj_scan_token(GROUP_START)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_25()) {
+    jj_scanpos = xsp;
+    if (jj_3_26()) return true;
+    }
+    if (jj_scan_token(GROUP_END)) return true;
+    xsp = jj_scanpos;
+    if (jj_3_30()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3_6() {
+    if (jj_scan_token(WITHIN)) return true;
+    return false;
+  }
+
+  private boolean jj_3_5() {
+    if (jj_scan_token(NOT_CONTAINING)) return true;
+    return false;
+  }
+
+  private boolean jj_3_4() {
+    if (jj_scan_token(CONTAINING)) return true;
+    return false;
+  }
+
+  private boolean jj_3_10() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_4()) {
+    jj_scanpos = xsp;
+    if (jj_3_5()) {
+    jj_scanpos = xsp;
+    if (jj_3_6()) {
+    jj_scanpos = xsp;
+    if (jj_3_7()) return true;
+    }
+    }
+    }
+    xsp = jj_scanpos;
+    if (jj_3_8()) {
+    jj_scanpos = xsp;
+    if (jj_3_9()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3_3() {
+    if (jj_scan_token(BRACKET_START)) return true;
+    if (jj_3R_7()) return true;
+    if (jj_scan_token(BRACKET_END)) return true;
+    return false;
+  }
+
+  private boolean jj_3_2() {
+    if (jj_3R_8()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_7() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_2()) {
+    jj_scanpos = xsp;
+    if (jj_3_3()) return true;
+    }
+    xsp = jj_scanpos;
+    if (jj_3_10()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3_23() {
+    if (jj_3R_12()) return true;
+    return false;
+  }
+
+  private boolean jj_3_44() {
+    if (jj_scan_token(QUESTION_MARK)) return true;
+    return false;
+  }
+
+  private boolean jj_3_22() {
+    if (jj_3R_11()) return true;
+    return false;
+  }
+
+  private boolean jj_3_43() {
+    if (jj_scan_token(CURLY_BRACKET_START)) return true;
+    if (jj_scan_token(NUMBER)) return true;
+    if (jj_scan_token(CURLY_BRACKET_END)) return true;
+    return false;
+  }
+
+  private boolean jj_3_42() {
+    if (jj_scan_token(CURLY_BRACKET_START)) return true;
+    if (jj_scan_token(NUMBER)) return true;
+    if (jj_scan_token(KOMMA)) return true;
+    if (jj_scan_token(NUMBER)) return true;
+    if (jj_scan_token(CURLY_BRACKET_END)) return true;
+    return false;
+  }
+
+  private boolean jj_3_21() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_22()) {
+    jj_scanpos = xsp;
+    if (jj_3_23()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3_45() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_42()) {
+    jj_scanpos = xsp;
+    if (jj_3_43()) {
+    jj_scanpos = xsp;
+    if (jj_3_44()) return true;
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3_72() {
+    if (jj_scan_token(TOKEN_EQUALS)) return true;
+    return false;
+  }
+
+  private boolean jj_3_20() {
+    if (jj_3R_12()) return true;
+    return false;
+  }
+
+  private boolean jj_3_71() {
+    if (jj_scan_token(TOKEN_NOTEQUALS)) return true;
+    return false;
+  }
+
+  private boolean jj_3_19() {
+    if (jj_3R_11()) return true;
+    return false;
+  }
+
+  private boolean jj_3_41() {
+    if (jj_scan_token(WORD_START)) return true;
+    if (jj_scan_token(WORD_END)) return true;
+    return false;
+  }
+
+  private boolean jj_3_38() {
+    if (jj_3R_14()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_9() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_19()) {
+    jj_scanpos = xsp;
+    if (jj_3_20()) return true;
+    }
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3_21()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3_74() {
+    if (jj_scan_token(UNQUOTED_VALUE)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_71()) {
+    jj_scanpos = xsp;
+    if (jj_3_72()) return true;
+    }
+    if (jj_scan_token(QUOTED_VALUE)) return true;
+    return false;
+  }
+
+  private boolean jj_3_34() {
+    if (jj_scan_token(OR)) return true;
+    if (jj_3R_14()) return true;
+    return false;
+  }
+
+  private boolean jj_3_1() {
+    if (jj_3R_7()) return true;
+    return false;
+  }
+
+  private boolean jj_3_36() {
+    if (jj_scan_token(OR)) return true;
+    if (jj_3R_14()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3_34()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3_33() {
+    if (jj_scan_token(AND)) return true;
+    if (jj_3R_14()) return true;
+    return false;
+  }
+
+  private boolean jj_3_17() {
+    if (jj_scan_token(OR)) return true;
+    return false;
+  }
+
+  private boolean jj_3_35() {
+    if (jj_scan_token(AND)) return true;
+    if (jj_3R_14()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3_33()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3_18() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_17()) jj_scanpos = xsp;
+    if (jj_3R_10()) return true;
+    return false;
+  }
+
+  private boolean jj_3_37() {
+    if (jj_3R_14()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_35()) {
+    jj_scanpos = xsp;
+    if (jj_3_36()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3_70() {
+    if (jj_scan_token(UNQUOTED_VALUE)) return true;
+    return false;
+  }
+
+  private boolean jj_3_69() {
+    if (jj_scan_token(NUMBER)) return true;
+    return false;
+  }
+
+  private boolean jj_3_40() {
+    if (jj_scan_token(WORD_START)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_37()) {
+    jj_scanpos = xsp;
+    if (jj_3_38()) return true;
+    }
+    if (jj_scan_token(WORD_END)) return true;
+    return false;
+  }
+
+  private boolean jj_3_39() {
+    if (jj_scan_token(QUOTED_VALUE)) return true;
+    return false;
+  }
+
+  private boolean jj_3_73() {
+    if (jj_scan_token(OCTOTHORPE)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_69()) {
+    jj_scanpos = xsp;
+    if (jj_3_70()) return true;
+    }
+    return false;
+  }
+
+  /** Generated Token Manager. */
+  public MtasCQLParserTokenManager token_source;
+  SimpleCharStream jj_input_stream;
+  /** Current token. */
+  public Token token;
+  /** Next token. */
+  public Token jj_nt;
+  private int jj_ntk;
+  private Token jj_scanpos, jj_lastpos;
+  private int jj_la;
+  private int jj_gen;
+  final private int[] jj_la1 = new int[0];
+  static private int[] jj_la1_0;
+  static {
+      jj_la1_init_0();
+   }
+   private static void jj_la1_init_0() {
+      jj_la1_0 = new int[] {};
+   }
+  final private JJCalls[] jj_2_rtns = new JJCalls[74];
+  private boolean jj_rescan = false;
+  private int jj_gc = 0;
+
+  /** Constructor with InputStream. */
+  public MtasCQLParser(java.io.InputStream stream) {
+     this(stream, null);
+  }
+  /** Constructor with InputStream and supplied encoding */
+  public MtasCQLParser(java.io.InputStream stream, String encoding) {
+    try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+    token_source = new MtasCQLParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 0; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** 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;
+    jj_gen = 0;
+    for (int i = 0; i < 0; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** Constructor. */
+  public MtasCQLParser(java.io.Reader stream) {
+    jj_input_stream = new SimpleCharStream(stream, 1, 1);
+    token_source = new MtasCQLParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 0; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** 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;
+    jj_gen = 0;
+    for (int i = 0; i < 0; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** Constructor with generated Token Manager. */
+  public MtasCQLParser(MtasCQLParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 0; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** Reinitialise. */
+  public void ReInit(MtasCQLParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 0; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  private Token jj_consume_token(int kind) throws ParseException {
+    Token oldToken;
+    if ((oldToken = token).next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    if (token.kind == kind) {
+      jj_gen++;
+      if (++jj_gc > 100) {
+        jj_gc = 0;
+        for (int i = 0; i < jj_2_rtns.length; i++) {
+          JJCalls c = jj_2_rtns[i];
+          while (c != null) {
+            if (c.gen < jj_gen) c.first = null;
+            c = c.next;
+          }
+        }
+      }
+      return token;
+    }
+    token = oldToken;
+    jj_kind = kind;
+    throw generateParseException();
+  }
+
+  static private final class LookaheadSuccess extends java.lang.Error { }
+  final private LookaheadSuccess jj_ls = new LookaheadSuccess();
+  private boolean jj_scan_token(int kind) {
+    if (jj_scanpos == jj_lastpos) {
+      jj_la--;
+      if (jj_scanpos.next == null) {
+        jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
+      } else {
+        jj_lastpos = jj_scanpos = jj_scanpos.next;
+      }
+    } else {
+      jj_scanpos = jj_scanpos.next;
+    }
+    if (jj_rescan) {
+      int i = 0; Token tok = token;
+      while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
+      if (tok != null) jj_add_error_token(kind, i);
+    }
+    if (jj_scanpos.kind != kind) return true;
+    if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
+    return false;
+  }
+
+
+/** Get the next Token. */
+  final public Token getNextToken() {
+    if (token.next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    jj_gen++;
+    return token;
+  }
+
+/** Get the specific Token. */
+  final public Token getToken(int index) {
+    Token t = token;
+    for (int i = 0; i < index; i++) {
+      if (t.next != null) t = t.next;
+      else t = t.next = token_source.getNextToken();
+    }
+    return t;
+  }
+
+  private int jj_ntk() {
+    if ((jj_nt=token.next) == null)
+      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
+    else
+      return (jj_ntk = jj_nt.kind);
+  }
+
+  private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>();
+  private int[] jj_expentry;
+  private int jj_kind = -1;
+  private int[] jj_lasttokens = new int[100];
+  private int jj_endpos;
+
+  private void jj_add_error_token(int kind, int pos) {
+    if (pos >= 100) return;
+    if (pos == jj_endpos + 1) {
+      jj_lasttokens[jj_endpos++] = kind;
+    } else if (jj_endpos != 0) {
+      jj_expentry = new int[jj_endpos];
+      for (int i = 0; i < jj_endpos; i++) {
+        jj_expentry[i] = jj_lasttokens[i];
+      }
+      jj_entries_loop: for (java.util.Iterator<?> it = jj_expentries.iterator(); it.hasNext();) {
+        int[] oldentry = (int[])(it.next());
+        if (oldentry.length == jj_expentry.length) {
+          for (int i = 0; i < jj_expentry.length; i++) {
+            if (oldentry[i] != jj_expentry[i]) {
+              continue jj_entries_loop;
+            }
+          }
+          jj_expentries.add(jj_expentry);
+          break jj_entries_loop;
+        }
+      }
+      if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
+    }
+  }
+
+  /** Generate ParseException. */
+  public ParseException generateParseException() {
+    jj_expentries.clear();
+    boolean[] la1tokens = new boolean[31];
+    if (jj_kind >= 0) {
+      la1tokens[jj_kind] = true;
+      jj_kind = -1;
+    }
+    for (int i = 0; i < 0; i++) {
+      if (jj_la1[i] == jj_gen) {
+        for (int j = 0; j < 32; j++) {
+          if ((jj_la1_0[i] & (1<<j)) != 0) {
+            la1tokens[j] = true;
+          }
+        }
+      }
+    }
+    for (int i = 0; i < 31; i++) {
+      if (la1tokens[i]) {
+        jj_expentry = new int[1];
+        jj_expentry[0] = i;
+        jj_expentries.add(jj_expentry);
+      }
+    }
+    jj_endpos = 0;
+    jj_rescan_token();
+    jj_add_error_token(0, 0);
+    int[][] exptokseq = new int[jj_expentries.size()][];
+    for (int i = 0; i < jj_expentries.size(); i++) {
+      exptokseq[i] = jj_expentries.get(i);
+    }
+    return new ParseException(token, exptokseq, tokenImage);
+  }
+
+  /** Enable tracing. */
+  final public void enable_tracing() {
+  }
+
+  /** Disable tracing. */
+  final public void disable_tracing() {
+  }
+
+  private void jj_rescan_token() {
+    jj_rescan = true;
+    for (int i = 0; i < 74; i++) {
+    try {
+      JJCalls p = jj_2_rtns[i];
+      do {
+        if (p.gen > jj_gen) {
+          jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
+          switch (i) {
+            case 0: jj_3_1(); break;
+            case 1: jj_3_2(); break;
+            case 2: jj_3_3(); break;
+            case 3: jj_3_4(); break;
+            case 4: jj_3_5(); break;
+            case 5: jj_3_6(); break;
+            case 6: jj_3_7(); break;
+            case 7: jj_3_8(); break;
+            case 8: jj_3_9(); break;
+            case 9: jj_3_10(); break;
+            case 10: jj_3_11(); break;
+            case 11: jj_3_12(); break;
+            case 12: jj_3_13(); break;
+            case 13: jj_3_14(); break;
+            case 14: jj_3_15(); break;
+            case 15: jj_3_16(); break;
+            case 16: jj_3_17(); break;
+            case 17: jj_3_18(); break;
+            case 18: jj_3_19(); break;
+            case 19: jj_3_20(); break;
+            case 20: jj_3_21(); break;
+            case 21: jj_3_22(); break;
+            case 22: jj_3_23(); break;
+            case 23: jj_3_24(); break;
+            case 24: jj_3_25(); break;
+            case 25: jj_3_26(); break;
+            case 26: jj_3_27(); break;
+            case 27: jj_3_28(); break;
+            case 28: jj_3_29(); break;
+            case 29: jj_3_30(); break;
+            case 30: jj_3_31(); break;
+            case 31: jj_3_32(); break;
+            case 32: jj_3_33(); break;
+            case 33: jj_3_34(); break;
+            case 34: jj_3_35(); break;
+            case 35: jj_3_36(); break;
+            case 36: jj_3_37(); break;
+            case 37: jj_3_38(); break;
+            case 38: jj_3_39(); break;
+            case 39: jj_3_40(); break;
+            case 40: jj_3_41(); break;
+            case 41: jj_3_42(); break;
+            case 42: jj_3_43(); break;
+            case 43: jj_3_44(); break;
+            case 44: jj_3_45(); break;
+            case 45: jj_3_46(); break;
+            case 46: jj_3_47(); break;
+            case 47: jj_3_48(); break;
+            case 48: jj_3_49(); break;
+            case 49: jj_3_50(); break;
+            case 50: jj_3_51(); break;
+            case 51: jj_3_52(); break;
+            case 52: jj_3_53(); break;
+            case 53: jj_3_54(); break;
+            case 54: jj_3_55(); break;
+            case 55: jj_3_56(); break;
+            case 56: jj_3_57(); break;
+            case 57: jj_3_58(); break;
+            case 58: jj_3_59(); break;
+            case 59: jj_3_60(); break;
+            case 60: jj_3_61(); break;
+            case 61: jj_3_62(); break;
+            case 62: jj_3_63(); break;
+            case 63: jj_3_64(); break;
+            case 64: jj_3_65(); break;
+            case 65: jj_3_66(); break;
+            case 66: jj_3_67(); break;
+            case 67: jj_3_68(); break;
+            case 68: jj_3_69(); break;
+            case 69: jj_3_70(); break;
+            case 70: jj_3_71(); break;
+            case 71: jj_3_72(); break;
+            case 72: jj_3_73(); break;
+            case 73: jj_3_74(); break;
+          }
+        }
+        p = p.next;
+      } while (p != null);
+      } catch(LookaheadSuccess ls) { }
+    }
+    jj_rescan = false;
+  }
+
+  private void jj_save(int index, int xla) {
+    JJCalls p = jj_2_rtns[index];
+    while (p.gen > jj_gen) {
+      if (p.next == null) { p = p.next = new JJCalls(); break; }
+      p = p.next;
+    }
+    p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
+  }
+
+  static final class JJCalls {
+    int gen;
+    Token first;
+    int arg;
+    JJCalls next;
+  }
+
+}
diff --git a/src/mtas/parser/cql/MtasCQLParser.jj b/src/mtas/parser/cql/MtasCQLParser.jj
index 8b45d7e..41199f2 100644
--- a/src/mtas/parser/cql/MtasCQLParser.jj
+++ b/src/mtas/parser/cql/MtasCQLParser.jj
@@ -8,8 +8,8 @@ options
   DEBUG_TOKEN_MANAGER = false;
 
   LOOKAHEAD= 1000;
-}
-
+} 
+ 
 PARSER_BEGIN(MtasCQLParser)
 package mtas.parser.cql;
 import mtas.analysis.token.MtasToken;
diff --git a/src/mtas/parser/cql/MtasCQLParserConstants.java b/src/mtas/parser/cql/MtasCQLParserConstants.java
new file mode 100644
index 0000000..e52ad32
--- /dev/null
+++ b/src/mtas/parser/cql/MtasCQLParserConstants.java
@@ -0,0 +1,104 @@
+/* Generated By:JavaCC: Do not edit this line. MtasCQLParserConstants.java */
+package mtas.parser.cql;
+
+
+/**
+ * Token literal values and constants.
+ * Generated by org.javacc.parser.OtherFilesGen#start()
+ */
+public interface MtasCQLParserConstants {
+
+  /** End of File. */
+  int EOF = 0;
+  /** RegularExpression Id. */
+  int CONTAINING = 5;
+  /** RegularExpression Id. */
+  int NOT_CONTAINING = 6;
+  /** RegularExpression Id. */
+  int WITHIN = 7;
+  /** RegularExpression Id. */
+  int NOT_WITHIN = 8;
+  /** RegularExpression Id. */
+  int GROUP_START = 9;
+  /** RegularExpression Id. */
+  int GROUP_END = 10;
+  /** RegularExpression Id. */
+  int WORD_START = 11;
+  /** RegularExpression Id. */
+  int WORD_END = 12;
+  /** RegularExpression Id. */
+  int BRACKET_START = 13;
+  /** RegularExpression Id. */
+  int BRACKET_END = 14;
+  /** RegularExpression Id. */
+  int CURLY_BRACKET_START = 15;
+  /** RegularExpression Id. */
+  int CURLY_BRACKET_END = 16;
+  /** RegularExpression Id. */
+  int SLASH = 17;
+  /** RegularExpression Id. */
+  int QUESTION_MARK = 18;
+  /** RegularExpression Id. */
+  int NEGATION = 19;
+  /** RegularExpression Id. */
+  int AND = 20;
+  /** RegularExpression Id. */
+  int OR = 21;
+  /** RegularExpression Id. */
+  int KOMMA = 22;
+  /** RegularExpression Id. */
+  int TOKEN_NOTEQUALS = 23;
+  /** RegularExpression Id. */
+  int TOKEN_EQUALS = 24;
+  /** RegularExpression Id. */
+  int NUMBER = 25;
+  /** RegularExpression Id. */
+  int QUOTED_VALUE = 26;
+  /** RegularExpression Id. */
+  int UNQUOTED_VALUE = 27;
+  /** RegularExpression Id. */
+  int OCTOTHORPE = 28;
+  /** RegularExpression Id. */
+  int DIGIT = 29;
+  /** RegularExpression Id. */
+  int ALLOWED_UNQUOTED_CHARACTER = 30;
+
+  /** Lexical state. */
+  int DEFAULT = 0;
+
+  /** Literal token values. */
+  String[] tokenImage = {
+    "<EOF>",
+    "\" \"",
+    "\"\\r\"",
+    "\"\\t\"",
+    "\"\\n\"",
+    "\"containing\"",
+    "\"!containing\"",
+    "\"within\"",
+    "\"!within\"",
+    "\"<\"",
+    "\">\"",
+    "\"[\"",
+    "\"]\"",
+    "\"(\"",
+    "\")\"",
+    "\"{\"",
+    "\"}\"",
+    "\"/\"",
+    "\"?\"",
+    "\"!\"",
+    "\"&\"",
+    "\"|\"",
+    "\",\"",
+    "\"!=\"",
+    "\"=\"",
+    "<NUMBER>",
+    "<QUOTED_VALUE>",
+    "<UNQUOTED_VALUE>",
+    "<OCTOTHORPE>",
+    "<DIGIT>",
+    "<ALLOWED_UNQUOTED_CHARACTER>",
+  };
+
+}
diff --git a/src/mtas/parser/cql/MtasCQLParserTokenManager.java b/src/mtas/parser/cql/MtasCQLParserTokenManager.java
new file mode 100644
index 0000000..a62f7dd
--- /dev/null
+++ b/src/mtas/parser/cql/MtasCQLParserTokenManager.java
@@ -0,0 +1,750 @@
+/* Generated By:JavaCC: Do not edit this line. MtasCQLParserTokenManager.java */
+package mtas.parser.cql;
+import mtas.analysis.token.MtasToken;
+import mtas.parser.cql.util.MtasCQLParserGroupCondition;
+import mtas.parser.cql.util.MtasCQLParserGroupFullCondition;
+import mtas.parser.cql.util.MtasCQLParserWordCondition;
+import mtas.parser.cql.util.MtasCQLParserWordPositionQuery;
+import mtas.parser.cql.util.MtasCQLParserWordFullCondition;
+import mtas.parser.cql.util.MtasCQLParserBasicSentenceCondition;
+import mtas.parser.cql.util.MtasCQLParserSentenceCondition;
+import mtas.parser.cql.util.MtasCQLParserSentencePartCondition;
+import mtas.parser.cql.util.MtasCQLParserGroupQuery;
+import mtas.parser.cql.util.MtasCQLParserWordQuery;
+import mtas.parser.cql.util.MtasCQLParserDefaultPrefixCondition;
+import org.apache.lucene.search.spans.SpanContainingQuery;
+import org.apache.lucene.search.spans.SpanNotQuery;
+import org.apache.lucene.search.spans.SpanQuery;
+import org.apache.lucene.search.spans.SpanWithinQuery;
+import org.apache.lucene.index.Term;
+import mtas.search.spans.MtasSpanSequenceItem;
+import mtas.search.spans.MtasSpanSequenceQuery;
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/** Token Manager. */
+public class MtasCQLParserTokenManager implements MtasCQLParserConstants
+{
+
+  /** Debug output. */
+  public  java.io.PrintStream debugStream = System.out;
+  /** Set debug output. */
+  public  void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
+private final int jjStopStringLiteralDfa_0(int pos, long active0)
+{
+   switch (pos)
+   {
+      case 0:
+         if ((active0 & 0xa0L) != 0L)
+         {
+            jjmatchedKind = 27;
+            return 6;
+         }
+         return -1;
+      case 1:
+         if ((active0 & 0xa0L) != 0L)
+         {
+            jjmatchedKind = 27;
+            jjmatchedPos = 1;
+            return 6;
+         }
+         return -1;
+      case 2:
+         if ((active0 & 0xa0L) != 0L)
+         {
+            jjmatchedKind = 27;
+            jjmatchedPos = 2;
+            return 6;
+         }
+         return -1;
+      case 3:
+         if ((active0 & 0xa0L) != 0L)
+         {
+            jjmatchedKind = 27;
+            jjmatchedPos = 3;
+            return 6;
+         }
+         return -1;
+      case 4:
+         if ((active0 & 0xa0L) != 0L)
+         {
+            jjmatchedKind = 27;
+            jjmatchedPos = 4;
+            return 6;
+         }
+         return -1;
+      case 5:
+         if ((active0 & 0x80L) != 0L)
+            return 6;
+         if ((active0 & 0x20L) != 0L)
+         {
+            jjmatchedKind = 27;
+            jjmatchedPos = 5;
+            return 6;
+         }
+         return -1;
+      case 6:
+         if ((active0 & 0x20L) != 0L)
+         {
+            jjmatchedKind = 27;
+            jjmatchedPos = 6;
+            return 6;
+         }
+         return -1;
+      case 7:
+         if ((active0 & 0x20L) != 0L)
+         {
+            jjmatchedKind = 27;
+            jjmatchedPos = 7;
+            return 6;
+         }
+         return -1;
+      case 8:
+         if ((active0 & 0x20L) != 0L)
+         {
+            jjmatchedKind = 27;
+            jjmatchedPos = 8;
+            return 6;
+         }
+         return -1;
+      case 9:
+         if ((active0 & 0x20L) != 0L)
+            return 6;
+         return -1;
+      default :
+         return -1;
+   }
+}
+private final int jjStartNfa_0(int pos, long active0)
+{
+   return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
+}
+private int jjStopAtPos(int pos, int kind)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   return pos + 1;
+}
+private int jjMoveStringLiteralDfa0_0()
+{
+   switch(curChar)
+   {
+      case 33:
+         jjmatchedKind = 19;
+         return jjMoveStringLiteralDfa1_0(0x800140L);
+      case 38:
+         return jjStopAtPos(0, 20);
+      case 40:
+         return jjStopAtPos(0, 13);
+      case 41:
+         return jjStopAtPos(0, 14);
+      case 44:
+         return jjStopAtPos(0, 22);
+      case 47:
+         return jjStopAtPos(0, 17);
+      case 60:
+         return jjStopAtPos(0, 9);
+      case 61:
+         return jjStopAtPos(0, 24);
+      case 62:
+         return jjStopAtPos(0, 10);
+      case 63:
+         return jjStopAtPos(0, 18);
+      case 91:
+         return jjStopAtPos(0, 11);
+      case 93:
+         return jjStopAtPos(0, 12);
+      case 99:
+         return jjMoveStringLiteralDfa1_0(0x20L);
+      case 119:
+         return jjMoveStringLiteralDfa1_0(0x80L);
+      case 123:
+         return jjStopAtPos(0, 15);
+      case 124:
+         return jjStopAtPos(0, 21);
+      case 125:
+         return jjStopAtPos(0, 16);
+      default :
+         return jjMoveNfa_0(1, 0);
+   }
+}
+private int jjMoveStringLiteralDfa1_0(long active0)
+{
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(0, active0);
+      return 1;
+   }
+   switch(curChar)
+   {
+      case 61:
+         if ((active0 & 0x800000L) != 0L)
+            return jjStopAtPos(1, 23);
+         break;
+      case 99:
+         return jjMoveStringLiteralDfa2_0(active0, 0x40L);
+      case 105:
+         return jjMoveStringLiteralDfa2_0(active0, 0x80L);
+      case 111:
+         return jjMoveStringLiteralDfa2_0(active0, 0x20L);
+      case 119:
+         return jjMoveStringLiteralDfa2_0(active0, 0x100L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(0, active0);
+}
+private int jjMoveStringLiteralDfa2_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(0, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(1, active0);
+      return 2;
+   }
+   switch(curChar)
+   {
+      case 105:
+         return jjMoveStringLiteralDfa3_0(active0, 0x100L);
+      case 110:
+         return jjMoveStringLiteralDfa3_0(active0, 0x20L);
+      case 111:
+         return jjMoveStringLiteralDfa3_0(active0, 0x40L);
+      case 116:
+         return jjMoveStringLiteralDfa3_0(active0, 0x80L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(1, active0);
+}
+private int jjMoveStringLiteralDfa3_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(1, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(2, active0);
+      return 3;
+   }
+   switch(curChar)
+   {
+      case 104:
+         return jjMoveStringLiteralDfa4_0(active0, 0x80L);
+      case 110:
+         return jjMoveStringLiteralDfa4_0(active0, 0x40L);
+      case 116:
+         return jjMoveStringLiteralDfa4_0(active0, 0x120L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(2, active0);
+}
+private int jjMoveStringLiteralDfa4_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(2, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(3, active0);
+      return 4;
+   }
+   switch(curChar)
+   {
+      case 97:
+         return jjMoveStringLiteralDfa5_0(active0, 0x20L);
+      case 104:
+         return jjMoveStringLiteralDfa5_0(active0, 0x100L);
+      case 105:
+         return jjMoveStringLiteralDfa5_0(active0, 0x80L);
+      case 116:
+         return jjMoveStringLiteralDfa5_0(active0, 0x40L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(3, active0);
+}
+private int jjMoveStringLiteralDfa5_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(3, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(4, active0);
+      return 5;
+   }
+   switch(curChar)
+   {
+      case 97:
+         return jjMoveStringLiteralDfa6_0(active0, 0x40L);
+      case 105:
+         return jjMoveStringLiteralDfa6_0(active0, 0x120L);
+      case 110:
+         if ((active0 & 0x80L) != 0L)
+            return jjStartNfaWithStates_0(5, 7, 6);
+         break;
+      default :
+         break;
+   }
+   return jjStartNfa_0(4, active0);
+}
+private int jjMoveStringLiteralDfa6_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(4, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(5, active0);
+      return 6;
+   }
+   switch(curChar)
+   {
+      case 105:
+         return jjMoveStringLiteralDfa7_0(active0, 0x40L);
+      case 110:
+         if ((active0 & 0x100L) != 0L)
+            return jjStopAtPos(6, 8);
+         return jjMoveStringLiteralDfa7_0(active0, 0x20L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(5, active0);
+}
+private int jjMoveStringLiteralDfa7_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(5, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(6, active0);
+      return 7;
+   }
+   switch(curChar)
+   {
+      case 105:
+         return jjMoveStringLiteralDfa8_0(active0, 0x20L);
+      case 110:
+         return jjMoveStringLiteralDfa8_0(active0, 0x40L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(6, active0);
+}
+private int jjMoveStringLiteralDfa8_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(6, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(7, active0);
+      return 8;
+   }
+   switch(curChar)
+   {
+      case 105:
+         return jjMoveStringLiteralDfa9_0(active0, 0x40L);
+      case 110:
+         return jjMoveStringLiteralDfa9_0(active0, 0x20L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(7, active0);
+}
+private int jjMoveStringLiteralDfa9_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(7, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(8, active0);
+      return 9;
+   }
+   switch(curChar)
+   {
+      case 103:
+         if ((active0 & 0x20L) != 0L)
+            return jjStartNfaWithStates_0(9, 5, 6);
+         break;
+      case 110:
+         return jjMoveStringLiteralDfa10_0(active0, 0x40L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(8, active0);
+}
+private int jjMoveStringLiteralDfa10_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(8, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(9, active0);
+      return 10;
+   }
+   switch(curChar)
+   {
+      case 103:
+         if ((active0 & 0x40L) != 0L)
+            return jjStopAtPos(10, 6);
+         break;
+      default :
+         break;
+   }
+   return jjStartNfa_0(9, active0);
+}
+private int jjStartNfaWithStates_0(int pos, int kind, int state)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) { return pos + 1; }
+   return jjMoveNfa_0(state, pos + 1);
+}
+static final long[] jjbitVec0 = {
+   0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec2 = {
+   0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+private int jjMoveNfa_0(int startState, int curPos)
+{
+   int startsAt = 0;
+   jjnewStateCnt = 8;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 1:
+                  if ((0x3ff600000000000L & l) != 0L)
+                  {
+                     if (kind > 27)
+                        kind = 27;
+                     jjCheckNAdd(6);
+                  }
+                  else if (curChar == 35)
+                  {
+                     if (kind > 28)
+                        kind = 28;
+                  }
+                  else if (curChar == 34)
+                     jjCheckNAddStates(0, 2);
+                  if ((0x3ff000000000000L & l) != 0L)
+                  {
+                     if (kind > 25)
+                        kind = 25;
+                     jjCheckNAdd(0);
+                  }
+                  break;
+               case 0:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 25)
+                     kind = 25;
+                  jjCheckNAdd(0);
+                  break;
+               case 3:
+                  jjCheckNAddStates(0, 2);
+                  break;
+               case 4:
+                  if ((0xfffffffbffffffffL & l) != 0L)
+                     jjCheckNAddStates(0, 2);
+                  break;
+               case 5:
+                  if (curChar == 34 && kind > 26)
+                     kind = 26;
+                  break;
+               case 6:
+                  if ((0x3ff600000000000L & l) == 0L)
+                     break;
+                  if (kind > 27)
+                     kind = 27;
+                  jjCheckNAdd(6);
+                  break;
+               case 7:
+                  if (curChar == 35 && kind > 28)
+                     kind = 28;
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 1:
+               case 6:
+                  if ((0x7fffffe87fffffeL & l) == 0L)
+                     break;
+                  if (kind > 27)
+                     kind = 27;
+                  jjCheckNAdd(6);
+                  break;
+               case 2:
+                  if (curChar == 92)
+                     jjstateSet[jjnewStateCnt++] = 3;
+                  break;
+               case 3:
+                  jjCheckNAddStates(0, 2);
+                  break;
+               case 4:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                     jjCheckNAddStates(0, 2);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = (int)(curChar >> 8);
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 077);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 3:
+               case 4:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                     jjCheckNAddStates(0, 2);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 8 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+static final int[] jjnextStates = {
+   2, 4, 5, 
+};
+private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
+{
+   switch(hiByte)
+   {
+      case 0:
+         return ((jjbitVec2[i2] & l2) != 0L);
+      default :
+         if ((jjbitVec0[i1] & l1) != 0L)
+            return true;
+         return false;
+   }
+}
+
+/** Token literal values. */
+public static final String[] jjstrLiteralImages = {
+"", null, null, null, null, "\143\157\156\164\141\151\156\151\156\147", 
+"\41\143\157\156\164\141\151\156\151\156\147", "\167\151\164\150\151\156", "\41\167\151\164\150\151\156", "\74", "\76", 
+"\133", "\135", "\50", "\51", "\173", "\175", "\57", "\77", "\41", "\46", "\174", 
+"\54", "\41\75", "\75", null, null, null, null, null, null, };
+
+/** Lexer state names. */
+public static final String[] lexStateNames = {
+   "DEFAULT",
+};
+static final long[] jjtoToken = {
+   0x1fffffe1L, 
+};
+static final long[] jjtoSkip = {
+   0x1eL, 
+};
+protected SimpleCharStream input_stream;
+private final int[] jjrounds = new int[8];
+private final int[] jjstateSet = new int[16];
+protected char curChar;
+/** Constructor. */
+public MtasCQLParserTokenManager(SimpleCharStream stream){
+   if (SimpleCharStream.staticFlag)
+      throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+   input_stream = stream;
+}
+
+/** Constructor. */
+public MtasCQLParserTokenManager(SimpleCharStream stream, int lexState){
+   this(stream);
+   SwitchTo(lexState);
+}
+
+/** Reinitialise parser. */
+public void ReInit(SimpleCharStream stream)
+{
+   jjmatchedPos = jjnewStateCnt = 0;
+   curLexState = defaultLexState;
+   input_stream = stream;
+   ReInitRounds();
+}
+private void ReInitRounds()
+{
+   int i;
+   jjround = 0x80000001;
+   for (i = 8; i-- > 0;)
+      jjrounds[i] = 0x80000000;
+}
+
+/** Reinitialise parser. */
+public void ReInit(SimpleCharStream stream, int lexState)
+{
+   ReInit(stream);
+   SwitchTo(lexState);
+}
+
+/** Switch to specified lex state. */
+public void SwitchTo(int lexState)
+{
+   if (lexState >= 1 || lexState < 0)
+      throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+   else
+      curLexState = lexState;
+}
+
+protected Token jjFillToken()
+{
+   final Token t;
+   final String curTokenImage;
+   final int beginLine;
+   final int endLine;
+   final int beginColumn;
+   final int endColumn;
+   String im = jjstrLiteralImages[jjmatchedKind];
+   curTokenImage = (im == null) ? input_stream.GetImage() : im;
+   beginLine = input_stream.getBeginLine();
+   beginColumn = input_stream.getBeginColumn();
+   endLine = input_stream.getEndLine();
+   endColumn = input_stream.getEndColumn();
+   t = Token.newToken(jjmatchedKind, curTokenImage);
+
+   t.beginLine = beginLine;
+   t.endLine = endLine;
+   t.beginColumn = beginColumn;
+   t.endColumn = endColumn;
+
+   return t;
+}
+
+int curLexState = 0;
+int defaultLexState = 0;
+int jjnewStateCnt;
+int jjround;
+int jjmatchedPos;
+int jjmatchedKind;
+
+/** Get the next Token. */
+public Token getNextToken() 
+{
+  Token matchedToken;
+  int curPos = 0;
+
+  EOFLoop :
+  for (;;)
+  {
+   try
+   {
+      curChar = input_stream.BeginToken();
+   }
+   catch(java.io.IOException e)
+   {
+      jjmatchedKind = 0;
+      matchedToken = jjFillToken();
+      return matchedToken;
+   }
+
+   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();
+   if (jjmatchedKind != 0x7fffffff)
+   {
+      if (jjmatchedPos + 1 < curPos)
+         input_stream.backup(curPos - jjmatchedPos - 1);
+      if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+      {
+         matchedToken = jjFillToken();
+         return matchedToken;
+      }
+      else
+      {
+         continue EOFLoop;
+      }
+   }
+   int error_line = input_stream.getEndLine();
+   int error_column = input_stream.getEndColumn();
+   String error_after = null;
+   boolean EOFSeen = false;
+   try { input_stream.readChar(); input_stream.backup(1); }
+   catch (java.io.IOException e1) {
+      EOFSeen = true;
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+      if (curChar == '\n' || curChar == '\r') {
+         error_line++;
+         error_column = 0;
+      }
+      else
+         error_column++;
+   }
+   if (!EOFSeen) {
+      input_stream.backup(1);
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+   }
+   throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
+  }
+}
+
+private void jjCheckNAdd(int state)
+{
+   if (jjrounds[state] != jjround)
+   {
+      jjstateSet[jjnewStateCnt++] = state;
+      jjrounds[state] = jjround;
+   }
+}
+private void jjAddStates(int start, int end)
+{
+   do {
+      jjstateSet[jjnewStateCnt++] = jjnextStates[start];
+   } while (start++ != end);
+}
+private void jjCheckNAddTwoStates(int state1, int state2)
+{
+   jjCheckNAdd(state1);
+   jjCheckNAdd(state2);
+}
+
+private void jjCheckNAddStates(int start, int end)
+{
+   do {
+      jjCheckNAdd(jjnextStates[start]);
+   } while (start++ != end);
+}
+
+}
diff --git a/src/mtas/parser/cql/ParseException.java b/src/mtas/parser/cql/ParseException.java
new file mode 100644
index 0000000..f8c628c
--- /dev/null
+++ b/src/mtas/parser/cql/ParseException.java
@@ -0,0 +1,187 @@
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 5.0 */
+/* JavaCCOptions:KEEP_LINE_COL=null */
+package mtas.parser.cql;
+
+/**
+ * This exception is thrown when parse errors are encountered.
+ * You can explicitly create objects of this exception type by
+ * calling the method generateParseException in the generated
+ * parser.
+ *
+ * You can modify this class to customize your error reporting
+ * mechanisms so long as you retain the public fields.
+ */
+public class ParseException extends Exception {
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * This constructor is used by the method "generateParseException"
+   * in the generated parser.  Calling this constructor generates
+   * a new object of this type with the fields "currentToken",
+   * "expectedTokenSequences", and "tokenImage" set.
+   */
+  public ParseException(Token currentTokenVal,
+                        int[][] expectedTokenSequencesVal,
+                        String[] tokenImageVal
+                       )
+  {
+    super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
+    currentToken = currentTokenVal;
+    expectedTokenSequences = expectedTokenSequencesVal;
+    tokenImage = tokenImageVal;
+  }
+
+  /**
+   * The following constructors are for use by you for whatever
+   * purpose you can think of.  Constructing the exception in this
+   * manner makes the exception behave in the normal way - i.e., as
+   * documented in the class "Throwable".  The fields "errorToken",
+   * "expectedTokenSequences", and "tokenImage" do not contain
+   * relevant information.  The JavaCC generated code does not use
+   * these constructors.
+   */
+
+  public ParseException() {
+    super();
+  }
+
+  /** Constructor with message. */
+  public ParseException(String message) {
+    super(message);
+  }
+
+
+  /**
+   * This is the last token that has been consumed successfully.  If
+   * this object has been created due to a parse error, the token
+   * followng this token will (therefore) be the first error token.
+   */
+  public Token currentToken;
+
+  /**
+   * Each entry in this array is an array of integers.  Each array
+   * of integers represents a sequence of tokens (by their ordinal
+   * values) that is expected at this point of the parse.
+   */
+  public int[][] expectedTokenSequences;
+
+  /**
+   * This is a reference to the "tokenImage" array of the generated
+   * parser within which the parse error occurred.  This array is
+   * defined in the generated ...Constants interface.
+   */
+  public String[] tokenImage;
+
+  /**
+   * It uses "currentToken" and "expectedTokenSequences" to generate a parse
+   * error message and returns it.  If this object has been created
+   * due to a parse error, and you do not catch it (it gets thrown
+   * from the parser) the correct error message
+   * gets displayed.
+   */
+  private static String initialise(Token currentToken,
+                           int[][] expectedTokenSequences,
+                           String[] tokenImage) {
+    String eol = System.getProperty("line.separator", "\n");
+    StringBuffer expected = new StringBuffer();
+    int maxSize = 0;
+    for (int i = 0; i < expectedTokenSequences.length; i++) {
+      if (maxSize < expectedTokenSequences[i].length) {
+        maxSize = expectedTokenSequences[i].length;
+      }
+      for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+        expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
+      }
+      if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+        expected.append("...");
+      }
+      expected.append(eol).append("    ");
+    }
+    String retval = "Encountered \"";
+    Token tok = currentToken.next;
+    for (int i = 0; i < maxSize; i++) {
+      if (i != 0) retval += " ";
+      if (tok.kind == 0) {
+        retval += tokenImage[0];
+        break;
+      }
+      retval += " " + tokenImage[tok.kind];
+      retval += " \"";
+      retval += add_escapes(tok.image);
+      retval += " \"";
+      tok = tok.next;
+    }
+    retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+    retval += "." + eol;
+    if (expectedTokenSequences.length == 1) {
+      retval += "Was expecting:" + eol + "    ";
+    } else {
+      retval += "Was expecting one of:" + eol + "    ";
+    }
+    retval += expected.toString();
+    return retval;
+  }
+
+  /**
+   * The end of line string for this machine.
+   */
+  protected String eol = System.getProperty("line.separator", "\n");
+
+  /**
+   * Used to convert raw characters to their escaped version
+   * when these raw version cannot be used as part of an ASCII
+   * string literal.
+   */
+  static String add_escapes(String str) {
+      StringBuffer retval = new StringBuffer();
+      char ch;
+      for (int i = 0; i < str.length(); i++) {
+        switch (str.charAt(i))
+        {
+           case 0 :
+              continue;
+           case '\b':
+              retval.append("\\b");
+              continue;
+           case '\t':
+              retval.append("\\t");
+              continue;
+           case '\n':
+              retval.append("\\n");
+              continue;
+           case '\f':
+              retval.append("\\f");
+              continue;
+           case '\r':
+              retval.append("\\r");
+              continue;
+           case '\"':
+              retval.append("\\\"");
+              continue;
+           case '\'':
+              retval.append("\\\'");
+              continue;
+           case '\\':
+              retval.append("\\\\");
+              continue;
+           default:
+              if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+                 String s = "0000" + Integer.toString(ch, 16);
+                 retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+              } else {
+                 retval.append(ch);
+              }
+              continue;
+        }
+      }
+      return retval.toString();
+   }
+
+}
+/* JavaCC - OriginalChecksum=a5744d0f598c98bc282befd42ee797ff (do not edit this line) */
diff --git a/src/mtas/parser/cql/SimpleCharStream.java b/src/mtas/parser/cql/SimpleCharStream.java
new file mode 100644
index 0000000..8f5ab97
--- /dev/null
+++ b/src/mtas/parser/cql/SimpleCharStream.java
@@ -0,0 +1,471 @@
+/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */
+/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package mtas.parser.cql;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (without unicode processing).
+ */
+
+public class SimpleCharStream
+{
+/** Whether parser is static. */
+  public static final boolean staticFlag = false;
+  int bufsize;
+  int available;
+  int tokenBegin;
+/** Position in buffer. */
+  public int bufpos = -1;
+  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[] buffer;
+  protected int maxNextCharInd = 0;
+  protected int inBuf = 0;
+  protected int tabSize = 8;
+
+  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;
+
+        maxNextCharInd = (bufpos += (bufsize - tokenBegin));
+      }
+      else
+      {
+        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+        buffer = newbuffer;
+
+        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+        bufline = newbufline;
+
+        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+        bufcolumn = newbufcolumn;
+
+        maxNextCharInd = (bufpos -= tokenBegin);
+      }
+    }
+    catch (Throwable t)
+    {
+      throw new Error(t.getMessage());
+    }
+
+
+    bufsize += 2048;
+    available = bufsize;
+    tokenBegin = 0;
+  }
+
+  protected void FillBuff() throws java.io.IOException
+  {
+    if (maxNextCharInd == available)
+    {
+      if (available == bufsize)
+      {
+        if (tokenBegin > 2048)
+        {
+          bufpos = maxNextCharInd = 0;
+          available = tokenBegin;
+        }
+        else if (tokenBegin < 0)
+          bufpos = maxNextCharInd = 0;
+        else
+          ExpandBuff(false);
+      }
+      else if (available > tokenBegin)
+        available = bufsize;
+      else if ((tokenBegin - available) < 2048)
+        ExpandBuff(true);
+      else
+        available = tokenBegin;
+    }
+
+    int i;
+    try {
+      if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
+      {
+        inputStream.close();
+        throw new java.io.IOException();
+      }
+      else
+        maxNextCharInd += i;
+      return;
+    }
+    catch(java.io.IOException e) {
+      --bufpos;
+      backup(0);
+      if (tokenBegin == -1)
+        tokenBegin = bufpos;
+      throw e;
+    }
+  }
+
+/** Start. */
+  public char BeginToken() throws java.io.IOException
+  {
+    tokenBegin = -1;
+    char c = readChar();
+    tokenBegin = bufpos;
+
+    return c;
+  }
+
+  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);
+    }
+
+    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];
+    }
+
+    if (++bufpos >= maxNextCharInd)
+      FillBuff();
+
+    char c = buffer[bufpos];
+
+    UpdateLineColumn(c);
+    return c;
+  }
+
+  @Deprecated
+  /**
+   * @deprecated
+   * @see #getEndColumn
+   */
+
+  public int getColumn() {
+    return bufcolumn[bufpos];
+  }
+
+  @Deprecated
+  /**
+   * @deprecated
+   * @see #getEndLine
+   */
+
+  public int getLine() {
+    return bufline[bufpos];
+  }
+
+  /** Get token end column number. */
+  public int getEndColumn() {
+    return bufcolumn[bufpos];
+  }
+
+  /** Get token end line number. */
+  public int getEndLine() {
+     return bufline[bufpos];
+  }
+
+  /** Get token beginning column number. */
+  public int getBeginColumn() {
+    return bufcolumn[tokenBegin];
+  }
+
+  /** Get token beginning line number. */
+  public int getBeginLine() {
+    return bufline[tokenBegin];
+  }
+
+/** Backup a number of characters. */
+  public void backup(int amount) {
+
+    inBuf += amount;
+    if ((bufpos -= amount) < 0)
+      bufpos += bufsize;
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(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];
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream, int startline,
+                          int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader 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];
+    }
+    prevCharIsLF = prevCharIsCR = false;
+    tokenBegin = inBuf = maxNextCharInd = 0;
+    bufpos = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream, int startline,
+                     int startcolumn)
+  {
+    ReInit(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+  /** Constructor. */
+  public SimpleCharStream(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 SimpleCharStream(java.io.InputStream dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+                          int startcolumn) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, int startline,
+                          int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, 1, 1, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream)
+  {
+    this(dstream, 1, 1, 4096);
+  }
+
+  /** 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) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(dstream, encoding, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+  /** 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);
+  }
+  /** Get token literal value. */
+  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);
+  }
+
+  /** Get the 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;
+  }
+
+  /** Reset buffer when finished. */
+  public void Done()
+  {
+    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;
+      }
+    }
+
+    line = bufline[j];
+    column = bufcolumn[j];
+  }
+
+}
+/* JavaCC - OriginalChecksum=684019f26036db3f6d2af88727527a69 (do not edit this line) */
diff --git a/src/mtas/parser/cql/Token.java b/src/mtas/parser/cql/Token.java
new file mode 100644
index 0000000..44b780e
--- /dev/null
+++ b/src/mtas/parser/cql/Token.java
@@ -0,0 +1,131 @@
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */
+/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package mtas.parser.cql;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token implements java.io.Serializable {
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * An integer that describes the kind of this token.  This numbering
+   * system is determined by JavaCCParser, and a table of these numbers is
+   * stored in the file ...Constants.java.
+   */
+  public int kind;
+
+  /** The line number of the first character of this Token. */
+  public int beginLine;
+  /** The column number of the first character of this Token. */
+  public int beginColumn;
+  /** The line number of the last character of this Token. */
+  public int endLine;
+  /** The column number of the last character of this Token. */
+  public int endColumn;
+
+  /**
+   * The string image of the token.
+   */
+  public String image;
+
+  /**
+   * A reference to the next regular (non-special) token from the input
+   * stream.  If this is the last token from the input stream, or if the
+   * token manager has not read tokens beyond this one, this field is
+   * set to null.  This is true only if this token is also a regular
+   * token.  Otherwise, see below for a description of the contents of
+   * this field.
+   */
+  public Token next;
+
+  /**
+   * This field is used to access special tokens that occur prior to this
+   * token, but after the immediately preceding regular (non-special) token.
+   * If there are no such special tokens, this field is set to null.
+   * When there are more than one such special token, this field refers
+   * to the last of these special tokens, which in turn refers to the next
+   * previous special token through its specialToken field, and so on
+   * until the first special token (whose specialToken field is null).
+   * The next fields of special tokens refer to other special tokens that
+   * immediately follow it (without an intervening regular token).  If there
+   * is no such token, this field is null.
+   */
+  public Token specialToken;
+
+  /**
+   * An optional attribute value of the Token.
+   * Tokens which are not used as syntactic sugar will often contain
+   * meaningful values that will be used later on by the compiler or
+   * interpreter. This attribute value is often different from the image.
+   * Any subclass of Token that actually wants to return a non-null value can
+   * override this method as appropriate.
+   */
+  public Object getValue() {
+    return null;
+  }
+
+  /**
+   * No-argument constructor
+   */
+  public Token() {}
+
+  /**
+   * Constructs a new token for the specified Image.
+   */
+  public Token(int kind)
+  {
+    this(kind, null);
+  }
+
+  /**
+   * Constructs a new token for the specified Image and Kind.
+   */
+  public Token(int kind, String image)
+  {
+    this.kind = kind;
+    this.image = image;
+  }
+
+  /**
+   * Returns the image.
+   */
+  public String toString()
+  {
+    return image;
+  }
+
+  /**
+   * Returns a new Token object, by default. However, if you want, you
+   * can create and return subclass objects based on the value of ofKind.
+   * Simply add the cases to the switch for all those special cases.
+   * For example, if you have a subclass of Token called IDToken that
+   * you want to create if ofKind is ID, simply add something like :
+   *
+   *    case MyParserConstants.ID : return new IDToken(ofKind, image);
+   *
+   * to the following switch statement. Then you can cast matchedToken
+   * variable to the appropriate type and use sit in your lexical actions.
+   */
+  public static Token newToken(int ofKind, String image)
+  {
+    switch(ofKind)
+    {
+      default : return new Token(ofKind, image);
+    }
+  }
+
+  public static Token newToken(int ofKind)
+  {
+    return newToken(ofKind, null);
+  }
+
+}
+/* JavaCC - OriginalChecksum=e03311f40a067ab1c4ea0bcdd2b5d3be (do not edit this line) */
diff --git a/src/mtas/parser/cql/TokenMgrError.java b/src/mtas/parser/cql/TokenMgrError.java
new file mode 100644
index 0000000..83a720f
--- /dev/null
+++ b/src/mtas/parser/cql/TokenMgrError.java
@@ -0,0 +1,147 @@
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */
+/* JavaCCOptions: */
+package mtas.parser.cql;
+
+/** Token Manager Error. */
+public class TokenMgrError extends Error
+{
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /*
+   * Ordinals for various reasons why an Error of this type can be thrown.
+   */
+
+  /**
+   * Lexical error occurred.
+   */
+  static final int LEXICAL_ERROR = 0;
+
+  /**
+   * An attempt was made to create a second instance of a static token manager.
+   */
+  static final int STATIC_LEXER_ERROR = 1;
+
+  /**
+   * Tried to change to an invalid lexical state.
+   */
+  static final int INVALID_LEXICAL_STATE = 2;
+
+  /**
+   * Detected (and bailed out of) an infinite loop in the token manager.
+   */
+  static final int LOOP_DETECTED = 3;
+
+  /**
+   * Indicates the reason why the exception is thrown. It will have
+   * one of the above 4 values.
+   */
+  int errorCode;
+
+  /**
+   * Replaces unprintable characters by their escaped (or unicode escaped)
+   * equivalents in the given string
+   */
+  protected static final String addEscapes(String str) {
+    StringBuffer retval = new StringBuffer();
+    char ch;
+    for (int i = 0; i < str.length(); i++) {
+      switch (str.charAt(i))
+      {
+        case 0 :
+          continue;
+        case '\b':
+          retval.append("\\b");
+          continue;
+        case '\t':
+          retval.append("\\t");
+          continue;
+        case '\n':
+          retval.append("\\n");
+          continue;
+        case '\f':
+          retval.append("\\f");
+          continue;
+        case '\r':
+          retval.append("\\r");
+          continue;
+        case '\"':
+          retval.append("\\\"");
+          continue;
+        case '\'':
+          retval.append("\\\'");
+          continue;
+        case '\\':
+          retval.append("\\\\");
+          continue;
+        default:
+          if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+            String s = "0000" + Integer.toString(ch, 16);
+            retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+          } else {
+            retval.append(ch);
+          }
+          continue;
+      }
+    }
+    return retval.toString();
+  }
+
+  /**
+   * Returns a detailed message for the Error when it is thrown by the
+   * token manager to indicate a lexical error.
+   * Parameters :
+   *    EOFSeen     : indicates if EOF caused the lexical error
+   *    curLexState : lexical state in which this error occurred
+   *    errorLine   : line number when the error occurred
+   *    errorColumn : column number when the error occurred
+   *    errorAfter  : prefix that was seen before this error occurred
+   *    curchar     : the offending character
+   * Note: You can customize the lexical error message by modifying this method.
+   */
+  protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
+    return("Lexical error at line " +
+          errorLine + ", column " +
+          errorColumn + ".  Encountered: " +
+          (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+          "after : \"" + addEscapes(errorAfter) + "\"");
+  }
+
+  /**
+   * You can also modify the body of this method to customize your error messages.
+   * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+   * of end-users concern, so you can return something like :
+   *
+   *     "Internal Error : Please file a bug report .... "
+   *
+   * from this method for such cases in the release version of your parser.
+   */
+  public String getMessage() {
+    return super.getMessage();
+  }
+
+  /*
+   * Constructors of various flavors follow.
+   */
+
+  /** No arg constructor. */
+  public TokenMgrError() {
+  }
+
+  /** Constructor with message and reason. */
+  public TokenMgrError(String message, int reason) {
+    super(message);
+    errorCode = reason;
+  }
+
+  /** Full Constructor. */
+  public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
+    this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+  }
+}
+/* JavaCC - OriginalChecksum=e6fb0e781afa8bd7df734ee8575150b6 (do not edit this line) */
diff --git a/src/mtas/parser/function/MtasFunctionParser.java b/src/mtas/parser/function/MtasFunctionParser.java
new file mode 100644
index 0000000..4e0783c
--- /dev/null
+++ b/src/mtas/parser/function/MtasFunctionParser.java
@@ -0,0 +1,648 @@
+/* Generated By:JavaCC: Do not edit this line. MtasFunctionParser.java */
+package mtas.parser.function;
+import mtas.codec.util.CodecUtil;
+import mtas.parser.function.util.MtasFunctionParserFunction;
+import mtas.parser.function.util.MtasFunctionParserFunctionBasic;
+import mtas.parser.function.util.MtasFunctionParserItem;
+import java.io.IOException;
+
+public class MtasFunctionParser implements MtasFunctionParserConstants {
+  public MtasFunctionParserFunction parse() throws ParseException
+  {
+    MtasFunctionParserFunction pf = parserFunction();
+    pf.close();
+    return pf;
+  }
+
+  final private MtasFunctionParserFunction parserFunction() throws ParseException, ParseException {
+  MtasFunctionParserFunction pf;
+    pf = parserFunctionBasic();
+    jj_consume_token(0);
+    {if (true) return pf;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final private MtasFunctionParserFunction parserFunctionBasic() throws ParseException, ParseException {
+  Token v, operator;
+  long vLong;
+  double vDouble;
+  MtasFunctionParserItem item;
+  MtasFunctionParserFunctionBasic pf;
+    item = parserFunctionItem();
+    pf = new MtasFunctionParserFunctionBasic(item);
+    label_1:
+    while (true) {
+      if (jj_2_1(100)) {
+        ;
+      } else {
+        break label_1;
+      }
+      if (jj_2_2(100)) {
+        operator = jj_consume_token(BASIC_OPERATOR_ADD);
+        item = parserFunctionItem();
+      pf.add(item);
+      } else if (jj_2_3(100)) {
+        operator = jj_consume_token(BASIC_OPERATOR_SUBTRACT);
+        item = parserFunctionItem();
+      pf.subtract(item);
+      } else if (jj_2_4(100)) {
+        operator = jj_consume_token(BASIC_OPERATOR_MULTIPLY);
+        item = parserFunctionItem();
+      pf.multiply(item);
+      } else if (jj_2_5(100)) {
+        operator = jj_consume_token(BASIC_OPERATOR_DIVIDE);
+        item = parserFunctionItem();
+      pf.divide(item);
+      } else if (jj_2_6(100)) {
+        operator = jj_consume_token(BASIC_OPERATOR_POWER);
+        item = parserFunctionItem();
+      pf.power(item);
+      } else if (jj_2_7(100)) {
+        v = jj_consume_token(LONG);
+      vLong = Long.parseLong(v.image);
+      if (vLong > 0)
+      {
+        {if (true) throw new ParseException("only negative");}
+      }
+      else
+      {
+        item = new MtasFunctionParserItem(MtasFunctionParserItem.TYPE_CONSTANT_LONG, - 1 * vLong);
+        pf.subtract(item);
+      }
+      } else if (jj_2_8(100)) {
+        v = jj_consume_token(DOUBLE);
+      vDouble = Double.parseDouble(v.image);
+      if (vDouble > 0)
+      {
+        {if (true) throw new ParseException("only negative");}
+      }
+      else
+      {
+        item = new MtasFunctionParserItem(MtasFunctionParserItem.TYPE_CONSTANT_DOUBLE, - 1 * vDouble);
+        pf.subtract(item);
+      }
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+    }
+    {if (true) return pf;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final private MtasFunctionParserItem parserFunctionItem() throws ParseException, ParseException {
+  Token v;
+  long vLong;
+  int vInt;
+  double vDouble;
+  String type;
+  MtasFunctionParserItem item;
+  MtasFunctionParserFunction pf;
+    if (jj_2_9(100)) {
+      v = jj_consume_token(VARIABLE);
+      vInt = Integer.parseInt(v.image.substring(2));
+      item = new MtasFunctionParserItem(MtasFunctionParserItem.TYPE_ARGUMENT, vInt);
+      {if (true) return item;}
+    } else if (jj_2_10(100)) {
+      jj_consume_token(N);
+      item = new MtasFunctionParserItem(MtasFunctionParserItem.TYPE_N);
+      {if (true) return item;}
+    } else if (jj_2_11(100)) {
+      v = jj_consume_token(LONG);
+      vLong = Long.parseLong(v.image);
+      item = new MtasFunctionParserItem(MtasFunctionParserItem.TYPE_CONSTANT_LONG, vLong);
+      {if (true) return item;}
+    } else if (jj_2_12(100)) {
+      v = jj_consume_token(DOUBLE);
+      vDouble = Double.parseDouble(v.image);
+      item = new MtasFunctionParserItem(MtasFunctionParserItem.TYPE_CONSTANT_DOUBLE, vDouble);
+      {if (true) return item;}
+    } else if (jj_2_13(100)) {
+      jj_consume_token(BRACKET_START);
+      pf = parserFunctionBasic();
+      jj_consume_token(BRACKET_END);
+      type = pf.getType();
+      if (type.equals(CodecUtil.DATA_TYPE_LONG))
+      {
+        item = new MtasFunctionParserItem(MtasFunctionParserItem.TYPE_PARSER_LONG, pf);
+        {if (true) return item;}
+      }
+      else if (type.equals(CodecUtil.DATA_TYPE_DOUBLE))
+      {
+        item = new MtasFunctionParserItem(MtasFunctionParserItem.TYPE_PARSER_DOUBLE, pf);
+        {if (true) return item;}
+      }
+      else
+      {
+        {if (true) throw new ParseException("unknown dataType");}
+      }
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    {if (true) throw new ParseException("unknown type");}
+    throw new Error("Missing return statement in function");
+  }
+
+  private boolean jj_2_1(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_1(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(0, xla); }
+  }
+
+  private boolean jj_2_2(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_2(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(1, xla); }
+  }
+
+  private boolean jj_2_3(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_3(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(2, xla); }
+  }
+
+  private boolean jj_2_4(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_4(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(3, xla); }
+  }
+
+  private boolean jj_2_5(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_5(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(4, xla); }
+  }
+
+  private boolean jj_2_6(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_6(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(5, xla); }
+  }
+
+  private boolean jj_2_7(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_7(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(6, xla); }
+  }
+
+  private boolean jj_2_8(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_8(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(7, xla); }
+  }
+
+  private boolean jj_2_9(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_9(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(8, xla); }
+  }
+
+  private boolean jj_2_10(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_10(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(9, xla); }
+  }
+
+  private boolean jj_2_11(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_11(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(10, xla); }
+  }
+
+  private boolean jj_2_12(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_12(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(11, xla); }
+  }
+
+  private boolean jj_2_13(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_13(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(12, xla); }
+  }
+
+  private boolean jj_3R_2() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_9()) {
+    jj_scanpos = xsp;
+    if (jj_3_10()) {
+    jj_scanpos = xsp;
+    if (jj_3_11()) {
+    jj_scanpos = xsp;
+    if (jj_3_12()) {
+    jj_scanpos = xsp;
+    if (jj_3_13()) return true;
+    }
+    }
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3_12() {
+    if (jj_scan_token(DOUBLE)) return true;
+    return false;
+  }
+
+  private boolean jj_3_6() {
+    if (jj_scan_token(BASIC_OPERATOR_POWER)) return true;
+    if (jj_3R_2()) return true;
+    return false;
+  }
+
+  private boolean jj_3_1() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_2()) {
+    jj_scanpos = xsp;
+    if (jj_3_3()) {
+    jj_scanpos = xsp;
+    if (jj_3_4()) {
+    jj_scanpos = xsp;
+    if (jj_3_5()) {
+    jj_scanpos = xsp;
+    if (jj_3_6()) {
+    jj_scanpos = xsp;
+    if (jj_3_7()) {
+    jj_scanpos = xsp;
+    if (jj_3_8()) return true;
+    }
+    }
+    }
+    }
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3_2() {
+    if (jj_scan_token(BASIC_OPERATOR_ADD)) return true;
+    if (jj_3R_2()) return true;
+    return false;
+  }
+
+  private boolean jj_3_8() {
+    if (jj_scan_token(DOUBLE)) return true;
+    return false;
+  }
+
+  private boolean jj_3_11() {
+    if (jj_scan_token(LONG)) return true;
+    return false;
+  }
+
+  private boolean jj_3_5() {
+    if (jj_scan_token(BASIC_OPERATOR_DIVIDE)) return true;
+    if (jj_3R_2()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_3() {
+    if (jj_3R_2()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3_1()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3_10() {
+    if (jj_scan_token(N)) return true;
+    return false;
+  }
+
+  private boolean jj_3_4() {
+    if (jj_scan_token(BASIC_OPERATOR_MULTIPLY)) return true;
+    if (jj_3R_2()) return true;
+    return false;
+  }
+
+  private boolean jj_3_13() {
+    if (jj_scan_token(BRACKET_START)) return true;
+    if (jj_3R_3()) return true;
+    if (jj_scan_token(BRACKET_END)) return true;
+    return false;
+  }
+
+  private boolean jj_3_7() {
+    if (jj_scan_token(LONG)) return true;
+    return false;
+  }
+
+  private boolean jj_3_9() {
+    if (jj_scan_token(VARIABLE)) return true;
+    return false;
+  }
+
+  private boolean jj_3_3() {
+    if (jj_scan_token(BASIC_OPERATOR_SUBTRACT)) return true;
+    if (jj_3R_2()) return true;
+    return false;
+  }
+
+  /** Generated Token Manager. */
+  public MtasFunctionParserTokenManager token_source;
+  SimpleCharStream jj_input_stream;
+  /** Current token. */
+  public Token token;
+  /** Next token. */
+  public Token jj_nt;
+  private int jj_ntk;
+  private Token jj_scanpos, jj_lastpos;
+  private int jj_la;
+  private int jj_gen;
+  final private int[] jj_la1 = new int[0];
+  static private int[] jj_la1_0;
+  static {
+      jj_la1_init_0();
+   }
+   private static void jj_la1_init_0() {
+      jj_la1_0 = new int[] {};
+   }
+  final private JJCalls[] jj_2_rtns = new JJCalls[13];
+  private boolean jj_rescan = false;
+  private int jj_gc = 0;
+
+  /** Constructor with InputStream. */
+  public MtasFunctionParser(java.io.InputStream stream) {
+     this(stream, null);
+  }
+  /** Constructor with InputStream and supplied encoding */
+  public MtasFunctionParser(java.io.InputStream stream, String encoding) {
+    try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+    token_source = new MtasFunctionParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 0; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** 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;
+    jj_gen = 0;
+    for (int i = 0; i < 0; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** Constructor. */
+  public MtasFunctionParser(java.io.Reader stream) {
+    jj_input_stream = new SimpleCharStream(stream, 1, 1);
+    token_source = new MtasFunctionParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 0; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** 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;
+    jj_gen = 0;
+    for (int i = 0; i < 0; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** Constructor with generated Token Manager. */
+  public MtasFunctionParser(MtasFunctionParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 0; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** Reinitialise. */
+  public void ReInit(MtasFunctionParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 0; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  private Token jj_consume_token(int kind) throws ParseException {
+    Token oldToken;
+    if ((oldToken = token).next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    if (token.kind == kind) {
+      jj_gen++;
+      if (++jj_gc > 100) {
+        jj_gc = 0;
+        for (int i = 0; i < jj_2_rtns.length; i++) {
+          JJCalls c = jj_2_rtns[i];
+          while (c != null) {
+            if (c.gen < jj_gen) c.first = null;
+            c = c.next;
+          }
+        }
+      }
+      return token;
+    }
+    token = oldToken;
+    jj_kind = kind;
+    throw generateParseException();
+  }
+
+  static private final class LookaheadSuccess extends java.lang.Error { }
+  final private LookaheadSuccess jj_ls = new LookaheadSuccess();
+  private boolean jj_scan_token(int kind) {
+    if (jj_scanpos == jj_lastpos) {
+      jj_la--;
+      if (jj_scanpos.next == null) {
+        jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
+      } else {
+        jj_lastpos = jj_scanpos = jj_scanpos.next;
+      }
+    } else {
+      jj_scanpos = jj_scanpos.next;
+    }
+    if (jj_rescan) {
+      int i = 0; Token tok = token;
+      while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
+      if (tok != null) jj_add_error_token(kind, i);
+    }
+    if (jj_scanpos.kind != kind) return true;
+    if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
+    return false;
+  }
+
+
+/** Get the next Token. */
+  final public Token getNextToken() {
+    if (token.next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    jj_gen++;
+    return token;
+  }
+
+/** Get the specific Token. */
+  final public Token getToken(int index) {
+    Token t = token;
+    for (int i = 0; i < index; i++) {
+      if (t.next != null) t = t.next;
+      else t = t.next = token_source.getNextToken();
+    }
+    return t;
+  }
+
+  private int jj_ntk() {
+    if ((jj_nt=token.next) == null)
+      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
+    else
+      return (jj_ntk = jj_nt.kind);
+  }
+
+  private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>();
+  private int[] jj_expentry;
+  private int jj_kind = -1;
+  private int[] jj_lasttokens = new int[100];
+  private int jj_endpos;
+
+  private void jj_add_error_token(int kind, int pos) {
+    if (pos >= 100) return;
+    if (pos == jj_endpos + 1) {
+      jj_lasttokens[jj_endpos++] = kind;
+    } else if (jj_endpos != 0) {
+      jj_expentry = new int[jj_endpos];
+      for (int i = 0; i < jj_endpos; i++) {
+        jj_expentry[i] = jj_lasttokens[i];
+      }
+      jj_entries_loop: for (java.util.Iterator<?> it = jj_expentries.iterator(); it.hasNext();) {
+        int[] oldentry = (int[])(it.next());
+        if (oldentry.length == jj_expentry.length) {
+          for (int i = 0; i < jj_expentry.length; i++) {
+            if (oldentry[i] != jj_expentry[i]) {
+              continue jj_entries_loop;
+            }
+          }
+          jj_expentries.add(jj_expentry);
+          break jj_entries_loop;
+        }
+      }
+      if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
+    }
+  }
+
+  /** Generate ParseException. */
+  public ParseException generateParseException() {
+    jj_expentries.clear();
+    boolean[] la1tokens = new boolean[16];
+    if (jj_kind >= 0) {
+      la1tokens[jj_kind] = true;
+      jj_kind = -1;
+    }
+    for (int i = 0; i < 0; i++) {
+      if (jj_la1[i] == jj_gen) {
+        for (int j = 0; j < 32; j++) {
+          if ((jj_la1_0[i] & (1<<j)) != 0) {
+            la1tokens[j] = true;
+          }
+        }
+      }
+    }
+    for (int i = 0; i < 16; i++) {
+      if (la1tokens[i]) {
+        jj_expentry = new int[1];
+        jj_expentry[0] = i;
+        jj_expentries.add(jj_expentry);
+      }
+    }
+    jj_endpos = 0;
+    jj_rescan_token();
+    jj_add_error_token(0, 0);
+    int[][] exptokseq = new int[jj_expentries.size()][];
+    for (int i = 0; i < jj_expentries.size(); i++) {
+      exptokseq[i] = jj_expentries.get(i);
+    }
+    return new ParseException(token, exptokseq, tokenImage);
+  }
+
+  /** Enable tracing. */
+  final public void enable_tracing() {
+  }
+
+  /** Disable tracing. */
+  final public void disable_tracing() {
+  }
+
+  private void jj_rescan_token() {
+    jj_rescan = true;
+    for (int i = 0; i < 13; i++) {
+    try {
+      JJCalls p = jj_2_rtns[i];
+      do {
+        if (p.gen > jj_gen) {
+          jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
+          switch (i) {
+            case 0: jj_3_1(); break;
+            case 1: jj_3_2(); break;
+            case 2: jj_3_3(); break;
+            case 3: jj_3_4(); break;
+            case 4: jj_3_5(); break;
+            case 5: jj_3_6(); break;
+            case 6: jj_3_7(); break;
+            case 7: jj_3_8(); break;
+            case 8: jj_3_9(); break;
+            case 9: jj_3_10(); break;
+            case 10: jj_3_11(); break;
+            case 11: jj_3_12(); break;
+            case 12: jj_3_13(); break;
+          }
+        }
+        p = p.next;
+      } while (p != null);
+      } catch(LookaheadSuccess ls) { }
+    }
+    jj_rescan = false;
+  }
+
+  private void jj_save(int index, int xla) {
+    JJCalls p = jj_2_rtns[index];
+    while (p.gen > jj_gen) {
+      if (p.next == null) { p = p.next = new JJCalls(); break; }
+      p = p.next;
+    }
+    p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
+  }
+
+  static final class JJCalls {
+    int gen;
+    Token first;
+    int arg;
+    JJCalls next;
+  }
+
+}
diff --git a/src/mtas/parser/function/MtasFunctionParserConstants.java b/src/mtas/parser/function/MtasFunctionParserConstants.java
new file mode 100644
index 0000000..8733413
--- /dev/null
+++ b/src/mtas/parser/function/MtasFunctionParserConstants.java
@@ -0,0 +1,59 @@
+/* Generated By:JavaCC: Do not edit this line. MtasFunctionParserConstants.java */
+package mtas.parser.function;
+
+
+/**
+ * Token literal values and constants.
+ * Generated by org.javacc.parser.OtherFilesGen#start()
+ */
+public interface MtasFunctionParserConstants {
+
+  /** End of File. */
+  int EOF = 0;
+  /** RegularExpression Id. */
+  int VARIABLE = 5;
+  /** RegularExpression Id. */
+  int LONG = 6;
+  /** RegularExpression Id. */
+  int DOUBLE = 7;
+  /** RegularExpression Id. */
+  int N = 8;
+  /** RegularExpression Id. */
+  int BASIC_OPERATOR_ADD = 9;
+  /** RegularExpression Id. */
+  int BASIC_OPERATOR_SUBTRACT = 10;
+  /** RegularExpression Id. */
+  int BASIC_OPERATOR_MULTIPLY = 11;
+  /** RegularExpression Id. */
+  int BASIC_OPERATOR_DIVIDE = 12;
+  /** RegularExpression Id. */
+  int BASIC_OPERATOR_POWER = 13;
+  /** RegularExpression Id. */
+  int BRACKET_START = 14;
+  /** RegularExpression Id. */
+  int BRACKET_END = 15;
+
+  /** Lexical state. */
+  int DEFAULT = 0;
+
+  /** Literal token values. */
+  String[] tokenImage = {
+    "<EOF>",
+    "\" \"",
+    "\"\\r\"",
+    "\"\\t\"",
+    "\"\\n\"",
+    "<VARIABLE>",
+    "<LONG>",
+    "<DOUBLE>",
+    "\"$n\"",
+    "\"+\"",
+    "\"-\"",
+    "\"*\"",
+    "\"/\"",
+    "\"^\"",
+    "\"(\"",
+    "\")\"",
+  };
+
+}
diff --git a/src/mtas/parser/function/MtasFunctionParserTokenManager.java b/src/mtas/parser/function/MtasFunctionParserTokenManager.java
new file mode 100644
index 0000000..31c63f1
--- /dev/null
+++ b/src/mtas/parser/function/MtasFunctionParserTokenManager.java
@@ -0,0 +1,441 @@
+/* Generated By:JavaCC: Do not edit this line. MtasFunctionParserTokenManager.java */
+package mtas.parser.function;
+import mtas.codec.util.CodecUtil;
+import mtas.parser.function.util.MtasFunctionParserFunction;
+import mtas.parser.function.util.MtasFunctionParserFunctionBasic;
+import mtas.parser.function.util.MtasFunctionParserItem;
+import java.io.IOException;
+
+/** Token Manager. */
+public class MtasFunctionParserTokenManager implements MtasFunctionParserConstants
+{
+
+  /** Debug output. */
+  public  java.io.PrintStream debugStream = System.out;
+  /** Set debug output. */
+  public  void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
+private final int jjStopStringLiteralDfa_0(int pos, long active0)
+{
+   switch (pos)
+   {
+      case 0:
+         if ((active0 & 0x100L) != 0L)
+            return 0;
+         if ((active0 & 0x400L) != 0L)
+            return 4;
+         return -1;
+      default :
+         return -1;
+   }
+}
+private final int jjStartNfa_0(int pos, long active0)
+{
+   return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
+}
+private int jjStopAtPos(int pos, int kind)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   return pos + 1;
+}
+private int jjMoveStringLiteralDfa0_0()
+{
+   switch(curChar)
+   {
+      case 36:
+         return jjMoveStringLiteralDfa1_0(0x100L);
+      case 40:
+         return jjStopAtPos(0, 14);
+      case 41:
+         return jjStopAtPos(0, 15);
+      case 42:
+         return jjStopAtPos(0, 11);
+      case 43:
+         return jjStopAtPos(0, 9);
+      case 45:
+         return jjStartNfaWithStates_0(0, 10, 4);
+      case 47:
+         return jjStopAtPos(0, 12);
+      case 94:
+         return jjStopAtPos(0, 13);
+      default :
+         return jjMoveNfa_0(2, 0);
+   }
+}
+private int jjMoveStringLiteralDfa1_0(long active0)
+{
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(0, active0);
+      return 1;
+   }
+   switch(curChar)
+   {
+      case 110:
+         if ((active0 & 0x100L) != 0L)
+            return jjStopAtPos(1, 8);
+         break;
+      default :
+         break;
+   }
+   return jjStartNfa_0(0, active0);
+}
+private int jjStartNfaWithStates_0(int pos, int kind, int state)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) { return pos + 1; }
+   return jjMoveNfa_0(state, pos + 1);
+}
+private int jjMoveNfa_0(int startState, int curPos)
+{
+   int startsAt = 0;
+   jjnewStateCnt = 14;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 4:
+                  if ((0x3fe000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(8, 9);
+                  else if (curChar == 48)
+                     jjCheckNAdd(9);
+                  if ((0x3fe000000000000L & l) != 0L)
+                  {
+                     if (kind > 6)
+                        kind = 6;
+                     jjCheckNAdd(5);
+                  }
+                  else if (curChar == 48)
+                  {
+                     if (kind > 6)
+                        kind = 6;
+                  }
+                  break;
+               case 2:
+                  if ((0x3fe000000000000L & l) != 0L)
+                  {
+                     if (kind > 6)
+                        kind = 6;
+                     jjCheckNAddStates(0, 2);
+                  }
+                  else if (curChar == 48)
+                  {
+                     if (kind > 6)
+                        kind = 6;
+                     jjCheckNAdd(9);
+                  }
+                  else if (curChar == 45)
+                     jjAddStates(3, 6);
+                  else if (curChar == 36)
+                     jjstateSet[jjnewStateCnt++] = 0;
+                  break;
+               case 1:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 5)
+                     kind = 5;
+                  jjstateSet[jjnewStateCnt++] = 1;
+                  break;
+               case 3:
+                  if (curChar == 45)
+                     jjAddStates(3, 6);
+                  break;
+               case 5:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 6)
+                     kind = 6;
+                  jjCheckNAdd(5);
+                  break;
+               case 6:
+                  if (curChar == 48 && kind > 6)
+                     kind = 6;
+                  break;
+               case 7:
+                  if ((0x3fe000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(8, 9);
+                  break;
+               case 8:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(8, 9);
+                  break;
+               case 9:
+                  if (curChar == 46)
+                     jjCheckNAdd(10);
+                  break;
+               case 10:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAdd(10);
+                  break;
+               case 11:
+                  if (curChar == 48)
+                     jjCheckNAdd(9);
+                  break;
+               case 12:
+                  if ((0x3fe000000000000L & l) == 0L)
+                     break;
+                  if (kind > 6)
+                     kind = 6;
+                  jjCheckNAddStates(0, 2);
+                  break;
+               case 13:
+                  if (curChar != 48)
+                     break;
+                  if (kind > 6)
+                     kind = 6;
+                  jjCheckNAdd(9);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if (curChar == 113)
+                     jjstateSet[jjnewStateCnt++] = 1;
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = (int)(curChar >> 8);
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 077);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 14 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+static final int[] jjnextStates = {
+   5, 8, 9, 4, 6, 7, 11, 
+};
+
+/** Token literal values. */
+public static final String[] jjstrLiteralImages = {
+"", null, null, null, null, null, null, null, "\44\156", "\53", "\55", "\52", 
+"\57", "\136", "\50", "\51", };
+
+/** Lexer state names. */
+public static final String[] lexStateNames = {
+   "DEFAULT",
+};
+static final long[] jjtoToken = {
+   0xffe1L, 
+};
+static final long[] jjtoSkip = {
+   0x1eL, 
+};
+protected SimpleCharStream input_stream;
+private final int[] jjrounds = new int[14];
+private final int[] jjstateSet = new int[28];
+protected char curChar;
+/** Constructor. */
+public MtasFunctionParserTokenManager(SimpleCharStream stream){
+   if (SimpleCharStream.staticFlag)
+      throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+   input_stream = stream;
+}
+
+/** Constructor. */
+public MtasFunctionParserTokenManager(SimpleCharStream stream, int lexState){
+   this(stream);
+   SwitchTo(lexState);
+}
+
+/** Reinitialise parser. */
+public void ReInit(SimpleCharStream stream)
+{
+   jjmatchedPos = jjnewStateCnt = 0;
+   curLexState = defaultLexState;
+   input_stream = stream;
+   ReInitRounds();
+}
+private void ReInitRounds()
+{
+   int i;
+   jjround = 0x80000001;
+   for (i = 14; i-- > 0;)
+      jjrounds[i] = 0x80000000;
+}
+
+/** Reinitialise parser. */
+public void ReInit(SimpleCharStream stream, int lexState)
+{
+   ReInit(stream);
+   SwitchTo(lexState);
+}
+
+/** Switch to specified lex state. */
+public void SwitchTo(int lexState)
+{
+   if (lexState >= 1 || lexState < 0)
+      throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+   else
+      curLexState = lexState;
+}
+
+protected Token jjFillToken()
+{
+   final Token t;
+   final String curTokenImage;
+   final int beginLine;
+   final int endLine;
+   final int beginColumn;
+   final int endColumn;
+   String im = jjstrLiteralImages[jjmatchedKind];
+   curTokenImage = (im == null) ? input_stream.GetImage() : im;
+   beginLine = input_stream.getBeginLine();
+   beginColumn = input_stream.getBeginColumn();
+   endLine = input_stream.getEndLine();
+   endColumn = input_stream.getEndColumn();
+   t = Token.newToken(jjmatchedKind, curTokenImage);
+
+   t.beginLine = beginLine;
+   t.endLine = endLine;
+   t.beginColumn = beginColumn;
+   t.endColumn = endColumn;
+
+   return t;
+}
+
+int curLexState = 0;
+int defaultLexState = 0;
+int jjnewStateCnt;
+int jjround;
+int jjmatchedPos;
+int jjmatchedKind;
+
+/** Get the next Token. */
+public Token getNextToken() 
+{
+  Token matchedToken;
+  int curPos = 0;
+
+  EOFLoop :
+  for (;;)
+  {
+   try
+   {
+      curChar = input_stream.BeginToken();
+   }
+   catch(java.io.IOException e)
+   {
+      jjmatchedKind = 0;
+      matchedToken = jjFillToken();
+      return matchedToken;
+   }
+
+   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();
+   if (jjmatchedKind != 0x7fffffff)
+   {
+      if (jjmatchedPos + 1 < curPos)
+         input_stream.backup(curPos - jjmatchedPos - 1);
+      if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+      {
+         matchedToken = jjFillToken();
+         return matchedToken;
+      }
+      else
+      {
+         continue EOFLoop;
+      }
+   }
+   int error_line = input_stream.getEndLine();
+   int error_column = input_stream.getEndColumn();
+   String error_after = null;
+   boolean EOFSeen = false;
+   try { input_stream.readChar(); input_stream.backup(1); }
+   catch (java.io.IOException e1) {
+      EOFSeen = true;
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+      if (curChar == '\n' || curChar == '\r') {
+         error_line++;
+         error_column = 0;
+      }
+      else
+         error_column++;
+   }
+   if (!EOFSeen) {
+      input_stream.backup(1);
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+   }
+   throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
+  }
+}
+
+private void jjCheckNAdd(int state)
+{
+   if (jjrounds[state] != jjround)
+   {
+      jjstateSet[jjnewStateCnt++] = state;
+      jjrounds[state] = jjround;
+   }
+}
+private void jjAddStates(int start, int end)
+{
+   do {
+      jjstateSet[jjnewStateCnt++] = jjnextStates[start];
+   } while (start++ != end);
+}
+private void jjCheckNAddTwoStates(int state1, int state2)
+{
+   jjCheckNAdd(state1);
+   jjCheckNAdd(state2);
+}
+
+private void jjCheckNAddStates(int start, int end)
+{
+   do {
+      jjCheckNAdd(jjnextStates[start]);
+   } while (start++ != end);
+}
+
+}
diff --git a/src/mtas/parser/function/ParseException.java b/src/mtas/parser/function/ParseException.java
new file mode 100644
index 0000000..967b022
--- /dev/null
+++ b/src/mtas/parser/function/ParseException.java
@@ -0,0 +1,187 @@
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 5.0 */
+/* JavaCCOptions:KEEP_LINE_COL=null */
+package mtas.parser.function;
+
+/**
+ * This exception is thrown when parse errors are encountered.
+ * You can explicitly create objects of this exception type by
+ * calling the method generateParseException in the generated
+ * parser.
+ *
+ * You can modify this class to customize your error reporting
+ * mechanisms so long as you retain the public fields.
+ */
+public class ParseException extends Exception {
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * This constructor is used by the method "generateParseException"
+   * in the generated parser.  Calling this constructor generates
+   * a new object of this type with the fields "currentToken",
+   * "expectedTokenSequences", and "tokenImage" set.
+   */
+  public ParseException(Token currentTokenVal,
+                        int[][] expectedTokenSequencesVal,
+                        String[] tokenImageVal
+                       )
+  {
+    super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
+    currentToken = currentTokenVal;
+    expectedTokenSequences = expectedTokenSequencesVal;
+    tokenImage = tokenImageVal;
+  }
+
+  /**
+   * The following constructors are for use by you for whatever
+   * purpose you can think of.  Constructing the exception in this
+   * manner makes the exception behave in the normal way - i.e., as
+   * documented in the class "Throwable".  The fields "errorToken",
+   * "expectedTokenSequences", and "tokenImage" do not contain
+   * relevant information.  The JavaCC generated code does not use
+   * these constructors.
+   */
+
+  public ParseException() {
+    super();
+  }
+
+  /** Constructor with message. */
+  public ParseException(String message) {
+    super(message);
+  }
+
+
+  /**
+   * This is the last token that has been consumed successfully.  If
+   * this object has been created due to a parse error, the token
+   * followng this token will (therefore) be the first error token.
+   */
+  public Token currentToken;
+
+  /**
+   * Each entry in this array is an array of integers.  Each array
+   * of integers represents a sequence of tokens (by their ordinal
+   * values) that is expected at this point of the parse.
+   */
+  public int[][] expectedTokenSequences;
+
+  /**
+   * This is a reference to the "tokenImage" array of the generated
+   * parser within which the parse error occurred.  This array is
+   * defined in the generated ...Constants interface.
+   */
+  public String[] tokenImage;
+
+  /**
+   * It uses "currentToken" and "expectedTokenSequences" to generate a parse
+   * error message and returns it.  If this object has been created
+   * due to a parse error, and you do not catch it (it gets thrown
+   * from the parser) the correct error message
+   * gets displayed.
+   */
+  private static String initialise(Token currentToken,
+                           int[][] expectedTokenSequences,
+                           String[] tokenImage) {
+    String eol = System.getProperty("line.separator", "\n");
+    StringBuffer expected = new StringBuffer();
+    int maxSize = 0;
+    for (int i = 0; i < expectedTokenSequences.length; i++) {
+      if (maxSize < expectedTokenSequences[i].length) {
+        maxSize = expectedTokenSequences[i].length;
+      }
+      for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+        expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
+      }
+      if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+        expected.append("...");
+      }
+      expected.append(eol).append("    ");
+    }
+    String retval = "Encountered \"";
+    Token tok = currentToken.next;
+    for (int i = 0; i < maxSize; i++) {
+      if (i != 0) retval += " ";
+      if (tok.kind == 0) {
+        retval += tokenImage[0];
+        break;
+      }
+      retval += " " + tokenImage[tok.kind];
+      retval += " \"";
+      retval += add_escapes(tok.image);
+      retval += " \"";
+      tok = tok.next;
+    }
+    retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+    retval += "." + eol;
+    if (expectedTokenSequences.length == 1) {
+      retval += "Was expecting:" + eol + "    ";
+    } else {
+      retval += "Was expecting one of:" + eol + "    ";
+    }
+    retval += expected.toString();
+    return retval;
+  }
+
+  /**
+   * The end of line string for this machine.
+   */
+  protected String eol = System.getProperty("line.separator", "\n");
+
+  /**
+   * Used to convert raw characters to their escaped version
+   * when these raw version cannot be used as part of an ASCII
+   * string literal.
+   */
+  static String add_escapes(String str) {
+      StringBuffer retval = new StringBuffer();
+      char ch;
+      for (int i = 0; i < str.length(); i++) {
+        switch (str.charAt(i))
+        {
+           case 0 :
+              continue;
+           case '\b':
+              retval.append("\\b");
+              continue;
+           case '\t':
+              retval.append("\\t");
+              continue;
+           case '\n':
+              retval.append("\\n");
+              continue;
+           case '\f':
+              retval.append("\\f");
+              continue;
+           case '\r':
+              retval.append("\\r");
+              continue;
+           case '\"':
+              retval.append("\\\"");
+              continue;
+           case '\'':
+              retval.append("\\\'");
+              continue;
+           case '\\':
+              retval.append("\\\\");
+              continue;
+           default:
+              if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+                 String s = "0000" + Integer.toString(ch, 16);
+                 retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+              } else {
+                 retval.append(ch);
+              }
+              continue;
+        }
+      }
+      return retval.toString();
+   }
+
+}
+/* JavaCC - OriginalChecksum=03241e67478474b014438ca8f89ad5a8 (do not edit this line) */
diff --git a/src/mtas/parser/function/SimpleCharStream.java b/src/mtas/parser/function/SimpleCharStream.java
new file mode 100644
index 0000000..36c84dc
--- /dev/null
+++ b/src/mtas/parser/function/SimpleCharStream.java
@@ -0,0 +1,471 @@
+/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */
+/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package mtas.parser.function;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (without unicode processing).
+ */
+
+public class SimpleCharStream
+{
+/** Whether parser is static. */
+  public static final boolean staticFlag = false;
+  int bufsize;
+  int available;
+  int tokenBegin;
+/** Position in buffer. */
+  public int bufpos = -1;
+  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[] buffer;
+  protected int maxNextCharInd = 0;
+  protected int inBuf = 0;
+  protected int tabSize = 8;
+
+  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;
+
+        maxNextCharInd = (bufpos += (bufsize - tokenBegin));
+      }
+      else
+      {
+        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+        buffer = newbuffer;
+
+        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+        bufline = newbufline;
+
+        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+        bufcolumn = newbufcolumn;
+
+        maxNextCharInd = (bufpos -= tokenBegin);
+      }
+    }
+    catch (Throwable t)
+    {
+      throw new Error(t.getMessage());
+    }
+
+
+    bufsize += 2048;
+    available = bufsize;
+    tokenBegin = 0;
+  }
+
+  protected void FillBuff() throws java.io.IOException
+  {
+    if (maxNextCharInd == available)
+    {
+      if (available == bufsize)
+      {
+        if (tokenBegin > 2048)
+        {
+          bufpos = maxNextCharInd = 0;
+          available = tokenBegin;
+        }
+        else if (tokenBegin < 0)
+          bufpos = maxNextCharInd = 0;
+        else
+          ExpandBuff(false);
+      }
+      else if (available > tokenBegin)
+        available = bufsize;
+      else if ((tokenBegin - available) < 2048)
+        ExpandBuff(true);
+      else
+        available = tokenBegin;
+    }
+
+    int i;
+    try {
+      if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
+      {
+        inputStream.close();
+        throw new java.io.IOException();
+      }
+      else
+        maxNextCharInd += i;
+      return;
+    }
+    catch(java.io.IOException e) {
+      --bufpos;
+      backup(0);
+      if (tokenBegin == -1)
+        tokenBegin = bufpos;
+      throw e;
+    }
+  }
+
+/** Start. */
+  public char BeginToken() throws java.io.IOException
+  {
+    tokenBegin = -1;
+    char c = readChar();
+    tokenBegin = bufpos;
+
+    return c;
+  }
+
+  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);
+    }
+
+    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];
+    }
+
+    if (++bufpos >= maxNextCharInd)
+      FillBuff();
+
+    char c = buffer[bufpos];
+
+    UpdateLineColumn(c);
+    return c;
+  }
+
+  @Deprecated
+  /**
+   * @deprecated
+   * @see #getEndColumn
+   */
+
+  public int getColumn() {
+    return bufcolumn[bufpos];
+  }
+
+  @Deprecated
+  /**
+   * @deprecated
+   * @see #getEndLine
+   */
+
+  public int getLine() {
+    return bufline[bufpos];
+  }
+
+  /** Get token end column number. */
+  public int getEndColumn() {
+    return bufcolumn[bufpos];
+  }
+
+  /** Get token end line number. */
+  public int getEndLine() {
+     return bufline[bufpos];
+  }
+
+  /** Get token beginning column number. */
+  public int getBeginColumn() {
+    return bufcolumn[tokenBegin];
+  }
+
+  /** Get token beginning line number. */
+  public int getBeginLine() {
+    return bufline[tokenBegin];
+  }
+
+/** Backup a number of characters. */
+  public void backup(int amount) {
+
+    inBuf += amount;
+    if ((bufpos -= amount) < 0)
+      bufpos += bufsize;
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(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];
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream, int startline,
+                          int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader 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];
+    }
+    prevCharIsLF = prevCharIsCR = false;
+    tokenBegin = inBuf = maxNextCharInd = 0;
+    bufpos = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream, int startline,
+                     int startcolumn)
+  {
+    ReInit(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+  /** Constructor. */
+  public SimpleCharStream(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 SimpleCharStream(java.io.InputStream dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+                          int startcolumn) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, int startline,
+                          int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, 1, 1, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream)
+  {
+    this(dstream, 1, 1, 4096);
+  }
+
+  /** 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) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(dstream, encoding, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+  /** 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);
+  }
+  /** Get token literal value. */
+  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);
+  }
+
+  /** Get the 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;
+  }
+
+  /** Reset buffer when finished. */
+  public void Done()
+  {
+    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;
+      }
+    }
+
+    line = bufline[j];
+    column = bufcolumn[j];
+  }
+
+}
+/* JavaCC - OriginalChecksum=351c902e220c6aaab99db9e1060ff515 (do not edit this line) */
diff --git a/src/mtas/parser/function/Token.java b/src/mtas/parser/function/Token.java
new file mode 100644
index 0000000..cc91e01
--- /dev/null
+++ b/src/mtas/parser/function/Token.java
@@ -0,0 +1,131 @@
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */
+/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package mtas.parser.function;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token implements java.io.Serializable {
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * An integer that describes the kind of this token.  This numbering
+   * system is determined by JavaCCParser, and a table of these numbers is
+   * stored in the file ...Constants.java.
+   */
+  public int kind;
+
+  /** The line number of the first character of this Token. */
+  public int beginLine;
+  /** The column number of the first character of this Token. */
+  public int beginColumn;
+  /** The line number of the last character of this Token. */
+  public int endLine;
+  /** The column number of the last character of this Token. */
+  public int endColumn;
+
+  /**
+   * The string image of the token.
+   */
+  public String image;
+
+  /**
+   * A reference to the next regular (non-special) token from the input
+   * stream.  If this is the last token from the input stream, or if the
+   * token manager has not read tokens beyond this one, this field is
+   * set to null.  This is true only if this token is also a regular
+   * token.  Otherwise, see below for a description of the contents of
+   * this field.
+   */
+  public Token next;
+
+  /**
+   * This field is used to access special tokens that occur prior to this
+   * token, but after the immediately preceding regular (non-special) token.
+   * If there are no such special tokens, this field is set to null.
+   * When there are more than one such special token, this field refers
+   * to the last of these special tokens, which in turn refers to the next
+   * previous special token through its specialToken field, and so on
+   * until the first special token (whose specialToken field is null).
+   * The next fields of special tokens refer to other special tokens that
+   * immediately follow it (without an intervening regular token).  If there
+   * is no such token, this field is null.
+   */
+  public Token specialToken;
+
+  /**
+   * An optional attribute value of the Token.
+   * Tokens which are not used as syntactic sugar will often contain
+   * meaningful values that will be used later on by the compiler or
+   * interpreter. This attribute value is often different from the image.
+   * Any subclass of Token that actually wants to return a non-null value can
+   * override this method as appropriate.
+   */
+  public Object getValue() {
+    return null;
+  }
+
+  /**
+   * No-argument constructor
+   */
+  public Token() {}
+
+  /**
+   * Constructs a new token for the specified Image.
+   */
+  public Token(int kind)
+  {
+    this(kind, null);
+  }
+
+  /**
+   * Constructs a new token for the specified Image and Kind.
+   */
+  public Token(int kind, String image)
+  {
+    this.kind = kind;
+    this.image = image;
+  }
+
+  /**
+   * Returns the image.
+   */
+  public String toString()
+  {
+    return image;
+  }
+
+  /**
+   * Returns a new Token object, by default. However, if you want, you
+   * can create and return subclass objects based on the value of ofKind.
+   * Simply add the cases to the switch for all those special cases.
+   * For example, if you have a subclass of Token called IDToken that
+   * you want to create if ofKind is ID, simply add something like :
+   *
+   *    case MyParserConstants.ID : return new IDToken(ofKind, image);
+   *
+   * to the following switch statement. Then you can cast matchedToken
+   * variable to the appropriate type and use sit in your lexical actions.
+   */
+  public static Token newToken(int ofKind, String image)
+  {
+    switch(ofKind)
+    {
+      default : return new Token(ofKind, image);
+    }
+  }
+
+  public static Token newToken(int ofKind)
+  {
+    return newToken(ofKind, null);
+  }
+
+}
+/* JavaCC - OriginalChecksum=1ff051f734b3b825a428890df3aeb019 (do not edit this line) */
diff --git a/src/mtas/parser/function/TokenMgrError.java b/src/mtas/parser/function/TokenMgrError.java
new file mode 100644
index 0000000..aa9bc90
--- /dev/null
+++ b/src/mtas/parser/function/TokenMgrError.java
@@ -0,0 +1,147 @@
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */
+/* JavaCCOptions: */
+package mtas.parser.function;
+
+/** Token Manager Error. */
+public class TokenMgrError extends Error
+{
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /*
+   * Ordinals for various reasons why an Error of this type can be thrown.
+   */
+
+  /**
+   * Lexical error occurred.
+   */
+  static final int LEXICAL_ERROR = 0;
+
+  /**
+   * An attempt was made to create a second instance of a static token manager.
+   */
+  static final int STATIC_LEXER_ERROR = 1;
+
+  /**
+   * Tried to change to an invalid lexical state.
+   */
+  static final int INVALID_LEXICAL_STATE = 2;
+
+  /**
+   * Detected (and bailed out of) an infinite loop in the token manager.
+   */
+  static final int LOOP_DETECTED = 3;
+
+  /**
+   * Indicates the reason why the exception is thrown. It will have
+   * one of the above 4 values.
+   */
+  int errorCode;
+
+  /**
+   * Replaces unprintable characters by their escaped (or unicode escaped)
+   * equivalents in the given string
+   */
+  protected static final String addEscapes(String str) {
+    StringBuffer retval = new StringBuffer();
+    char ch;
+    for (int i = 0; i < str.length(); i++) {
+      switch (str.charAt(i))
+      {
+        case 0 :
+          continue;
+        case '\b':
+          retval.append("\\b");
+          continue;
+        case '\t':
+          retval.append("\\t");
+          continue;
+        case '\n':
+          retval.append("\\n");
+          continue;
+        case '\f':
+          retval.append("\\f");
+          continue;
+        case '\r':
+          retval.append("\\r");
+          continue;
+        case '\"':
+          retval.append("\\\"");
+          continue;
+        case '\'':
+          retval.append("\\\'");
+          continue;
+        case '\\':
+          retval.append("\\\\");
+          continue;
+        default:
+          if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+            String s = "0000" + Integer.toString(ch, 16);
+            retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+          } else {
+            retval.append(ch);
+          }
+          continue;
+      }
+    }
+    return retval.toString();
+  }
+
+  /**
+   * Returns a detailed message for the Error when it is thrown by the
+   * token manager to indicate a lexical error.
+   * Parameters :
+   *    EOFSeen     : indicates if EOF caused the lexical error
+   *    curLexState : lexical state in which this error occurred
+   *    errorLine   : line number when the error occurred
+   *    errorColumn : column number when the error occurred
+   *    errorAfter  : prefix that was seen before this error occurred
+   *    curchar     : the offending character
+   * Note: You can customize the lexical error message by modifying this method.
+   */
+  protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
+    return("Lexical error at line " +
+          errorLine + ", column " +
+          errorColumn + ".  Encountered: " +
+          (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+          "after : \"" + addEscapes(errorAfter) + "\"");
+  }
+
+  /**
+   * You can also modify the body of this method to customize your error messages.
+   * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+   * of end-users concern, so you can return something like :
+   *
+   *     "Internal Error : Please file a bug report .... "
+   *
+   * from this method for such cases in the release version of your parser.
+   */
+  public String getMessage() {
+    return super.getMessage();
+  }
+
+  /*
+   * Constructors of various flavors follow.
+   */
+
+  /** No arg constructor. */
+  public TokenMgrError() {
+  }
+
+  /** Constructor with message and reason. */
+  public TokenMgrError(String message, int reason) {
+    super(message);
+    errorCode = reason;
+  }
+
+  /** Full Constructor. */
+  public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
+    this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+  }
+}
+/* JavaCC - OriginalChecksum=c8e52d6b54c7ac5de1d496ea7ce2fcd9 (do not edit this line) */
diff --git a/src/mtas/solr/handler/component/MtasMergeStrategy.java b/src/mtas/solr/handler/component/MtasMergeStrategy.java
index 11d1ffa..5986422 100644
--- a/src/mtas/solr/handler/component/MtasMergeStrategy.java
+++ b/src/mtas/solr/handler/component/MtasMergeStrategy.java
@@ -21,8 +21,14 @@ import org.apache.solr.search.SolrIndexSearcher;
 
 import mtas.solr.handler.component.MtasSolrSearchComponent.ComponentSortSelect;
 
+/**
+ * The Class MtasMergeStrategy.
+ */
 public class MtasMergeStrategy implements MergeStrategy {
 
+  /* (non-Javadoc)
+   * @see org.apache.solr.handler.component.MergeStrategy#merge(org.apache.solr.handler.component.ResponseBuilder, org.apache.solr.handler.component.ShardRequest)
+   */
   @Override
   public void merge(ResponseBuilder rb, ShardRequest sreq) {
 
@@ -84,26 +90,46 @@ public class MtasMergeStrategy implements MergeStrategy {
     }
   }
 
+  /* (non-Javadoc)
+   * @see org.apache.solr.handler.component.MergeStrategy#mergesIds()
+   */
   @Override
   public boolean mergesIds() {
     return false;
   }
 
+  /* (non-Javadoc)
+   * @see org.apache.solr.handler.component.MergeStrategy#handlesMergeFields()
+   */
   @Override
   public boolean handlesMergeFields() {
     return false;
   }
 
+  /* (non-Javadoc)
+   * @see org.apache.solr.handler.component.MergeStrategy#handleMergeFields(org.apache.solr.handler.component.ResponseBuilder, org.apache.solr.search.SolrIndexSearcher)
+   */
   @Override
   public void handleMergeFields(ResponseBuilder rb,
       SolrIndexSearcher searcher) {
   }
 
+  /* (non-Javadoc)
+   * @see org.apache.solr.handler.component.MergeStrategy#getCost()
+   */
   @Override
   public int getCost() {
     return 0;
   }
 
+  /**
+   * Merge named list.
+   *
+   * @param sreq the sreq
+   * @param mtasResponse the mtas response
+   * @param key the key
+   * @param preferredPurpose the preferred purpose
+   */
   private void mergeNamedList(ShardRequest sreq,
       NamedList<Object> mtasResponse, String key, Integer preferredPurpose) {
     // create new response for key
@@ -147,6 +173,15 @@ public class MtasMergeStrategy implements MergeStrategy {
     }
   }
 
+  /**
+   * Merge array list.
+   *
+   * @param sreq the sreq
+   * @param mtasResponse the mtas response
+   * @param key the key
+   * @param preferredPurpose the preferred purpose
+   * @param mergeAllShardResponses the merge all shard responses
+   */
   private void mergeArrayList(ShardRequest sreq,
       NamedList<Object> mtasResponse, String key, Integer preferredPurpose,
       boolean mergeAllShardResponses) {
@@ -203,6 +238,12 @@ public class MtasMergeStrategy implements MergeStrategy {
     }
   }
 
+  /**
+   * Encode.
+   *
+   * @param o the o
+   * @return the string
+   */
   String encode(Object o) {
     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
     ObjectOutputStream objectOutputStream;
@@ -217,6 +258,12 @@ public class MtasMergeStrategy implements MergeStrategy {
     }
   }
 
+  /**
+   * Decode.
+   *
+   * @param s the s
+   * @return the object
+   */
   private Object decode(String s) {
     byte[] bytes = Base64.base64ToByteArray(s);
     ObjectInputStream objectInputStream;
@@ -230,6 +277,12 @@ public class MtasMergeStrategy implements MergeStrategy {
     }
   }
 
+  /**
+   * Decode.
+   *
+   * @param l the l
+   * @return the array list
+   */
   ArrayList decode(ArrayList l) {
     for (int i = 0; i < l.size(); i++) {
       if (l.get(i) instanceof NamedList) {
@@ -241,6 +294,12 @@ public class MtasMergeStrategy implements MergeStrategy {
     return l;
   }
 
+  /**
+   * Decode.
+   *
+   * @param nl the nl
+   * @return the named list
+   */
   private NamedList<Object> decode(NamedList<Object> nl) {
     for (int i = 0; i < nl.size(); i++) {
       String key = nl.getName(i);
@@ -276,6 +335,12 @@ public class MtasMergeStrategy implements MergeStrategy {
   }
 
 
+  /**
+   * Merge responses tree set.
+   *
+   * @param originalList the original list
+   * @param shardList the shard list
+   */
   private void mergeResponsesTreeSet(TreeSet<Object> originalList,
       TreeSet<Object> shardList) {
     for (Object item : shardList) {
@@ -283,6 +348,13 @@ public class MtasMergeStrategy implements MergeStrategy {
     }
   }
 
+  /**
+   * Merge responses array list.
+   *
+   * @param originalList the original list
+   * @param shardList the shard list
+   * @throws IOException Signals that an I/O exception has occurred.
+   */
   private void mergeResponsesArrayList(ArrayList<Object> originalList,
       ArrayList<Object> shardList) throws IOException {
     // get keys from original
@@ -324,6 +396,13 @@ public class MtasMergeStrategy implements MergeStrategy {
     }
   }
 
+  /**
+   * Merge responses named list.
+   *
+   * @param mainResponse the main response
+   * @param shardResponse the shard response
+   * @throws IOException Signals that an I/O exception has occurred.
+   */
   private void mergeResponsesNamedList(NamedList<Object> mainResponse,
       NamedList<Object> shardResponse) throws IOException {
     Iterator<Entry<String, Object>> it = shardResponse.iterator();
@@ -372,6 +451,12 @@ public class MtasMergeStrategy implements MergeStrategy {
     }
   }
 
+  /**
+   * Adjustable parts cloned.
+   *
+   * @param original the original
+   * @return the object
+   */
   private Object adjustablePartsCloned(Object original) {
     if (original instanceof NamedList) {
       NamedList<Object> newObject = new SimpleOrderedMap();
diff --git a/src/mtas/solr/handler/component/MtasSolrSearchComponent.java b/src/mtas/solr/handler/component/MtasSolrSearchComponent.java
index 34d82dd..bfebfcc 100644
--- a/src/mtas/solr/handler/component/MtasSolrSearchComponent.java
+++ b/src/mtas/solr/handler/component/MtasSolrSearchComponent.java
@@ -339,14 +339,21 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /** The Constant SUBNAME_MTAS_STATS_SPANS_QUERY_VALUE. */
   public static final String SUBNAME_MTAS_STATS_SPANS_QUERY_VALUE = "value";
 
+  /** The Constant STAGE_TERMVECTOR_MISSING_TOP. */
   public static final int STAGE_TERMVECTOR_MISSING_TOP = ResponseBuilder.STAGE_EXECUTE_QUERY
       + 10;
+  
+  /** The Constant STAGE_TERMVECTOR_MISSING_KEY. */
   public static final int STAGE_TERMVECTOR_MISSING_KEY = ResponseBuilder.STAGE_EXECUTE_QUERY
       + 15;
+  
+  /** The Constant STAGE_LIST. */
   public static final int STAGE_LIST = ResponseBuilder.STAGE_EXECUTE_QUERY + 20;
 
+  /** The show debug info. */
   private static boolean showDebugInfo = true;
 
+  /** The merge strategy. */
   private MtasMergeStrategy mergeStrategy;
 
   /*
@@ -422,10 +429,8 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Gets the field type.
    *
-   * @param schema
-   *          the schema
-   * @param field
-   *          the field
+   * @param schema the schema
+   * @param field the field
    * @return the field type
    */
   private String getFieldType(IndexSchema schema, String field) {
@@ -451,12 +456,9 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Prepare kwic.
    *
-   * @param rb
-   *          the rb
-   * @param mtasFields
-   *          the mtas fields
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param rb the rb
+   * @param mtasFields the mtas fields
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void prepareKwic(ResponseBuilder rb, ComponentFields mtasFields)
       throws IOException {
@@ -557,12 +559,9 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Prepare facet.
    *
-   * @param rb
-   *          the rb
-   * @param mtasFields
-   *          the mtas fields
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param rb the rb
+   * @param mtasFields the mtas fields
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void prepareFacet(ResponseBuilder rb, ComponentFields mtasFields)
       throws IOException {
@@ -725,12 +724,9 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Prepare list.
    *
-   * @param rb
-   *          the rb
-   * @param mtasFields
-   *          the mtas fields
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param rb the rb
+   * @param mtasFields the mtas fields
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void prepareList(ResponseBuilder rb, ComponentFields mtasFields)
       throws IOException {
@@ -833,12 +829,9 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Prepare group.
    *
-   * @param rb
-   *          the rb
-   * @param mtasFields
-   *          the mtas fields
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param rb the rb
+   * @param mtasFields the mtas fields
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void prepareGroup(ResponseBuilder rb, ComponentFields mtasFields)
       throws IOException {
@@ -985,16 +978,11 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Prepare group.
    *
-   * @param solrParams
-   *          the solr params
-   * @param gids
-   *          the gids
-   * @param name
-   *          the name
-   * @param positions
-   *          the positions
-   * @param prefixes
-   *          the prefixes
+   * @param solrParams the solr params
+   * @param gids the gids
+   * @param name the name
+   * @param positions the positions
+   * @param prefixes the prefixes
    */
   private void prepareGroup(SolrParams solrParams, SortedSet<String> gids,
       String name, String[] positions, String[] prefixes) {
@@ -1013,12 +1001,9 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Prepare term vector.
    *
-   * @param rb
-   *          the rb
-   * @param mtasFields
-   *          the mtas fields
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param rb the rb
+   * @param mtasFields the mtas fields
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void prepareTermVector(ResponseBuilder rb, ComponentFields mtasFields)
       throws IOException {
@@ -1131,12 +1116,9 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Prepare prefix.
    *
-   * @param rb
-   *          the rb
-   * @param mtasFields
-   *          the mtas fields
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param rb the rb
+   * @param mtasFields the mtas fields
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void preparePrefix(ResponseBuilder rb, ComponentFields mtasFields)
       throws IOException {
@@ -1181,12 +1163,9 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Prepare stats.
    *
-   * @param rb
-   *          the rb
-   * @param mtasFields
-   *          the mtas fields
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param rb the rb
+   * @param mtasFields the mtas fields
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void prepareStats(ResponseBuilder rb, ComponentFields mtasFields)
       throws IOException {
@@ -1204,12 +1183,9 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Prepare stats positions.
    *
-   * @param rb
-   *          the rb
-   * @param mtasFields
-   *          the mtas fields
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param rb the rb
+   * @param mtasFields the mtas fields
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void prepareStatsPositions(ResponseBuilder rb,
       ComponentFields mtasFields) throws IOException {
@@ -1278,12 +1254,9 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Prepare stats tokens.
    *
-   * @param rb
-   *          the rb
-   * @param mtasFields
-   *          the mtas fields
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param rb the rb
+   * @param mtasFields the mtas fields
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void prepareStatsTokens(ResponseBuilder rb,
       ComponentFields mtasFields) throws IOException {
@@ -1352,12 +1325,9 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Prepare stats spans.
    *
-   * @param rb
-   *          the rb
-   * @param mtasFields
-   *          the mtas fields
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param rb the rb
+   * @param mtasFields the mtas fields
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void prepareStatsSpans(ResponseBuilder rb, ComponentFields mtasFields)
       throws IOException {
@@ -1470,10 +1440,8 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Gets the ids from parameters.
    *
-   * @param params
-   *          the params
-   * @param prefix
-   *          the prefix
+   * @param params the params
+   * @param prefix the prefix
    * @return the ids from parameters
    */
   private SortedSet<String> getIdsFromParameters(SolrParams params,
@@ -1495,15 +1463,11 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Construct query.
    *
-   * @param queryValue
-   *          the query value
-   * @param queryType
-   *          the query type
-   * @param field
-   *          the field
+   * @param queryValue the query value
+   * @param queryType the query type
+   * @param field the field
    * @return the span query
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private SpanQuery constructQuery(String queryValue, String queryType,
       String field) throws IOException {
@@ -1533,8 +1497,7 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Gets the positive integer.
    *
-   * @param number
-   *          the number
+   * @param number the number
    * @return the positive integer
    */
   private int getPositiveInteger(String number) {
@@ -1548,8 +1511,7 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Gets the double.
    *
-   * @param number
-   *          the number
+   * @param number the number
    * @return the double
    */
   private Double getDouble(String number) {
@@ -1563,18 +1525,12 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Compare and check.
    *
-   * @param list
-   *          the list
-   * @param original
-   *          the original
-   * @param nameNew
-   *          the name new
-   * @param nameOriginal
-   *          the name original
-   * @param unique
-   *          the unique
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param list the list
+   * @param original the original
+   * @param nameNew the name new
+   * @param nameOriginal the name original
+   * @param unique the unique
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void compareAndCheck(String[] list, String[] original, String nameNew,
       String nameOriginal, Boolean unique) throws IOException {
@@ -1928,6 +1884,9 @@ public class MtasSolrSearchComponent extends SearchComponent {
     //        + " HANDLERESPONSES " + rb.stage + " " + rb.req.getParamString());
   }
 
+  /* (non-Javadoc)
+   * @see org.apache.solr.handler.component.SearchComponent#finishStage(org.apache.solr.handler.component.ResponseBuilder)
+   */
   @Override
   public void finishStage(ResponseBuilder rb) {
     // System.out
@@ -1996,6 +1955,13 @@ public class MtasSolrSearchComponent extends SearchComponent {
     return ResponseBuilder.STAGE_DONE;
   }
 
+  /**
+   * Distributed process termvector missing top.
+   *
+   * @param rb the rb
+   * @param mtasFields the mtas fields
+   * @throws IOException Signals that an I/O exception has occurred.
+   */
   private void distributedProcessTermvectorMissingTop(ResponseBuilder rb,
       ComponentFields mtasFields) throws IOException {
     int numberOfShards = rb.shards.length;
@@ -2031,15 +1997,11 @@ public class MtasSolrSearchComponent extends SearchComponent {
   }
 
   /**
-   * Distributed process termvector.
+   * Distributed process termvector missing key.
    *
-   * @param rb
-   *          the rb
-   * @param mtasFields
-   *          the mtas fields
-   * @return
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param rb the rb
+   * @param mtasFields the mtas fields
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void distributedProcessTermvectorMissingKey(ResponseBuilder rb,
       ComponentFields mtasFields) throws IOException {
@@ -2123,10 +2085,8 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Distributed process list.
    *
-   * @param rb
-   *          the rb
-   * @param mtasFields
-   *          the mtas fields
+   * @param rb the rb
+   * @param mtasFields the mtas fields
    */
   private void distributedProcessList(ResponseBuilder rb,
       ComponentFields mtasFields) {
@@ -2240,15 +2200,12 @@ public class MtasSolrSearchComponent extends SearchComponent {
   }
 
   /**
-   * Compute missing items per shard.
+   * Compute missing termvector items per shard.
    *
-   * @param shardResponses
-   *          the shard responses
-   * @param args
-   *          the args
+   * @param shardResponses the shard responses
+   * @param args the args
    * @return the hash map
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private HashMap<String, HashMap<String, HashSet<String>>> computeMissingTermvectorItemsPerShard(
       List<ShardResponse> shardResponses, String... args) throws IOException {
@@ -2330,6 +2287,11 @@ public class MtasSolrSearchComponent extends SearchComponent {
     return result;
   }
 
+  /**
+   * Repair prefix items.
+   *
+   * @param mtasResponse the mtas response
+   */
   private void repairPrefixItems(NamedList<Object> mtasResponse) {
     // repair prefix lists
     try {
@@ -2360,8 +2322,7 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Gets the mtas fields.
    *
-   * @param rb
-   *          the rb
+   * @param rb the rb
    * @return the mtas fields
    */
   private ComponentFields getMtasFields(ResponseBuilder rb) {
@@ -2371,13 +2332,10 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Creates the stats position.
    *
-   * @param position
-   *          the position
-   * @param encode
-   *          the encode
+   * @param position the position
+   * @param encode the encode
    * @return the simple ordered map
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private SimpleOrderedMap<Object> createStatsPosition(
       ComponentPosition position, Boolean encode) throws IOException {
@@ -2399,13 +2357,10 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Creates the stats token.
    *
-   * @param token
-   *          the token
-   * @param encode
-   *          the encode
+   * @param token the token
+   * @param encode the encode
    * @return the simple ordered map
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private SimpleOrderedMap<Object> createStatsToken(ComponentToken token,
       Boolean encode) throws IOException {
@@ -2427,13 +2382,10 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Creates the stats span.
    *
-   * @param span
-   *          the span
-   * @param encode
-   *          the encode
+   * @param span the span
+   * @param encode the encode
    * @return the simple ordered map
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private SimpleOrderedMap<Object> createStatsSpan(ComponentSpan span,
       Boolean encode) throws IOException {
@@ -2455,13 +2407,10 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Creates the term vector.
    *
-   * @param termVector
-   *          the term vector
-   * @param encode
-   *          the encode
+   * @param termVector the term vector
+   * @param encode the encode
    * @return the simple ordered map
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private SimpleOrderedMap<Object> createTermVector(
       ComponentTermVector termVector, Boolean encode) throws IOException {
@@ -2507,10 +2456,8 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Creates the prefix.
    *
-   * @param prefix
-   *          the prefix
-   * @param encode
-   *          the encode
+   * @param prefix the prefix
+   * @param encode the encode
    * @return the simple ordered map
    */
   private SimpleOrderedMap<Object> createPrefix(ComponentPrefix prefix,
@@ -2535,8 +2482,7 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Creates the list.
    *
-   * @param list
-   *          the list
+   * @param list the list
    * @return the simple ordered map
    */
   private SimpleOrderedMap<Object> createList(ComponentList list) {
@@ -2666,10 +2612,8 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Creates the group.
    *
-   * @param group
-   *          the group
-   * @param encode
-   *          the encode
+   * @param group the group
+   * @param encode the encode
    * @return the simple ordered map
    */
   private SimpleOrderedMap<Object> createGroup(ComponentGroup group,
@@ -2698,13 +2642,10 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Creates the facet.
    *
-   * @param facet
-   *          the facet
-   * @param encode
-   *          the encode
+   * @param facet the facet
+   * @param encode the encode
    * @return the simple ordered map
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private SimpleOrderedMap<Object> createFacet(ComponentFacet facet,
       Boolean encode) throws IOException {
@@ -2731,8 +2672,7 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Creates the kwic.
    *
-   * @param kwic
-   *          the kwic
+   * @param kwic the kwic
    * @return the simple ordered map
    */
   private SimpleOrderedMap<Object> createKwic(ComponentKwic kwic) {
@@ -2859,6 +2799,12 @@ public class MtasSolrSearchComponent extends SearchComponent {
     return mtasKwicResponse;
   }
 
+  /**
+   * Rewrite.
+   *
+   * @param al the al
+   * @throws IOException Signals that an I/O exception has occurred.
+   */
   private void rewrite(ArrayList<Object> al) throws IOException {
     for (int i = 0; i < al.size(); i++) {
       if (al.get(i) instanceof NamedList) {
@@ -2872,10 +2818,8 @@ public class MtasSolrSearchComponent extends SearchComponent {
   /**
    * Rewrite.
    *
-   * @param nl
-   *          the nl
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param nl the nl
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   private void rewrite(NamedList<Object> nl) throws IOException {
     HashMap<String, NamedList<Object>> collapseNamedList = null;
@@ -2993,22 +2937,14 @@ public class MtasSolrSearchComponent extends SearchComponent {
     /**
      * Instantiates a new component sort select.
      *
-     * @param dataCollector
-     *          the data collector
-     * @param dataType
-     *          the data type
-     * @param statsType
-     *          the stats type
-     * @param statsItems
-     *          the stats items
-     * @param sortType
-     *          the sort type
-     * @param sortDirection
-     *          the sort direction
-     * @param start
-     *          the start
-     * @param number
-     *          the number
+     * @param dataCollector the data collector
+     * @param dataType the data type
+     * @param statsType the stats type
+     * @param statsItems the stats items
+     * @param sortType the sort type
+     * @param sortDirection the sort direction
+     * @param start the start
+     * @param number the number
      */
     public ComponentSortSelect(MtasDataCollector<?, ?> dataCollector,
         String[] dataType, String[] statsType, TreeSet<String>[] statsItems,
@@ -3046,14 +2982,10 @@ public class MtasSolrSearchComponent extends SearchComponent {
     /**
      * Instantiates a new component sort select.
      *
-     * @param dataCollector
-     *          the data collector
-     * @param dataType
-     *          the data type
-     * @param statsType
-     *          the stats type
-     * @param statsItems
-     *          the stats items
+     * @param dataCollector the data collector
+     * @param dataType the data type
+     * @param statsType the stats type
+     * @param statsItems the stats items
      */
     public ComponentSortSelect(MtasDataCollector dataCollector, String dataType,
         String statsType, TreeSet<String> statsItems) {
@@ -3065,10 +2997,8 @@ public class MtasSolrSearchComponent extends SearchComponent {
     /**
      * Merge.
      *
-     * @param newItem
-     *          the new item
-     * @throws IOException
-     *           Signals that an I/O exception has occurred.
+     * @param newItem the new item
+     * @throws IOException Signals that an I/O exception has occurred.
      */
     void merge(ComponentSortSelect newItem) throws IOException {
       dataCollector.merge(newItem.dataCollector, true);
@@ -3078,8 +3008,7 @@ public class MtasSolrSearchComponent extends SearchComponent {
      * Gets the total.
      *
      * @return the total
-     * @throws IOException
-     *           Signals that an I/O exception has occurred.
+     * @throws IOException Signals that an I/O exception has occurred.
      */
     private int getTotal() throws IOException {
       if (dataCollector.getCollectorType()
@@ -3094,9 +3023,9 @@ public class MtasSolrSearchComponent extends SearchComponent {
     /**
      * Gets the data.
      *
+     * @param showDebugInfo the show debug info
      * @return the data
-     * @throws IOException
-     *           Signals that an I/O exception has occurred.
+     * @throws IOException Signals that an I/O exception has occurred.
      */
     NamedList<Object> getData(boolean showDebugInfo) throws IOException {
       if (dataCollector.getCollectorType()
@@ -3127,6 +3056,13 @@ public class MtasSolrSearchComponent extends SearchComponent {
       }
     }
 
+    /**
+     * Gets the key list.
+     *
+     * @param showFull the show full
+     * @return the key list
+     * @throws IOException Signals that an I/O exception has occurred.
+     */
     private Set<String> getKeyList(boolean showFull) throws IOException {
       if (dataCollector.getCollectorType()
           .equals(DataCollector.COLLECTOR_TYPE_LIST)) {
@@ -3139,6 +3075,13 @@ public class MtasSolrSearchComponent extends SearchComponent {
       }
     }
 
+    /**
+     * Gets the named list.
+     *
+     * @param showDebugInfo the show debug info
+     * @return the named list
+     * @throws IOException Signals that an I/O exception has occurred.
+     */
     NamedList<Object> getNamedList(boolean showDebugInfo) throws IOException {
       return getNamedList(false, showDebugInfo);
     }
@@ -3146,9 +3089,10 @@ public class MtasSolrSearchComponent extends SearchComponent {
     /**
      * Gets the named list.
      *
+     * @param showFull the show full
+     * @param showDebugInfo the show debug info
      * @return the named list
-     * @throws IOException
-     *           Signals that an I/O exception has occurred.
+     * @throws IOException Signals that an I/O exception has occurred.
      */
     private NamedList<Object> getNamedList(boolean showFull,
         boolean showDebugInfo) throws IOException {
diff --git a/src/mtas/solr/update/processor/MtasUpdateRequestProcessorResultReader.java b/src/mtas/solr/update/processor/MtasUpdateRequestProcessorResultReader.java
index d1e0c51..70f9c51 100644
--- a/src/mtas/solr/update/processor/MtasUpdateRequestProcessorResultReader.java
+++ b/src/mtas/solr/update/processor/MtasUpdateRequestProcessorResultReader.java
@@ -15,25 +15,26 @@ public class MtasUpdateRequestProcessorResultReader implements Closeable {
   /** The stored string value. */
   private String storedStringValue;
 
+  /** The file input stream. */
   private FileInputStream fileInputStream;
 
   /** The object input stream. */
   private ObjectInputStream objectInputStream;
 
+  /** The file. */
   private File file;
 
   /** The iterator. */
   private Iterator<MtasUpdateRequestProcessorResultItem> iterator;
 
+  /** The closed. */
   private boolean closed;
 
   /**
    * Instantiates a new mtas update request processor result reader.
    *
-   * @param fileName
-   *          the file name
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @param fileName the file name
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   public MtasUpdateRequestProcessorResultReader(String fileName)
       throws IOException {
diff --git a/src/mtas/solr/update/processor/MtasUpdateRequestProcessorResultWriter.java b/src/mtas/solr/update/processor/MtasUpdateRequestProcessorResultWriter.java
index 4e278fc..aeb5ae2 100644
--- a/src/mtas/solr/update/processor/MtasUpdateRequestProcessorResultWriter.java
+++ b/src/mtas/solr/update/processor/MtasUpdateRequestProcessorResultWriter.java
@@ -12,22 +12,25 @@ import org.apache.lucene.util.BytesRef;
  */
 public class MtasUpdateRequestProcessorResultWriter implements Closeable {
 
+  /** The object output stream. */
   private ObjectOutputStream objectOutputStream;
 
+  /** The file output stream. */
   private FileOutputStream fileOutputStream;
 
+  /** The closed. */
   private boolean closed;
 
+  /** The token number. */
   private int tokenNumber;
 
+  /** The file. */
   private File file;
 
   /**
    * Instantiates a new mtas update request processor result writer.
    *
-   * @param value
-   *          the value
-   * @throws IOException
+   * @param value the value
    */
   public MtasUpdateRequestProcessorResultWriter(String value) {
     closed = false;
@@ -48,19 +51,12 @@ public class MtasUpdateRequestProcessorResultWriter implements Closeable {
   /**
    * Adds the item.
    *
-   * @param term
-   *          the term
-   * @param offsetStart
-   *          the offset start
-   * @param offsetEnd
-   *          the offset end
-   * @param posIncr
-   *          the pos incr
-   * @param payload
-   *          the payload
-   * @param flags
-   *          the flags
-   * @throws IOException
+   * @param term the term
+   * @param offsetStart the offset start
+   * @param offsetEnd the offset end
+   * @param posIncr the pos incr
+   * @param payload the payload
+   * @param flags the flags
    */
   public void addItem(String term, Integer offsetStart, Integer offsetEnd,
       Integer posIncr, BytesRef payload, Integer flags) {
@@ -78,16 +74,20 @@ public class MtasUpdateRequestProcessorResultWriter implements Closeable {
     }
   }
 
+  /**
+   * Gets the token number.
+   *
+   * @return the token number
+   */
   public int getTokenNumber() {
     return tokenNumber;
   }
 
   /**
-   * Creates the file.
+   * Gets the file name.
    *
-   * @return the string
-   * @throws IOException
-   *           Signals that an I/O exception has occurred.
+   * @return the file name
+   * @throws IOException Signals that an I/O exception has occurred.
    */
   public String getFileName() throws IOException {
     if (file != null) {
@@ -97,6 +97,9 @@ public class MtasUpdateRequestProcessorResultWriter implements Closeable {
     }
   }
 
+  /* (non-Javadoc)
+   * @see java.io.Closeable#close()
+   */
   @Override
   public void close() throws IOException {
     if (!closed) {
@@ -106,6 +109,9 @@ public class MtasUpdateRequestProcessorResultWriter implements Closeable {
     }
   }
 
+  /**
+   * Force close and delete.
+   */
   public void forceCloseAndDelete() {
     try {
       if (objectOutputStream != null) {
diff --git a/src/site/markdown/download.md b/src/site/markdown/download.md.vm
index f15bf4d..539c97a 100644
--- a/src/site/markdown/download.md
+++ b/src/site/markdown/download.md.vm
@@ -11,11 +11,11 @@
       <th>Description</th>
     </tr>
     <tr>
-      <td>6.1.0</td>
-      <td>20160714</td>
-      <td><a href='https://github.com/matthijsbrouwer/mtas/releases/download/20160714/mtas-6.1.0.jar'>Binary (jar)</a></td>
-      <td><a href='https://github.com/matthijsbrouwer/mtas/archive/20160714.tar.gz'>Source (tgz)</a></td>
-      <td><a href='https://github.com/matthijsbrouwer/mtas/archive/20160714.zip'>Source (zip)</a></td>
+      <td>$context.get("currentDevelopmentVersion")</td>
+      <td>$context.get("currentDevelopmentRelease")</td>
+      <td><a href='https://github.com/matthijsbrouwer/mtas/releases/download/${currentDevelopmentRelease}/mtas-${currentDevelopmentVersion}.jar'>Binary (jar)</a></td>
+      <td><a href='https://github.com/matthijsbrouwer/mtas/archive/${currentDevelopmentRelease}.tar.gz'>Source (tgz)</a></td>
+      <td><a href='https://github.com/matthijsbrouwer/mtas/archive/${currentDevelopmentRelease}.zip'>Source (zip)</a></td>
       <td>Development version</td>
     </tr>
   </tbody>
diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md
index f469b6c..1b1cc0f 100644
--- a/src/site/markdown/index.md
+++ b/src/site/markdown/index.md
@@ -1 +1,21 @@
 #Multi Tier Annotation Search
+
+##Download binary
+
+Prebuilt JARs for Mtas are available from the [Download](downloads.html) page.
+
+##Building from source
+
+Download the source code from GitHub
+
+```
+git clone git://github.com/meertensinstituut/mtas.git
+```
+
+To build the library, from the created project directory
+
+```
+mvn package
+```
+
+
diff --git a/src/site/markdown/installation.md b/src/site/markdown/installation.md
index e69de29..452122f 100644
--- a/src/site/markdown/installation.md
+++ b/src/site/markdown/installation.md
@@ -0,0 +1,10 @@
+#Getting started
+
+test
+
+```
+TEST
+```
+
+eind test
+
diff --git a/src/site/markdown/installation_lucene.md b/src/site/markdown/installation_lucene.md
new file mode 100644
index 0000000..616d469
--- /dev/null
+++ b/src/site/markdown/installation_lucene.md
@@ -0,0 +1 @@
+#Installation Lucene
\ No newline at end of file
diff --git a/src/site/markdown/installation_solr.md b/src/site/markdown/installation_solr.md
new file mode 100644
index 0000000..3a6adc1
--- /dev/null
+++ b/src/site/markdown/installation_solr.md
@@ -0,0 +1 @@
+#Installation Solr
diff --git a/src/site/resources/images/meertens.png b/src/site/resources/images/meertens.png
new file mode 100644
index 0000000..beffe72
--- /dev/null
+++ b/src/site/resources/images/meertens.png
diff --git a/src/site/site.xml b/src/site/site.xml
index 6930bee..4f1d542 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -1,8 +1,24 @@
 <project name="Multi Tier Annotation Search">
+  <bannerRight>
+    <name>Meertens Instituut</name>
+    <src>images/meertens.png</src>
+    <href>http://www.meertens.knaw.nl/</href>
+    <width>147</width>
+    <height>100</height>
+    <title>Meertens Instituut</title>
+  </bannerRight>
+  <skin>
+    <groupId>org.apache.maven.skins</groupId>
+    <artifactId>maven-fluido-skin</artifactId>
+    <version>1.5</version>
+  </skin>
   <body>
     <menu name="Mtas">
       <item name="Introduction" href="index.html"/>
-      <item name="Installation" href="installation.html"/>
+      <item name="Getting started" href="installation.html">
+        <item name="Lucene" href="installation_lucene.html"/>
+        <item name="Solr" href="installation_solr.html"/>
+      </item>
       <item name="Download" href="download.html"/>      
     </menu>
     <menu ref="reports"/>