- MAJOR REFACTORING in Poliqarp: strongly changed grammar and serialiser, results in much better readable and maintainable (and shorter!) code
- restructuring: PQ+ grammars in own directory, adapted package name for generated Parser/Lexer classes
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java
index e7bf8bd..a7f6dea 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java
@@ -64,7 +64,7 @@
 		return group;
 	}
 	
-	protected LinkedHashMap<String, Object> makeClass(int classCount) {
+	protected LinkedHashMap<String, Object> makeSpanClass(int classCount) {
 		LinkedHashMap<String, Object> group = new LinkedHashMap<String, Object>();
 		group.put("@type", "korap:group");
 		group.put("operation", "operation:class");
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr4AbstractSyntaxTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr4AbstractSyntaxTree.java
index 59a248a..216cfb0 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr4AbstractSyntaxTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/Antlr4AbstractSyntaxTree.java
@@ -78,11 +78,19 @@
     }
 
     public ParseTree getFirstChildWithCat(ParseTree node, String nodeCat) {
-        for (int i = 0; i < node.getChildCount(); i++) {
-            if (getNodeCat(node.getChild(i)).equals(nodeCat)) {
-                return node.getChild(i);
-            }
-        }
+        return getNthChildWithCat(node, nodeCat, 1);
+    }
+    
+    public ParseTree getNthChildWithCat(ParseTree node, String nodeCat, int n) {
+    	int counter = 0;
+    	for (int i = 0; i < node.getChildCount(); i++) {
+    		if (getNodeCat(node.getChild(i)).equals(nodeCat)) {
+    			counter++;
+    			if (counter == n) {
+    				return node.getChild(i);
+    			}
+    		}
+    	}
         return null;
     }
     
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java
index 2668b65..8412bc0 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java
@@ -1,7 +1,7 @@
 package de.ids_mannheim.korap.query.serialize;
 
-import de.ids_mannheim.korap.query.PoliqarpPlusLexer;
-import de.ids_mannheim.korap.query.PoliqarpPlusParser;
+import de.ids_mannheim.korap.query.poliqarp.PoliqarpPlusLexer;
+import de.ids_mannheim.korap.query.poliqarp.PoliqarpPlusParser;
 import de.ids_mannheim.korap.util.QueryException;
 import org.antlr.v4.runtime.*;
 import org.antlr.v4.runtime.tree.ParseTree;
@@ -18,704 +18,318 @@
  */
 public class PoliqarpPlusTree extends Antlr4AbstractSyntaxTree {
 
-    Logger log = LoggerFactory.getLogger(PoliqarpPlusTree.class);
-    /**
-     * Top-level map representing the whole request.
-     */
-    LinkedHashMap<String, Object> requestMap = new LinkedHashMap<String, Object>();
-    /**
-     * Keeps track of open node categories
-     */
-    LinkedList<String> openNodeCats = new LinkedList<String>();
-    /**
-     * Flag that indicates whether token fields or meta fields are currently being processed
-     */
-    private boolean inMeta = false;
-    /**
-     * Flag that indicates whether a cq_segment is to be ignored (e.g. when it is empty, is followed directly by only a spanclass and has no other children etc...).
-     */
-    private boolean ignoreCq_segment = false;
-    /**
-     * Flag that indicates whether a cq_segments element is quantified by an occ element.
-     */
-    private boolean cqHasOccSibling = false;
-    /**
-     * Flag that indicates whether a cq_segments' children are quantified by an occ element.
-     */
-    private boolean cqHasOccChild = false;
-    /**
-     * Flag for negation of complete field
-     */
-    private boolean negField = false;
-    /**
-     * Parser object deriving the ANTLR parse tree.
-     */
-    private Parser parser;
-    /**
-     * Keeps track of all visited nodes in a tree
-     */
-    private List<ParseTree> visited = new ArrayList<ParseTree>();
+	Logger log = LoggerFactory.getLogger(PoliqarpPlusTree.class);
+	/**
+	 * Top-level map representing the whole request.
+	 */
+	LinkedHashMap<String, Object> requestMap = new LinkedHashMap<String, Object>();
+	/**
+	 * Keeps track of open node categories
+	 */
+	LinkedList<String> openNodeCats = new LinkedList<String>();
+	/**
+	 * Flag that indicates whether a cq_segment is to be ignored (e.g. when it is empty, is followed directly by only a spanclass and has no other children etc...).
+	 */
+	private boolean negField = false;
+	/**
+	 * Parser object deriving the ANTLR parse tree.
+	 */
+	private Parser parser;
+	/**
+	 * Keeps track of all visited nodes in a tree
+	 */
+	private List<ParseTree> visited = new ArrayList<ParseTree>();
+	/**
+	 * Keeps track of active object.
+	 */
+	private LinkedList<LinkedHashMap<String, Object>> objectStack = new LinkedList<LinkedHashMap<String, Object>>();
+	/**
+	 * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
+	 */
+	private LinkedList<Integer> objectsToPop = new LinkedList<Integer>();
+	/**
+	 * If true, print debug statements
+	 */
+	public static boolean verbose = false;
+	ParseTree currentNode = null;
+	Integer stackedObjects = 0;
 
-    /**
-     * Keeps track of active fields (like 'base=foo').
-     */
-    private LinkedList<ArrayList<Object>> fieldStack = new LinkedList<ArrayList<Object>>();
-    /**
-     * Keeps track of active tokens.
-     */
-    private LinkedList<LinkedHashMap<String, Object>> tokenStack = new LinkedList<LinkedHashMap<String, Object>>();
-    /**
-     * Marks the currently active token in order to know where to add flags (might already have been taken away from token stack).
-     */
-    private LinkedHashMap<String, Object> curToken = new LinkedHashMap<String, Object>();
-    /**
-     * Keeps track of active object.
-     */
-    private LinkedList<LinkedHashMap<String, Object>> objectStack = new LinkedList<LinkedHashMap<String, Object>>();
-    /**
-     * Marks the object to which following occurrence information is to be added.
-     */
-    private LinkedHashMap<String, Object> curOccGroup = new LinkedHashMap<String, Object>();
-    /**
-     * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
-     */
-    private LinkedList<Integer> objectsToPop = new LinkedList<Integer>();
-    /**
-     * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
-     */
-    private LinkedList<Integer> tokensToPop = new LinkedList<Integer>();
-    /**
-     * Keeps track of how many objects there are to pop after every recursion of {@link #processNode(ParseTree)}
-     */
-    LinkedList<Integer> fieldsToPop = new LinkedList<Integer>();
-    /**
-     * If true, print debug statements
-     */
-    public static boolean verbose = false;
-    /**
-     * Index of the current child of its parent (needed for relating occ elements to their operands).
-     */
-    private int curChildIndex = 0;
-    /**
-     *
-     */
-    ParseTree currentNode = null;
-    Integer stackedObjects = 0;
-    Integer stackedTokens = 0;
-    Integer stackedFields = 0;
+	/**
+	 * Most centrally, this class maintains a set of nested maps and lists which represent the JSON tree, which is built by the JSON serialiser
+	 * on basis of the {@link #requestMap} at the root of the tree.
+	 * <br/>
+	 * The class further maintains a set of stacks which effectively keep track of which objects to embed in which containing objects.
+	 *
+	 * @param query The syntax tree as returned by ANTLR
+	 * @throws QueryException
+	 */
+	public PoliqarpPlusTree(String query) throws QueryException {
+		process(query);
+		System.out.println(">>> " + requestMap.get("query") + " <<<");
+		log.info(">>> " + requestMap.get("query") + " <<<");
+	}
 
+	@Override
+	public Map<String, Object> getRequestMap() {
+		return requestMap;
+	}
 
-    /**
-     * Most centrally, this class maintains a set of nested maps and lists which represent the JSON tree, which is built by the JSON serialiser
-     * on basis of the {@link #requestMap} at the root of the tree.
-     * <br/>
-     * The class further maintains a set of stacks which effectively keep track of which objects to embed in which containing objects.
-     *
-     * @param query The syntax tree as returned by ANTLR
-     * @throws QueryException
-     */
-    public PoliqarpPlusTree(String query) throws QueryException {
-        try {
-            process(query);
-        } catch (NullPointerException e) {
-            if (query.contains(" ")) {
-                System.err.println("Warning: It seems like your query contains illegal whitespace characters. Trying again with whitespaces removed...");
-                query = query.replaceAll(" ", "");
-                process(query);
-            } else {
-                throw new QueryException("Error handling query.");
-            }
-        }
-        System.out.println(">>> " + requestMap.get("query") + " <<<");
-        log.info(">>> " + requestMap.get("query") + " <<<");
-    }
+	@Override
+	public void process(String query) throws QueryException {
+		ParseTree tree;
+		tree = parsePoliqarpQuery(query);
+		super.parser = this.parser;
+		log.info("Processing PoliqarpPlus");
+		requestMap.put("@context", "http://ids-mannheim.de/ns/KorAP/json-ld/v0.1/context.jsonld");
+		processNode(tree);
+	}
 
-    @Override
-    public Map<String, Object> getRequestMap() {
-        return requestMap;
-    }
+	/**
+	 * Recursively calls itself with the children of the currently active node, traversing the tree nodes in a top-down, depth-first fashion.
+	 * A list is maintained that contains all visited nodes
+	 * in case they have been directly addressed by its (grand-/grand-grand-/...) parent node, such that some processing time is saved, as these node will
+	 * not be processed. This method is effectively a list of if-statements that are responsible for treating the different node types correctly and filling the
+	 * respective maps/lists.
+	 *
+	 * @param node The currently processed node. The process(String query) method calls this method with the root.
+	 * @throws QueryException
+	 */
+	private void processNode(ParseTree node) throws QueryException {
+		// Top-down processing
+		if (visited.contains(node)) return;
+		else visited.add(node);
 
-    @Override
-    public void process(String query) throws QueryException {
-        ParseTree tree;
-        try {
-            tree = parsePoliqarpQuery(query);
-        } catch (QueryException e) {
-            // if the second time query could not be parsed, throw exception!
-            tree = parsePoliqarpQuery(query.replaceAll(" ", ""));
-        }
-        super.parser = this.parser;
-        log.info("Processing PoliqarpPlus");
-        System.out.println("Processing PoliqarpPlus");
-        requestMap.put("@context", "http://ids-mannheim.de/ns/KorAP/json-ld/v0.1/context.jsonld");
-//		prepareContext(requestMap);
-        processNode(tree);
-    }
+		currentNode = node;
 
-    /**
-     * Recursively calls itself with the children of the currently active node, traversing the tree nodes in a top-down, depth-first fashion.
-     * A list is maintained that contains all visited nodes
-     * in case they have been directly addressed by its (grand-/grand-grand-/...) parent node, such that some processing time is saved, as these node will
-     * not be processed. This method is effectively a list of if-statements that are responsible for treating the different node types correctly and filling the
-     * respective maps/lists.
-     *
-     * @param node The currently processed node. The process(String query) method calls this method with the root.
-     * @throws QueryException
-     */
-    @SuppressWarnings("unchecked")
-    private void processNode(ParseTree node) throws QueryException {
-        // Top-down processing
-        if (visited.contains(node)) return;
-        else visited.add(node);
+		String nodeCat = getNodeCat(node);
+		openNodeCats.push(nodeCat);
 
-        currentNode = node;
-        
-        String nodeCat = getNodeCat(node);
-        openNodeCats.push(nodeCat);
+		stackedObjects = 0;
 
-        stackedObjects = 0;
-        stackedTokens = 0;
-        stackedFields = 0;
-
-        if (verbose) {
-            System.err.println(" " + objectStack);
-            System.out.println(openNodeCats);
-        }
+		if (verbose) {
+			System.err.println(" " + objectStack);
+			System.out.println(openNodeCats);
+		}
 
 
 		/*
-         ****************************************************************
+		 ****************************************************************
 		 **************************************************************** 
 		 * 			Processing individual node categories  				*
 		 ****************************************************************
 		 ****************************************************************
 		 */
 
-        // cq_segments/sq_segments: token group
-        if (nodeCat.equals("cq_segments") || nodeCat.equals("sq_segments")) {
-            cqHasOccSibling = false;
-            cqHasOccChild = false;
-            // disregard empty segments in simple queries (parsed by ANTLR as empty cq_segments)
-            ignoreCq_segment = (node.getChildCount() == 1 && (node.getChild(0).toStringTree(parser).equals(" ") || getNodeCat(node.getChild(0)).equals("spanclass") || getNodeCat(node.getChild(0)).equals("position")));
-//            ignoreCq_segment = ignoreCq_segment | (node.getParent().getChildCount()==2 && getNodeCat(node.getParent().getChild(1)).equals("flag"));
-            
-//            ignoreCq_segment = (node.getChildCount() == 1 && (node.getChild(0).toStringTree(parser).equals(" ") || getNodeCat(node.getChild(0)).equals("position")));
-            // ignore this node if it only serves as an aligned sequence container
-            if (node.getChildCount() > 1) {
-                if (getNodeCat(node.getChild(1)).equals("cq_segments") && hasChild(node.getChild(1), "alignment")) {
-                    ignoreCq_segment = true;
-                }
-                if (getNodeCat(node.getChild(0)).equals("(") && getNodeCat(node.getChild(node.getChildCount()-1)).equals(")")) {
-                    ignoreCq_segment = true;
-                }
-            }
-            if (!ignoreCq_segment) {
-                LinkedHashMap<String, Object> sequence = new LinkedHashMap<String, Object>();
-                // Step 0:  cq_segments has 'occ' child -> introduce group as super group to the sequence/token/group
-                // this requires creating a group and inserting it at a suitable place
-                if (node.getParent().getChildCount() > curChildIndex + 2 && getNodeCat(node.getParent().getChild(curChildIndex + 2)).equals("occ")) {
-                    cqHasOccSibling = true;
-                    createOccGroup(node);
-                }
-                if (getNodeCat(node.getChild(node.getChildCount() - 1)).equals("occ")) {
-                    cqHasOccChild = true;
-                }
-                // Step I: decide type of element (one or more elements? -> token or sequence)
-                // take into account a possible 'occ' child with accompanying parantheses, therefore 3 extra children
-                int occExtraChildren = cqHasOccChild ? 3 : 0;
-                if (node.getChildCount() > 1 + occExtraChildren) {
-                    ParseTree emptySegments = getFirstChildWithCat(node, "empty_segments");
-                    if (emptySegments != null && emptySegments != node.getChild(0)) {
-                        String[] minmax = parseEmptySegments(emptySegments);
-                        Integer min = Integer.parseInt(minmax[0]);
-                        Integer max = Integer.parseInt(minmax[1]);
-                        sequence.put("@type", "korap:group");
-                        sequence.put("operation", "operation:sequence");
-                        sequence.put("inOrder", true);
-                        ArrayList<Object> constraint = new ArrayList<Object>();
-                        sequence.put("distances", constraint);
-                        ArrayList<Object> sequenceOperands = new ArrayList<Object>();
-                        sequence.put("operands", sequenceOperands);
-                        objectStack.push(sequence);
-                        stackedObjects++;
-                        LinkedHashMap<String, Object> distMap = new LinkedHashMap<String, Object>();
-                        constraint.add(distMap);
-                        distMap.put("@type", "korap:distance");
-                        distMap.put("key", "w");
-                        distMap.put("min", min);
-                        distMap.put("max", max);
-                    } else {
-                        sequence = makeGroup("sequence");
-                        if (emptySegments != null) {
-                            String[] minmax = parseEmptySegments(emptySegments);
-                            Integer min = Integer.parseInt(minmax[0]);
-                            Integer max = Integer.parseInt(minmax[1]);
-                            sequence.put("offset-min", min - 1);
-                            sequence.put("offset-max", max - 1);
-                        }
-                        objectStack.push(sequence);
-                        stackedObjects++;
-                    }
-                } else {
-                    // if only child, make the sequence a mere token...
-                    // ... but only if it has a real token/element beneath it
-                    if (!isContainerOnly(node)) {
-                        sequence.put("@type", "korap:token");
-                        tokenStack.push(sequence);
-                        stackedTokens++;
-                        objectStack.push(sequence);
-                        stackedObjects++;
-                        // else, it's a group (with shrink()/spanclass/align... as child)
-                    } else {
-//						sequence.put("@type", "korap:group");
-//						objectStack.push(sequence);
-//						stackedObjects++;
-                    }
-                }
-                // Step II: decide where to put this element
-                // check if this is an argument for a containing occurrence group (see step 0)
-                if (cqHasOccSibling) {
-                    ArrayList<Object> topGroupOperands = (ArrayList<Object>) objectStack.get(1).get("operands");
-                    topGroupOperands.add(sequence);
-                    // ...if not modified by occurrence, put into appropriate super object
-                } else {
-                    if (openNodeCats.get(1).equals("query")) {
-                        // cq_segment is top query node
-                        if (node.getParent().getChildCount() == 1) {
-                            // only child
-                            requestMap.put("query", sequence);
-                        } else {
-                            // not an only child, need to create containing sequence
-                            if (node.getParent().getChild(0).equals(node)) {
-                                // if first child, create containing sequence and embed there
-                                LinkedHashMap<String, Object> superSequence = new LinkedHashMap<String, Object>();
-                                superSequence.put("@type", "korap:group");
-                                superSequence.put("operation", "operation:" + "sequence");
-                                ArrayList<Object> operands = new ArrayList<Object>();
-                                superSequence.put("operands", operands);
-                                operands.add(sequence);
-                                requestMap.put("query", superSequence);
-                                objectStack.push(superSequence); // add at 2nd position to keep current cq_segment accessible
-                                stackedObjects++;
-                            } else {
-                                // if not first child, add to previously created parent sequence
-                                ArrayList<Object> topSequenceOperands;
-                                try {
-                                    topSequenceOperands = (ArrayList<Object>) objectStack.get(1).get("operands");
-                                } catch (IndexOutOfBoundsException e) {
-                                    // Normally, the current element has been added to the object stack, so the try-block works fine.
-                                    // In some cases however, the element is not added (see ultimate else-block in Step I), and we need a
-                                    // fallback to the first element in the object stack.
-                                    topSequenceOperands = (ArrayList<Object>) objectStack.get(0).get("operands");
-                                }
-                                topSequenceOperands.add(sequence);
-                            }
-                        }
-                    } else if (!objectStack.isEmpty()) {
-                        // embed in super sequence
-                        ArrayList<Object> topSequenceOperands;
-                        if (!isContainerOnly(node)) {
-                            try {
-                                topSequenceOperands = (ArrayList<Object>) objectStack.get(1).get("operands");
-                                topSequenceOperands.add(sequence);
-                            } catch (IndexOutOfBoundsException e) {
-//								topSequenceOperands = (ArrayList<Object>) objectStack.get(0).get("operands");
-                            }
-                        }
+		if (nodeCat.equals("segment")) {
+			// Cover possible quantification (i.e. repetition) of segment
+			ParseTree quantification = getFirstChildWithCat(node, "repetition");
+			if (quantification != null) {
+				LinkedHashMap<String,Object> quantGroup = makeGroup("repetition");
+				int[] minmax = parseRepetition(quantification);
+				quantGroup.put("min", minmax[0]);
+				quantGroup.put("max", minmax[1]);
+				putIntoSuperObject(quantGroup);
+				objectStack.push(quantGroup);
+				stackedObjects++;
+			}
+		}
+
+		if (nodeCat.equals("sequence")) {
+			LinkedHashMap<String,Object> sequence = makeGroup("sequence");
+			ParseTree emptyTokens = getFirstChildWithCat(node, "emptyTokenSequence");
+			if (emptyTokens!=null) {
+				int[] minmax = parseEmptySegments(emptyTokens);
+				LinkedHashMap<String,Object> distance = makeDistance("w", minmax[0], minmax[1]);
+				sequence.put("inOrder", true);
+				ArrayList<Object> distances = new ArrayList<Object>();
+				distances.add(distance);
+				sequence.put("distances", distances);
+			}
+			putIntoSuperObject(sequence);
+			objectStack.push(sequence);
+			stackedObjects++;
+		}
+
+		if (nodeCat.equals("token")) {
+			LinkedHashMap<String,Object> token = makeToken();
+			List<ParseTree> negations = getChildrenWithCat(node, "!");
+			boolean negated = false;
+			if (negations.size() % 2 == 1) negated = true;
+			if (getNodeCat(node.getChild(0)).equals("key")) {
+				LinkedHashMap<String,Object> term = makeTerm();
+				
+				String key = node.getChild(0).getText();
+				if (getNodeCat(node.getChild(0).getChild(0)).equals("regex")) {
+					term.put("type", "type:regex");
+					key = key.substring(1,key.length()-1);
+				}
+				term.put("layer", "orth");
+				term.put("key", key);
+				String matches = negated ? "ne" : "eq";
+				term.put("match", "match:"+matches);
+				ParseTree flagNode = getFirstChildWithCat(node, "flag");
+				if (flagNode != null) {
+					String flag = getNodeCat(flagNode.getChild(0)).substring(1); //substring removes leading slash '/'
+					System.err.println(flag);
+					if (flag.contains("i")) term.put("caseInsensitive", true);
+					else if (flag.contains("I")) term.put("caseInsensitive", false);
+					if (flag.contains("x")) {
+						term.put("key", ".*?"+key+".*?");
+					}
+				}
+				token.put("wrap", term);
+			} else {
+				LinkedHashMap<String,Object> termOrTermGroup = parseTermOrTermGroup(node.getChild(1), negated);
+				token.put("wrap", termOrTermGroup);
+			}
+			putIntoSuperObject(token);
+			visited.add(node.getChild(0));
+			visited.add(node.getChild(2));
+		}
+
+		if (nodeCat.equals("alignment")) {
+			LinkedHashMap<String,Object> aligned = makeGroup("alignment");
+			aligned.put("align", "align:left");
+			putIntoSuperObject(aligned);
+			objectStack.push(aligned);
+			stackedObjects++;
+		}
+
+		if (nodeCat.equals("span")) {
+			LinkedHashMap<String,Object> span = makeSpan();
+			ParseTree keyNode = getFirstChildWithCat(node, "key");
+			ParseTree layerNode = getFirstChildWithCat(node, "layer");
+			ParseTree foundryNode = getFirstChildWithCat(node, "foundry");
+			ParseTree termOpNode = getFirstChildWithCat(node, "termOp");
+			if (foundryNode != null) span.put("foundry", foundryNode.getText());
+			if (layerNode != null) {
+				String layer = layerNode.getText();
+				if (layer.equals("base")) layer="lemma";
+				span.put("layer", layer);
+			}
+			span.put("key", keyNode.getText());
+			if (termOpNode != null) {
+				String termOp = termOpNode.getText();
+				if (termOp.equals("==")) span.put("matches", "matches:eq");
+				else if (termOp.equals("!=")) span.put("matches", "matches:ne");
+			}
+			putIntoSuperObject(span);
+			objectStack.push(span);
+			stackedObjects++;
+		}
+
+		if (nodeCat.equals("disjunction")) {
+			LinkedHashMap<String,Object> disjunction = makeGroup("or");
+			putIntoSuperObject(disjunction);
+			objectStack.push(disjunction);
+			stackedObjects++;
+		}
+
+		if (nodeCat.equals("position")) {
+			LinkedHashMap<String,Object> position = makePosition(parseFrame(node.getChild(0)));
+			putIntoSuperObject(position);
+			objectStack.push(position);
+			stackedObjects++;
+			// offsets
+			if (hasChild(node, "emptyTokenSequence")) {
+				LinkedHashMap<String,Object> sequence = makeGroup("sequence");
+				ParseTree leftOffset = getNthChildWithCat(node, "emptyTokenSequence", 1);
+				if (leftOffset!=null) {
+					int[] minmax = parseEmptySegments(leftOffset);
+					sequence.put("leftoffset-min", minmax[0]-1);
+					sequence.put("leftoffset-max", minmax[1]-1);
+				}
+				ParseTree rightOffset = getNthChildWithCat(node, "emptyTokenSequence", 2);
+				if (rightOffset!=null) {
+					int[] minmax = parseEmptySegments(rightOffset);
+					sequence.put("rightoffset-min", minmax[0]-1);
+					sequence.put("rightoffset-max", minmax[1]-1);
+				}
+				putIntoSuperObject(sequence);
+				objectStack.push(sequence);
+				stackedObjects++;
+			}
+		}
+
+		if (nodeCat.equals("spanclass")) {
+			// Step I: get info
+			int classId = 0;
+			if (getNodeCat(node.getChild(1)).equals("spanclass_id")) {
+				String ref = node.getChild(1).getChild(0).toStringTree(parser);
+				try {
+					classId = Integer.parseInt(ref);
+				} catch (NumberFormatException e) {
+					log.error("The specified class reference in the focus/split-Operator is not a number: " + ref);
+					throw new QueryException("The specified class reference in the focus/split-Operator is not a number: " + ref);
+				}
+				// only allow class id up to 255
+				if (classId > 255) {
+					classId = 0;
+				}
+			}
+			LinkedHashMap<String, Object> classGroup = makeSpanClass(classId);
+			putIntoSuperObject(classGroup);
+			objectStack.push(classGroup);
+			stackedObjects++;
+		}
 
 
-                    }
-                }
-            }
-        }
+		if (nodeCat.equals("matching")) {
+			// Step I: get info
+			ArrayList<Integer> classRefs = new ArrayList<Integer>();
+			String classRefOp = null;
+			if (getNodeCat(node.getChild(2)).equals("spanclass_id")) {
+				ParseTree spanNode = node.getChild(2);
+				for (int i = 0; i < spanNode.getChildCount() - 1; i++) {
+					String ref = spanNode.getChild(i).getText();
+					if (ref.equals("|") || ref.equals("&")) {
+						classRefOp = ref.equals("|") ? "intersection" : "union";
+					} else {
+						try {
+							int classRef = Integer.parseInt(ref);
+							classRefs.add(classRef);
+						} catch (NumberFormatException e) {
+							throw new QueryException("The specified class reference in the shrink/split-Operator is not a number.");
+						}
+					}
+				}
+			} else {
+				classRefs.add(0);
+			}
+			LinkedHashMap<String, Object> referenceGroup = makeReference(classRefs);
 
-        // cq_segment
-        if (nodeCat.equals("cq_segment")) {
-            int onTopOfObjectStack = 0;
-            // Step I: determine whether to create new token or get token from the stack (if added by cq_segments)
-            LinkedHashMap<String, Object> token = makeToken();
-            if (tokenStack.isEmpty()) {
-                token = new LinkedHashMap<String, Object>();
-                tokenStack.push(token);
-                stackedTokens++;
-                // do this only if token is newly created, otherwise it'll be in objectStack twice
-                objectStack.push(token);
-                onTopOfObjectStack = 1;
-                stackedObjects++;
-            } else {
-                // in case cq_segments has already added the token
-                token = tokenStack.getFirst();
-            }
-            curToken = token;
-            // Step II: start filling object and add to containing sequence
-            token.put("@type", "korap:token");
-            // add token to sequence only if it is not an only child (in that case, cq_segments has already added the info and is just waiting for the values from "field")
-            // take into account a possible 'occ' child
-            if (node.getParent().getChildCount() > 1) {
-                if (node.getText().equals("[]")) {
-                } else {
-                    ArrayList<Object> topSequenceOperands = (ArrayList<Object>) objectStack.get(onTopOfObjectStack).get("operands");
-                    topSequenceOperands.add(token);
-                }
-            }
-        }
+			String type = node.getChild(0).toStringTree(parser);
+			if (type.equals("split")) referenceGroup.put("operation", "operation:split");
+			if (classRefOp != null) {
+				referenceGroup.put("classRefOp", "classRefOp:" + classRefOp);
+			}
+			ArrayList<Object> referenceOperands = new ArrayList<Object>();
+			referenceGroup.put("operands", referenceOperands);
+			// Step II: decide where to put the group
+			putIntoSuperObject(referenceGroup);
+			objectStack.push(referenceGroup);
+			stackedObjects++;
+			visited.add(node.getChild(0));
+		}
 
-        // cq_segment modified by occurrence
-        if (nodeCat.equals("cq_seg_occ")) {
-            LinkedHashMap<String, Object> group = makeGroup("repetition");
-            curOccGroup = group;
-            putIntoSuperObject(group);
-            objectStack.push(group);
-            stackedObjects++;
-        }
+		if (nodeCat.equals("meta")) {
+			LinkedHashMap<String, Object> metaFilter = new LinkedHashMap<String, Object>();
+			requestMap.put("meta", metaFilter);
+			metaFilter.put("@type", "korap:meta");
+		}
 
-        // disjoint cq_segments, like ([base=foo][base=bar])|[base=foobar]
-        if (nodeCat.equals("cq_disj_segments")) {
-            LinkedHashMap<String, Object> disjunction = new LinkedHashMap<String, Object>();
-            objectStack.push(disjunction);
-            stackedObjects++;
-            ArrayList<Object> disjOperands = new ArrayList<Object>();
-            disjunction.put("@type", "korap:group");
-            disjunction.put("operation", "operation:" + "or");
-            disjunction.put("operands", disjOperands);
-            // decide where to put the disjunction
-            if (openNodeCats.get(1).equals("query")) {
-                requestMap.put("query", disjunction);
-            } else if (openNodeCats.get(1).equals("cq_segments")) {
-                ArrayList<Object> topSequenceOperands = (ArrayList<Object>) objectStack.get(1).get("operands");
-                topSequenceOperands.add(disjunction);
-            }
-        }
+		if (nodeCat.equals("within") && !getNodeCat(node.getParent()).equals("position")) {
+			ParseTree domainNode = node.getChild(2);
+			String domain = getNodeCat(domainNode);
+			LinkedHashMap<String, Object> curObject = (LinkedHashMap<String, Object>) objectStack.getFirst();
+			curObject.put("within", domain);
+			visited.add(node.getChild(0));
+			visited.add(node.getChild(1));
+			visited.add(domainNode);
+		}
 
-        // field element (outside meta)
-        if (nodeCat.equals("field")) {
-            LinkedHashMap<String, Object> fieldMap = makeTerm();
-            // Step I: extract info
-            String layer = "";
-            String foundry = null;
-            String value = null;
-            String key = null;
-            ParseTree fieldNameNode = node.getChild(0);
-            if (fieldNameNode.getChildCount() == 1) {
-                layer = fieldNameNode.getChild(0).toStringTree(parser);   //e.g. (field_name base) (field_op !=) (re_query "bar*")
-            } else if (fieldNameNode.getChildCount() == 3) {
-                // layer is indicated, merge layer and field name (0th and 2nd children, 1st is "/")
-                foundry = fieldNameNode.getChild(0).toStringTree(parser);
-                layer = fieldNameNode.getChild(2).toStringTree(parser);
-//			} else if (fieldNameNode.getChildCount() == 5) {
-//				// layer and value are indicated
-//				foundry = fieldNameNode.getChild(0).toStringTree(poliqarpParser);
-//				layer = fieldNameNode.getChild(2).toStringTree(poliqarpParser);
-//				value = fieldNameNode.getChild(4).toStringTree(poliqarpParser);
-            }
-            if (hasChild(node, "key")) {
-                ParseTree keyNode = getFirstChildWithCat(node, "key");
-                key = keyNode.getChild(0).toStringTree(parser);
-            }
+		objectsToPop.push(stackedObjects);
 
-            String relation = node.getChild(1).getChild(0).toStringTree(parser);
-            if (negField) {
-                if (relation.startsWith("!")) {
-                    relation = relation.substring(1);
-                } else {
-                    relation = "!" + relation;
-                }
-            }
-            if (relation.equals("=")) {
-                relation = "eq";
-            } else if (relation.equals("!=")) {
-                relation = "ne";
-            }
-
-            ParseTree valNode;
-            if (hasChild(node, "key")) valNode = node.getChild(3);
-            else valNode = node.getChild(2);
-            String valType = getNodeCat(valNode);
-            if (valType.equals("simple_query")) {
-                value = valNode.getChild(0).getChild(0).toStringTree(parser);   //e.g. (simple_query (sq_segment foo))
-            } else if (valType.equals("re_query")) {
-                value = valNode.getChild(0).toStringTree(parser);                //e.g. (re_query "bar*")
-                fieldMap.put("type", "type:regex");
-                value = value.substring(1, value.length() - 1); //remove trailing quotes
-            }
-            if (key == null) {
-                fieldMap.put("key", value);
-            } else {
-                fieldMap.put("key", key);
-                fieldMap.put("value", value);
-            }
-
-            if (layer.equals("base")) layer = "lemma";
-
-
-            fieldMap.put("layer", layer);
-            if (foundry != null) fieldMap.put("foundry", foundry);
-
-            fieldMap.put("match", "match:" + relation);
-
-        	
-            if (hasChild(valNode.getChild(0), "flag")) {
-            	ParseTree flagNode = getFirstChildWithCat(valNode.getChild(0), "flag").getChild(0);
-            	String flag = getNodeCat(flagNode).substring(1); //substring removes leading slash '/'
-                // add to current token's value
-                if (flag.contains("i")) fieldMap.put("caseInsensitive", true);
-                else if (flag.contains("I")) fieldMap.put("caseInsensitive", false);
-                else fieldMap.put("flag", flag);
-            }
-            // Step II: decide where to put the field map (as the only value of a token or the meta filter or as a part of a group in case of coordinated fields)
-            if (fieldStack.isEmpty()) {
-                if (!inMeta) {
-                    tokenStack.getFirst().put("wrap", fieldMap);
-                } else {
-                    ((HashMap<String, Object>) requestMap.get("meta")).put("key", fieldMap);
-                }
-            } else {
-                fieldStack.getFirst().add(fieldMap);
-            }
-            visited.add(node.getChild(0));
-            visited.add(node.getChild(1));
-            visited.add(node.getChild(2));
-            if (key != null) visited.add(node.getChild(3));
-        }
-
-        if (nodeCat.equals("neg_field") || nodeCat.equals("neg_field_group")) {
-            negField = !negField;
-        }
-
-        // conj_field serves for both conjunctions and disjunctions
-        if (nodeCat.equals("conj_field")) {
-            // Step I: get operator (& or |)
-            ParseTree operatorNode = node.getChild(1).getChild(0);
-            String operator = getNodeCat(operatorNode);
-            String relation = operator.equals("&") ? "and" : "or";
-            if (negField) {
-                relation = relation.equals("or") ? "and" : "or";
-            }
-            LinkedHashMap<String, Object> group = makeTermGroup(relation);
-            ArrayList<Object> groupOperands = (ArrayList<Object>) group.get("operands");
-            fieldStack.push(groupOperands);
-            stackedFields++;
-            // Step II: decide where to put the group (directly under token or in top meta filter section or embed in super group)
-            if (openNodeCats.get(1).equals("cq_segment")) {
-                tokenStack.getFirst().put("wrap", group);
-            } else if (openNodeCats.get(1).equals("meta_field_group")) {
-                ((HashMap<String, Object>) requestMap.get("meta")).put("key", group);
-            } else if (openNodeCats.get(2).equals("conj_field")) {
-                fieldStack.get(1).add(group);
-            } else {
-                tokenStack.getFirst().put("wrap", group);
-            }
-            // skip the operator
-            visited.add(node.getChild(1));
-        }
-
-
-        if (nodeCat.equals("sq_segment")) {
-            // Step I: determine whether to create new token or get token from the stack (if added by cq_segments)
-            LinkedHashMap<String, Object> token;
-            if (tokenStack.isEmpty()) {
-                token = new LinkedHashMap<String, Object>();
-                tokenStack.push(token);
-                stackedTokens++;
-            } else {
-                // in case sq_segments has already added the token
-                token = tokenStack.getFirst();
-            }
-            curToken = token;
-            objectStack.push(token);
-            stackedObjects++;
-            // Step II: fill object (token values) and put into containing sequence
-            if (node.getText().equals("[]")) {
-
-            } else {
-                token.put("@type", "korap:token");
-                String word = node.getChild(0).toStringTree(parser);
-                LinkedHashMap<String, Object> tokenValues = new LinkedHashMap<String, Object>();
-                token.put("wrap", tokenValues);
-                tokenValues.put("@type", "korap:term");
-                tokenValues.put("key", word);
-                tokenValues.put("layer", "orth");
-                tokenValues.put("match", "match:eq");
-                // add token to sequence only if it is not an only child (in that case, sq_segments has already added the info and is just waiting for the values from "field")
-                if (node.getParent().getChildCount() > 1) {
-                    ArrayList<Object> topSequenceOperands = (ArrayList<Object>) objectStack.get(1).get("operands");
-                    topSequenceOperands.add(token);
-                }
-            }
-            visited.add(node.getChild(0));
-        }
-
-        if (nodeCat.equals("re_query")) {
-            LinkedHashMap<String, Object> reQuery = new LinkedHashMap<String, Object>();
-            // if in field, regex was already added there
-            if (!openNodeCats.get(1).equals("field")) {
-                LinkedHashMap<String, Object> token = new LinkedHashMap<String, Object>();
-                token.put("@type", "korap:token");
-                token.put("wrap", reQuery);
-                reQuery.put("@type", "korap:term");
-                String key = node.getChild(0).toStringTree(parser);
-                key = key.substring(1, key.length()-1);
-                reQuery.put("key", key);
-                reQuery.put("layer", "orth");
-                reQuery.put("type", "type:regex");
-                reQuery.put("match", "match:eq");
-                putIntoSuperObject(token);
-            }
-        }
-
-        if (nodeCat.equals("alignment")) {
-            LinkedHashMap<String, Object> alignGroup = new LinkedHashMap<String, Object>();
-            alignGroup.put("@type", "korap:group");
-            alignGroup.put("align", "left");
-            alignGroup.put("operands", new ArrayList<Object>());
-            putIntoSuperObject(alignGroup);
-            objectStack.push(alignGroup);
-            stackedObjects++;
-            visited.add(node.getChild(0));
-        }
-
-        if (nodeCat.equals("element")) {
-            // Step I: determine whether to create new token or get token from the stack (if added by cq_segments)
-            LinkedHashMap<String, Object> span = makeSpan();
-            if (!tokenStack.isEmpty()) {
-                // in case sq_segments has already added the token
-                span = tokenStack.getFirst();
-            }
-            curToken = span;
-            // Step II: fill object (token values) and put into containing sequence
-            span.put("@type", "korap:span");
-            int valChildIdx = node.getChildCount() - 2; // closing '>' is last child
-            String value = node.getChild(valChildIdx).toStringTree(parser);
-            ParseTree foundryNode = getFirstChildWithCat(node, "foundry");
-            ParseTree layerNode = getFirstChildWithCat(node, "layer");
-            if (foundryNode != null) {
-                span.put("foundry", foundryNode.getChild(0).toStringTree(parser));
-            }
-            if (layerNode != null) {
-                span.put("layer", layerNode.getChild(0).toStringTree(parser));
-            }
-            span.put("key", value);
-            // add token to sequence only if it is not an only child (in that case, cq_segments has already added the info and is just waiting for the values from "field")
-            objectStack.push(span);
-            stackedObjects++;
-            if (node.getParent().getChildCount() > 1) {
-                ArrayList<Object> topSequenceOperands = (ArrayList<Object>) objectStack.get(1).get("operands");
-                topSequenceOperands.add(span);
-            }
-            visited.add(node.getChild(0));
-            visited.add(node.getChild(1));
-            visited.add(node.getChild(2));
-        }
-
-        if (nodeCat.equals("spanclass")) {
-            // Step I: get info
-            int classId = 0;
-            if (getNodeCat(node.getChild(1)).equals("spanclass_id")) {
-                String ref = node.getChild(1).getChild(0).toStringTree(parser);
-                try {
-                    classId = Integer.parseInt(ref);
-                } catch (NumberFormatException e) {
-                	log.error("The specified class reference in the focus/split-Operator is not a number: " + ref);
-                    throw new QueryException("The specified class reference in the focus/split-Operator is not a number: " + ref);
-                }
-                // only allow class id up to 255
-                if (classId > 255) {
-                    classId = 0;
-                }
-            }
-            LinkedHashMap<String, Object> classGroup = makeClass(classId);
-            putIntoSuperObject(classGroup);
-            objectStack.push(classGroup);
-            stackedObjects++;
-        }
-
-        if (nodeCat.equals("position")) {
-        	String frame = getNodeCat(node.getChild(0)).toLowerCase();
-            LinkedHashMap<String, Object> positionGroup = makePosition(frame);
-            putIntoSuperObject(positionGroup);
-            objectStack.push(positionGroup);
-            stackedObjects++;
-        }
-
-        if (nodeCat.equals("focus")) {
-            // Step I: get info
-            ArrayList<Integer> classRefs = new ArrayList<Integer>();
-            String classRefOp = null;
-            if (getNodeCat(node.getChild(2)).equals("spanclass_id")) {
-                ParseTree spanNode = node.getChild(2);
-                for (int i = 0; i < spanNode.getChildCount() - 1; i++) {
-                    String ref = spanNode.getChild(i).getText();
-                    if (ref.equals("|") || ref.equals("&")) {
-                        classRefOp = ref.equals("|") ? "intersection" : "union";
-                    } else {
-                        try {
-                            int classRef = Integer.parseInt(ref);
-                            classRefs.add(classRef);
-                        } catch (NumberFormatException e) {
-                            throw new QueryException("The specified class reference in the shrink/split-Operator is not a number.");
-                        }
-                    }
-                }
-            } else {
-                classRefs.add(0);
-            }
-            LinkedHashMap<String, Object> referenceGroup = makeReference(classRefs);
-            
-            String type = node.getChild(0).toStringTree(parser);
-            if (type.equals("split")) referenceGroup.put("operation", "operation:split");
-            if (classRefOp != null) {
-                referenceGroup.put("classRefOp", "classRefOp:" + classRefOp);
-            }
-            ArrayList<Object> referenceOperands = new ArrayList<Object>();
-            referenceGroup.put("operands", referenceOperands);
-            // Step II: decide where to put the group
-            putIntoSuperObject(referenceGroup);
-            objectStack.push(referenceGroup);
-            stackedObjects++;
-            visited.add(node.getChild(0));
-        }
-
-        // repetition of token group
-        if (nodeCat.equals("occ")) {
-            ParseTree occChild = node.getChild(0);
-            String repetition = occChild.toStringTree(parser);
-            int[] minmax = parseRepetition(repetition);
-            curOccGroup.put("operation", "operation:" + "repetition");
-            curOccGroup.put("min", minmax[0]);
-            curOccGroup.put("max", minmax[1]);
-            visited.add(occChild);
-        }
-
-        // flags for case sensitivity and whole-word-matching
-        if (nodeCat.equals("flag")) {
-            String flag = getNodeCat(node.getChild(0)).substring(1); //substring removes leading slash '/'
-            // add to current token's value
-            if (flag.contains("i")) ((HashMap<String, Object>) curToken.get("wrap")).put("caseInsensitive", true);
-            else if (flag.contains("I")) ((HashMap<String, Object>) curToken.get("wrap")).put("caseInsensitive", false);
-            else ((HashMap<String, Object>) curToken.get("wrap")).put("flag", flag);
-        }
-
-        if (nodeCat.equals("meta")) {
-            inMeta = true;
-            LinkedHashMap<String, Object> metaFilter = new LinkedHashMap<String, Object>();
-            requestMap.put("meta", metaFilter);
-            metaFilter.put("@type", "korap:meta");
-        }
-
-        if (nodeCat.equals("within") && !getNodeCat(node.getParent()).equals("position")) {
-            ParseTree domainNode = node.getChild(2);
-            String domain = getNodeCat(domainNode);
-            LinkedHashMap<String, Object> curObject = (LinkedHashMap<String, Object>) objectStack.getFirst();
-            curObject.put("within", domain);
-            visited.add(node.getChild(0));
-            visited.add(node.getChild(1));
-            visited.add(domainNode);
-        }
-
-        objectsToPop.push(stackedObjects);
-        tokensToPop.push(stackedTokens);
-        fieldsToPop.push(stackedFields);
-		
 		/*
 		 ****************************************************************
 		 **************************************************************** 
@@ -723,202 +337,207 @@
 		 ****************************************************************
 		 ****************************************************************
 		 */
-        for (int i = 0; i < node.getChildCount(); i++) {
-            ParseTree child = node.getChild(i);
-            curChildIndex = i;
-            processNode(child);
-        }
+		for (int i = 0; i < node.getChildCount(); i++) {
+			ParseTree child = node.getChild(i);
+			processNode(child);
+		}
 
-        // set negField back
-        if (nodeCat.equals("neg_field") || nodeCat.equals("neg_field_group")) {
-            negField = !negField;
-        }
+		// set negField back
+		if (nodeCat.equals("neg_field") || nodeCat.equals("neg_field_group")) {
+			negField = !negField;
+		}
 
-        // Stuff that happens when leaving a node (taking items off the stacks)
-        for (int i = 0; i < objectsToPop.get(0); i++) {
-            objectStack.pop();
-        }
-        objectsToPop.pop();
-        for (int i = 0; i < tokensToPop.get(0); i++) {
-            tokenStack.pop();
-        }
-        tokensToPop.pop();
-        for (int i = 0; i < fieldsToPop.get(0); i++) {
-            fieldStack.pop();
-        }
-        fieldsToPop.pop();
-        openNodeCats.pop();
-    }
+		// Stuff that happens when leaving a node (taking items off the stacks)
+		for (int i = 0; i < objectsToPop.get(0); i++) {
+			objectStack.pop();
+		}
+		objectsToPop.pop();
 
-    private void putIntoSuperObject(LinkedHashMap<String, Object> object) {
+		openNodeCats.pop();
+	}
+
+	private int[] parseRepetition(ParseTree node) {
+		int min = 0, max = 0;
+		ParseTree minNode = getFirstChildWithCat(node, "min");
+		ParseTree maxNode = getFirstChildWithCat(node, "max");
+		ParseTree kleeneNode = getFirstChildWithCat(node, "kleene");
+		if (kleeneNode != null) {
+			String kleeneOp = kleeneNode.getText();
+			if (kleeneOp.equals("*")) {
+				max = MAXIMUM_DISTANCE;
+			} else if (kleeneOp.equals("+")) {
+				min = 1;
+				max = MAXIMUM_DISTANCE;
+			} if (kleeneOp.equals("?")) {
+				max = 1;
+			}
+		} else {
+			max = Integer.parseInt(maxNode.getText());
+			if (minNode!=null) min = Integer.parseInt(minNode.getText());
+			else min = max;
+		}
+		return new int[]{min,max};
+	}
+
+	private String parseFrame(ParseTree node) {
+		return node.toStringTree(parser);
+	}
+
+	@SuppressWarnings("unchecked")
+	private LinkedHashMap<String, Object> parseTermOrTermGroup(ParseTree node, boolean negatedGlobal) {
+		if (getNodeCat(node).equals("term")) {
+			String regex = null;
+			LinkedHashMap<String,Object> term = makeTerm();
+			boolean negated = negatedGlobal;
+			List<ParseTree> negations = getChildrenWithCat(node, "!");
+			if (negations.size() % 2 == 1) negated = !negated;
+			ParseTree keyNode = getFirstChildWithCat(node, "key");
+			ParseTree layerNode = getFirstChildWithCat(node, "layer");
+			ParseTree foundryNode = getFirstChildWithCat(node, "foundry");
+			ParseTree termOpNode = getFirstChildWithCat(node, "termOp");
+			ParseTree flagNode = getFirstChildWithCat(node, "flag");
+			if (foundryNode != null) term.put("foundry", foundryNode.getText());
+			if (layerNode != null) {
+				String layer = layerNode.getText();
+				if (layer.equals("base")) layer="lemma";
+				term.put("layer", layer);
+			}
+			if (getNodeCat(keyNode.getChild(0)).equals("regex")) {
+				term.put("type", "type:regex");
+				regex = keyNode.getText();
+				regex = regex.substring(1, regex.length()-1);
+				term.put("key", regex);
+			} else {
+				term.put("key", keyNode.getText());
+			}
+			if (termOpNode != null) {
+				String termOp = termOpNode.getText();
+				negated = termOp.equals("=") ? negated : !negated; 
+				if (!negated) term.put("match", "match:eq");
+				else term.put("match", "match:ne");
+			}
+			if (flagNode != null) {
+				String flag = getNodeCat(flagNode.getChild(0)).substring(1); //substring removes leading slash '/'
+				System.err.println(flag);
+				if (flag.contains("i")) term.put("caseInsensitive", true);
+				else if (flag.contains("I")) term.put("caseInsensitive", false);
+				if (flag.contains("x")) {
+					term.put("key", ".*?"+regex+".*?");
+				}
+			}
+			return term;
+		} else {
+			LinkedHashMap<String,Object> termGroup = null;
+			ParseTree leftOp = null;
+			ParseTree rightOp = null;
+			if (!getNodeCat(node.getChild(0)).equals("(")) leftOp = node.getChild(0);
+			else leftOp = node.getChild(1);
+			if (!getNodeCat(node.getChild(node.getChildCount()-1)).equals(")")) rightOp = node.getChild(node.getChildCount()-1);
+			else rightOp = node.getChild(node.getChildCount()-2);
+
+			ParseTree boolOp = getFirstChildWithCat(node, "booleanOp"); 
+			String operator = boolOp.getText().equals("&") ? "and" : "or";
+			termGroup = makeTermGroup(operator);
+			ArrayList<Object> operands = (ArrayList<Object>) termGroup.get("operands");
+			operands.add(parseTermOrTermGroup(leftOp, negatedGlobal));
+			operands.add(parseTermOrTermGroup(rightOp, negatedGlobal));
+			return termGroup;
+		}
+	}
+
+	private void putIntoSuperObject(LinkedHashMap<String, Object> object) {
 		putIntoSuperObject(object, 0);
 	}
-	
+
 	@SuppressWarnings({ "unchecked" })
 	private void putIntoSuperObject(LinkedHashMap<String, Object> object, int objStackPosition) {
-		if (currentNode.getParent().getChildCount() > 1) {
+		if (objectStack.size()>objStackPosition) {
 			ArrayList<Object> topObjectOperands = (ArrayList<Object>) objectStack.get(objStackPosition).get("operands");
 			topObjectOperands.add(object);
-		} else if (openNodeCats.get(2).equals("query")) {
-			requestMap.put("query", object);
-		} else if (openNodeCats.get(0).equals("re_query") && openNodeCats.get(1).equals("query")) {
-			requestMap.put("query", object);
 		} else {
-			ArrayList<Object> topObjectOperands = (ArrayList<Object>) objectStack.get(objStackPosition).get("operands");
-			topObjectOperands.add(object);
+			requestMap.put("query", object);
 		}
 	}
 
-	private int[] parseRepetition(String repetition) {
-		if (repetition.equals("*")) {
-			return new int[] {0, MAXIMUM_DISTANCE};
-		} else if (repetition.equals("+")) {
-			return new int[] {1, MAXIMUM_DISTANCE};
-		} else if (repetition.equals("?")) {
-			return new int[] {0, 1};
-		} else {
-			repetition = repetition.substring(1, repetition.length()-1); // remove braces
-			String[] splitted = repetition.split(",");
-			if (splitted.length==2) {
-				return new int[] {Integer.parseInt(splitted[0]), Integer.parseInt(splitted[1])};
-			} else {
-				return new int[] {Integer.parseInt(splitted[0]), Integer.parseInt(splitted[0])};
+	private int[] parseEmptySegments(ParseTree emptySegments) {
+		Integer min = 1;
+		Integer max = 1;
+		ParseTree child;
+		for (int i = 0; i < emptySegments.getChildCount(); i++) {
+			child = emptySegments.getChild(i);
+			ParseTree nextSibling = emptySegments.getChild(i + 1);
+			if (child.toStringTree(parser).equals("(emptyToken [ ])")) {
+				if (nextSibling != null && getNodeCat(nextSibling).equals("repetition")) {
+					int[] minmax = parseRepetition(nextSibling);
+					min += minmax[0];
+					max += minmax[1];
+				} else {
+					min++;
+					max++;
+				}
 			}
-			
 		}
+		if (max > MAXIMUM_DISTANCE) max = MAXIMUM_DISTANCE;
+		return new int[]{min, max};
 	}
 
-    private String[] parseEmptySegments(ParseTree emptySegments) {
-        String[] minmax = new String[2];
-        Integer min = 1;
-        Integer max = 1;
-        boolean infinite = false;
-        ParseTree child;
-        for (int i = 0; i < emptySegments.getChildCount() - 1; i++) {
-            child = emptySegments.getChild(i);
-            ParseTree nextSibling = emptySegments.getChild(i + 1);
-            String nextSiblingString = nextSibling.toStringTree();
-            if (child.toStringTree().equals("[]")) {
-                if (nextSiblingString.equals("?")) {
-                    max++;
-                } else if (nextSiblingString.equals("+")) {
-                	min++;
-                	infinite = true;
-                } else if (nextSiblingString.equals("*")) {
-                	infinite = true;
-                }
-                else if (nextSiblingString.startsWith("{")) {
-                    String occ = nextSiblingString.substring(1, nextSiblingString.length() - 1);
-                    System.out.println(occ);
-                    if (occ.contains(",")) {
-                        String[] minmaxOcc = occ.split(",");
-                        min += Integer.parseInt(minmaxOcc[0]);
-                        max += Integer.parseInt(minmaxOcc[1]);
-                    } else {
-                        min += Integer.parseInt(occ);
-                        max += Integer.parseInt(occ);
-                    }
-                } else {
-                    min++;
-                    max++;
-                }
-            }
-        }
-        child = emptySegments.getChild(emptySegments.getChildCount() - 1);
-        if (child.toStringTree().equals("[]")) {
-            min++;
-            max++;
-        }
-        if (infinite) max = MAXIMUM_DISTANCE;
-        minmax[0] = min.toString();
-        minmax[1] = max.toString();
-        return minmax;
-    }
+	private ParserRuleContext parsePoliqarpQuery(String p) throws QueryException {
+		checkUnbalancedPars(p);
 
-    @SuppressWarnings("unchecked")
-    private void createOccGroup(ParseTree node) {
-        LinkedHashMap<String, Object> occGroup = new LinkedHashMap<String, Object>();
-        occGroup.put("@type", "korap:group");
-        ArrayList<Object> groupOperands = new ArrayList<Object>();
-        occGroup.put("operands", groupOperands);
-        curOccGroup = occGroup;
-        objectStack.push(occGroup);
-        stackedObjects++;
-        // if only this group is on the object stack, add as top query element
-        if (objectStack.size() == 1) {
-            requestMap.put("query", occGroup);
-            // embed in super sequence
-        } else {
-            ArrayList<Object> topSequenceOperands = (ArrayList<Object>) objectStack.get(1).get("operands");
-            topSequenceOperands.add(occGroup);
-        }
-    }
+		Lexer poliqarpLexer = new PoliqarpPlusLexer((CharStream) null);
+		ParserRuleContext tree = null;
 
+		// Like p. 111
+		try {
 
-    private ParserRuleContext parsePoliqarpQuery(String p) throws QueryException {
-        checkUnbalancedPars(p);
+			// Tokenize input data
+			ANTLRInputStream input = new ANTLRInputStream(p);
+			poliqarpLexer.setInputStream(input);
+			CommonTokenStream tokens = new CommonTokenStream(poliqarpLexer);
+			parser = new PoliqarpPlusParser(tokens);
 
-        Lexer poliqarpLexer = new PoliqarpPlusLexer((CharStream) null);
-        ParserRuleContext tree = null;
-        // Like p. 111
-        try {
+			// Don't throw out erroneous stuff
+			parser.setErrorHandler(new BailErrorStrategy());
+			parser.removeErrorListeners();
 
-            // Tokenize input data
-            ANTLRInputStream input = new ANTLRInputStream(p);
-            poliqarpLexer.setInputStream(input);
-            CommonTokenStream tokens = new CommonTokenStream(poliqarpLexer);
-            parser = new PoliqarpPlusParser(tokens);
+			// Get starting rule from parser
+			Method startRule = PoliqarpPlusParser.class.getMethod("request");
+			tree = (ParserRuleContext) startRule.invoke(parser, (Object[]) null);
+			log.debug(tree.toStringTree(parser));
+		}
+		// Some things went wrong ...
+		catch (Exception e) {
+			log.error("Could not parse query. Please make sure it is well-formed.");;
+			log.error("Underlying error is: "+e.getMessage());
+			System.err.println(e.getMessage());
+		}
 
-            // Don't throw out erroneous stuff
-            parser.setErrorHandler(new BailErrorStrategy());
-            parser.removeErrorListeners();
+		if (tree == null) {
+			throw new QueryException("The query you specified could not be processed. Please make sure it is well-formed.");
+		}
+		// Return the generated tree
+		return tree;
+	}
 
-            // Get starting rule from parser
-            Method startRule = PoliqarpPlusParser.class.getMethod("request");
-            tree = (ParserRuleContext) startRule.invoke(parser, (Object[]) null);
-            log.debug(tree.toStringTree(parser));
-        }
-
-        // Some things went wrong ...
-        catch (Exception e) {
-        	log.error("Could not parse query. Please make sure it is well-formed.");;
-            log.error("Underlying error is: "+e.getStackTrace());
-        	System.err.println(e.getMessage());
-        }
-
-        if (tree == null) {
-        	log.error("Could not parse query. Please make sure it is well-formed.");
-        	throw new QueryException("The query you specified could not be processed. Please make sure it is well-formed.");
-        }
-        // Return the generated tree
-        return tree;
-    }
-
-    public static void main(String[] args) {
+	public static void main(String[] args) {
 		/*
 		 * For testing
 		 */
-        String[] queries = new String[]{
-//        		"matches(<np>,[base=Berlin][][base=Tegel])",
-        		"[base=\"foo\"][]",
-//        		"[][base=Foo]",
-        		"[base=der][]{2,5}[base=Mann][]?[][base=Frau]",
-        };
-		PoliqarpPlusTree.verbose=true;
-        for (String q : queries) {
-            try {
-                System.out.println(q);
-//				System.out.println(PoliqarpPlusTree.parsePoliqarpQuery(q).toStringTree(PoliqarpPlusTree.parser));
-                @SuppressWarnings("unused")
-                PoliqarpPlusTree pt = new PoliqarpPlusTree(q);
-                System.out.println(pt.parsePoliqarpQuery(q).toStringTree(pt.parser));
-                System.out.println(q);
-                System.out.println();
+		String[] queries = new String[]{
+				"[base=foo][base=foo]"
+		};
+//		PoliqarpPlusTree.verbose=true;
+		for (String q : queries) {
+			try {
+				System.out.println(q);
+				@SuppressWarnings("unused")
+				PoliqarpPlusTree pt = new PoliqarpPlusTree(q);
+				System.out.println();
 
-            } catch (Exception npe) {
-                npe.printStackTrace();
-                System.out.println("null\n");
-            }
-        }
-    }
+			} catch (Exception npe) {
+				npe.printStackTrace();
+				System.out.println("null\n");
+			}
+		}
+	}
 }
diff --git a/src/test/java/PoliqarpPlusTreeTest.java b/src/test/java/PoliqarpPlusTreeTest.java
index 430b271..7e2afc1 100644
--- a/src/test/java/PoliqarpPlusTreeTest.java
+++ b/src/test/java/PoliqarpPlusTreeTest.java
@@ -27,37 +27,57 @@
 	
 	@Test
 	public void testSingleTokens() throws QueryException {
+		String query;
 		// [base=Mann]
-		String token1 = "{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}";
+		String token1 = "{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}";
 		assertTrue(equalsQueryContent(token1, "[base=Mann]"));
 		
 		// [orth!=Frau]
-		String token2 = "{@type=korap:token, wrap={@type=korap:term, key=Frau, layer=orth, match=match:ne}}";
+		String token2 = "{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Frau, match=match:ne}}";
 		assertTrue(equalsQueryContent(token2, "[orth!=Frau]"));
 		
 		// [!p=NN]
-		String token3 = "{@type=korap:token, wrap={@type=korap:term, key=NN, layer=p, match=match:ne}}";
-		assertTrue(equalsQueryContent(token3, "[!p=NN]"));
+		query = "[!p=NN]";
+		String token3 = "{@type=korap:token, wrap={@type=korap:term, layer=p, key=NN, match=match:ne}}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(token3.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
 		// [!p!=NN]
-		String token4 = "{@type=korap:token, wrap={@type=korap:term, key=NN, layer=p, match=match:eq}}";
-		assertTrue(equalsQueryContent(token4, "[!p!=NN]"));
+		query = "[!p!=NN]";
+		String token4 = "{@type=korap:token, wrap={@type=korap:term, layer=p, key=NN, match=match:eq}}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(token4.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
 	}
 	
 	@Test
 	public void testRegex() throws QueryException {
 		String query = "[orth=\"M(a|ä)nn(er)?\"]";
-		String re1 = "{@type=korap:token, wrap={@type=korap:term, type=type:regex, key=M(a|ä)nn(er)?, layer=orth, match=match:eq}}";
+		String re1 = "{@type=korap:token, wrap={@type=korap:term, layer=orth, type=type:regex, key=M(a|ä)nn(er)?, match=match:eq}}";
 		ppt = new PoliqarpPlusTree(query);
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(re1.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
+		query = "[orth=\"M(a|ä)nn(er)?\"/x]";
+		String re2 = "{@type=korap:token, wrap={@type=korap:term, layer=orth, type=type:regex, key=.*?M(a|ä)nn(er)?.*?, match=match:eq}}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(re2.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
+		query = "\"M(a|ä)nn(er)?\"/x";
+		String re3 = "{@type=korap:token, wrap={@type=korap:term, type=type:regex, layer=orth, key=.*?M(a|ä)nn(er)?.*?, match=match:eq}}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(re3.replaceAll(" ", ""), map.replaceAll(" ", ""));
 	}
 	
 	@Test
 	public void testCaseSensitivityFlag() throws QueryException {
 		String query="[orth=deutscher/i]";
 		String cs1 = 
-				"{@type=korap:token, wrap={@type=korap:term, key=deutscher, layer=orth, match=match:eq, caseInsensitive=true}}";
+				"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=deutscher, match=match:eq, caseInsensitive=true}}";
 		ppt = new PoliqarpPlusTree(query);
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(cs1.replaceAll(" ", ""), map.replaceAll(" ", ""));
@@ -65,8 +85,8 @@
 		query="[orth=deutscher/i][orth=Bundestag]";
 		String cs2 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=deutscher, layer=orth, match=match:eq, caseInsensitive=true}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=Bundestag, layer=orth, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=deutscher, match=match:eq, caseInsensitive=true}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Bundestag, match=match:eq}}" +
 					"]}";
 		ppt = new PoliqarpPlusTree(query);
 		map = ppt.getRequestMap().get("query").toString();
@@ -74,7 +94,7 @@
 		
 		query="deutscher/i";
 		String cs3 = 
-				"{@type=korap:token, wrap={@type=korap:term, key=deutscher, layer=orth, match=match:eq, caseInsensitive=true}}";
+				"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=deutscher, match=match:eq, caseInsensitive=true}}";
 		ppt = new PoliqarpPlusTree(query);
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(cs3.replaceAll(" ", ""), map.replaceAll(" ", ""));
@@ -82,8 +102,8 @@
 		query="deutscher/i Bundestag";
 		String cs4 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=deutscher, layer=orth, match=match:eq, caseInsensitive=true}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=Bundestag, layer=orth, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=deutscher, match=match:eq, caseInsensitive=true}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Bundestag, match=match:eq}}" +
 					"]}";
 		ppt = new PoliqarpPlusTree(query);
 		map = ppt.getRequestMap().get("query").toString();
@@ -92,8 +112,8 @@
 		query="deutscher Bundestag/i";
 		String cs5 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=deutscher, layer=orth, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=Bundestag, layer=orth, match=match:eq, caseInsensitive=true}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=deutscher, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Bundestag, match=match:eq, caseInsensitive=true}}" +
 					"]}";
 		ppt = new PoliqarpPlusTree(query);
 		map = ppt.getRequestMap().get("query").toString();
@@ -130,12 +150,12 @@
 	public void testEmptyTokens() throws QueryException {
 		// [base=der][][base=Mann]
 		String et1 = 
-			"{@type=korap:group, operation=operation:sequence, inOrder=true, distances=[" +
-				"{@type=korap:distance, key=w, min=2, max=2}" +
-			"], " +
+			"{@type=korap:group, operation=operation:sequence, " +
 			"operands=[" +
-				"{@type=korap:token, wrap={@type=korap:term, key=der, layer=lemma, match=match:eq}}," +
-				"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}" +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=der, match=match:eq}}," +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}" +
+			"], inOrder=true, distances=[" +
+				"{@type=korap:distance, key=w, min=2, max=2}" +
 			"]}";
 		ppt = new PoliqarpPlusTree("[base=der][][base=Mann]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -143,12 +163,12 @@
 		
 		// [base=der][][][base=Mann]
 		String et2 = 
-			"{@type=korap:group, operation=operation:sequence, inOrder=true, distances=[" +
-				"{@type=korap:distance, key=w, min=3, max=3}" +
-			"], " +
+			"{@type=korap:group, operation=operation:sequence, " +
 			"operands=[" +
-				"{@type=korap:token, wrap={@type=korap:term, key=der, layer=lemma, match=match:eq}}," +
-				"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}" +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=der, match=match:eq}}," +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}" +
+			"], inOrder=true, distances=[" +
+				"{@type=korap:distance, key=w, min=3, max=3}" +
 			"]}";
 		ppt = new PoliqarpPlusTree("[base=der][][][base=Mann]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -156,12 +176,12 @@
 		
 		// [base=der][][]?[base=Mann]
 		String et3 = 
-			"{@type=korap:group, operation=operation:sequence, inOrder=true, distances=[" +
-				"{@type=korap:distance, key=w, min=2, max=3}" +
-			"], " +
+			"{@type=korap:group, operation=operation:sequence, " +
 			"operands=[" +
-				"{@type=korap:token, wrap={@type=korap:term, key=der, layer=lemma, match=match:eq}}," +
-				"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}" +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=der, match=match:eq}}," +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}" +
+			"], inOrder=true, distances=[" +
+				"{@type=korap:distance, key=w, min=2, max=3}" +
 			"]}";
 		ppt = new PoliqarpPlusTree("[base=der][][]?[base=Mann]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -173,7 +193,7 @@
 			"{@type=korap:group, operation=operation:position, frame=frame:startswith, operands=[" +	
 				"{@type=korap:span, key=s}," +
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}" +
+					"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}" +
 				"], offset-min=1, offset-max=1}" +
 			"]}";
 		ppt = new PoliqarpPlusTree("startswith(<s>, [][base=Mann])");
@@ -182,18 +202,18 @@
 		
 		// [base=der][]{2,5}[base=Mann][]?[][base=Frau]   nested distances=
 		String et5 = 
-				"{@type=korap:group, operation=operation:sequence, inOrder=true, distances=[" +
-					"{@type=korap:distance, key=w, min=3, max=6}" +
-				"], " +
+				"{@type=korap:group, operation=operation:sequence," +
 				"operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=der, layer=lemma, match=match:eq}}," +
-					"{@type=korap:group, operation=operation:sequence, inOrder=true, distances=[" +
-						"{@type=korap:distance, key=w, min=2, max=3}" +
-					"], " +
+					"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=der, match=match:eq}}," +
+					"{@type=korap:group, operation=operation:sequence, " +
 					"operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=Frau, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Frau, match=match:eq}}" +
+					"], inOrder=true, distances=[" +
+						"{@type=korap:distance, key=w, min=2, max=3}" +
 					"]}" +
+				"], inOrder=true, distances=[" +
+					"{@type=korap:distance, key=w, min=3, max=6}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("[base=der][]{2,5}[base=Mann][]?[][base=Frau]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -201,25 +221,25 @@
 		
 		// [base=der][]*[base=Mann]
 		String et6 = 
-			"{@type=korap:group, operation=operation:sequence, inOrder=true, distances=[" +
-				"{@type=korap:distance, key=w, min=1, max=100}" +
-			"], " +
+			"{@type=korap:group, operation=operation:sequence, " +
 			"operands=[" +
-				"{@type=korap:token, wrap={@type=korap:term, key=der, layer=lemma, match=match:eq}}," +
-				"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}" +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=der, match=match:eq}}," +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}" +
+			"], inOrder=true, distances=[" +
+				"{@type=korap:distance, key=w, min=1, max=100}" +
 			"]}";
 		ppt = new PoliqarpPlusTree("[base=der][]*[base=Mann]");
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(et6.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
-		// [base=der][]*[base=Mann]
+		// [base=der][]+[base=Mann]
 		String et7 = 
-			"{@type=korap:group, operation=operation:sequence, inOrder=true, distances=[" +
-				"{@type=korap:distance, key=w, min=2, max=100}" +
-			"], " +
+			"{@type=korap:group, operation=operation:sequence, " +
 			"operands=[" +
-				"{@type=korap:token, wrap={@type=korap:term, key=der, layer=lemma, match=match:eq}}," +
-				"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}" +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=der, match=match:eq}}," +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}" +
+			"], inOrder=true, distances=[" +
+				"{@type=korap:distance, key=w, min=2, max=100}" +
 			"]}";
 		ppt = new PoliqarpPlusTree("[base=der][]+[base=Mann]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -232,10 +252,10 @@
 		String cof1 = 
 			"{@type=korap:token, wrap=" +
 				"{@type=korap:termGroup, relation=relation:and, operands=[" +
-					"{@type=korap:term, key=Mann, layer=lemma, match=match:eq}," +
+					"{@type=korap:term, layer=lemma, key=Mann, match=match:eq}," +
 					"{@type=korap:termGroup, relation=relation:or, operands=[" +
-						"{@type=korap:term, key=N, layer=cas, match=match:eq}," +
-						"{@type=korap:term, key=A, layer=cas, match=match:eq}" +
+						"{@type=korap:term, layer=cas, key=N, match=match:eq}," +
+						"{@type=korap:term, layer=cas, key=A, match=match:eq}" +
 					"]}" +
 				"]}" +
 			"}";
@@ -253,9 +273,11 @@
 		String cof2 = 
 			"{@type=korap:token, wrap=" +
 				"{@type=korap:termGroup, relation=relation:and, operands=[" +
-					"{@type=korap:term, key=Mann, layer=lemma, match=match:eq}," +
-					"{@type=korap:term, key=N, layer=cas, match=match:eq}," +
-					"{@type=korap:term, key=m, layer=gen, match=match:eq}" +
+					"{@type=korap:term, layer=lemma, key=Mann, match=match:eq}," +
+					"{@type=korap:termGroup, relation=relation:and, operands=[" +
+						"{@type=korap:term, layer=cas, key=N, match=match:eq}," +
+						"{@type=korap:term, layer=gen, key=m, match=match:eq}" +
+					"]}" +
 				"]}" +
 			"}";
 		ppt = new PoliqarpPlusTree("[base=Mann&cas=N&gen=m]");
@@ -267,7 +289,7 @@
 	public void testOccurrence() throws QueryException {
 		// [base=foo]*
 		String occ1 = "{@type=korap:group, operation=operation:repetition, operands=[" +
-					     "{@type=korap:token, wrap={@type=korap:term, key=foo, layer=lemma, match=match:eq}}" +
+					     "{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=foo, match=match:eq}}" +
 					  "], min=0, max=100}"; 
 		ppt = new PoliqarpPlusTree("[base=foo]*");
 		map = ppt.getRequestMap().get("query").toString();
@@ -277,9 +299,9 @@
 		String occ2 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
 					"{@type=korap:group, operation=operation:repetition, operands=[" +
-					     "{@type=korap:token, wrap={@type=korap:term, key=foo, layer=lemma, match=match:eq}}" +
+					     "{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=foo, match=match:eq}}" +
 					"], min=0, max=100 }," +
-					"{@type=korap:token, wrap={@type=korap:term, key=bar, layer=lemma, match=match:eq}}" +
+					"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=bar, match=match:eq}}" +
 				"]}"; 
 		ppt = new PoliqarpPlusTree("[base=foo]*[base=bar]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -288,9 +310,9 @@
 		// [base=bar][base=foo]*
 		String occ3 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=bar, layer=lemma, match=match:eq}}," +
+					"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=bar, match=match:eq}}," +
 					"{@type=korap:group, operation=operation:repetition, operands=[" +
-					     "{@type=korap:token, wrap={@type=korap:term, key=foo, layer=lemma, match=match:eq}}" +
+					     "{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=foo, match=match:eq}}" +
 					"], min=0, max=100 }" +
 				"]}"; 
 		ppt = new PoliqarpPlusTree("[base=bar][base=foo]*");
@@ -299,12 +321,12 @@
 		
 		// ([base=bar][base=foo])*
 		String occ4 = 
-				"{@type=korap:group, operands=[" +	
+				"{@type=korap:group, operation=operation:repetition, operands=[" +	
 					"{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=bar, layer=lemma, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=foo, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=bar, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=foo, match=match:eq}}" +
 					"]}" +
-				"], operation=operation:repetition, min=0, max=100 }" ;
+				"], min=0, max=100}" ;
 		ppt = new PoliqarpPlusTree("([base=bar][base=foo])*");
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(occ4.replaceAll(" ", ""), map.replaceAll(" ", ""));
@@ -313,12 +335,12 @@
 		String occ5 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
 					"{@type=korap:span, key=s}," +
-					"{@type=korap:group, operands=[" +	
+					"{@type=korap:group, operation=operation:repetition, operands=[" +	
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=bar, layer=lemma, match=match:eq}}," +
-							"{@type=korap:token, wrap={@type=korap:term, key=foo, layer=lemma, match=match:eq}}" +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=bar, match=match:eq}}," +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=foo, match=match:eq}}" +
 						"]}" +
-					"], operation=operation:repetition, min=0, max=100 }" +
+					"], min=0, max=100 }" +
 				"]}" ;
 		ppt = new PoliqarpPlusTree("<s>([base=bar][base=foo])*");
 		map = ppt.getRequestMap().get("query").toString();
@@ -329,12 +351,12 @@
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
 					"{@type=korap:span, key=s}," +
 					"{@type=korap:span, key=np}," +
-					"{@type=korap:group, operands=[" +	
+					"{@type=korap:group, operation=operation:repetition, operands=[" +	
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=bar, layer=lemma, match=match:eq}}," +
-							"{@type=korap:token, wrap={@type=korap:term, key=foo, layer=lemma, match=match:eq}}" +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=bar, match=match:eq}}," +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=foo, match=match:eq}}" +
 						"]}" +
-					"], operation=operation:repetition, min=0, max=100 }" +
+					"], min=0, max=100 }" +
 				"]}" ;
 		ppt = new PoliqarpPlusTree("<s><np>([base=bar][base=foo])*");
 		map = ppt.getRequestMap().get("query").toString();
@@ -347,13 +369,13 @@
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
 					"{@type=korap:span, key=s}," +
 					"{@type=korap:span, key=np}," +
-					"{@type=korap:group, operands=[" +	
+					"{@type=korap:group, operation=operation:repetition, operands=[" +	
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=bar, layer=lemma, match=match:eq}}," +
-							"{@type=korap:token, wrap={@type=korap:term, key=foo, layer=lemma, match=match:eq}}" +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=bar, match=match:eq}}," +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=foo, match=match:eq}}" +
 						"]}" +
-					"], operation=operation:repetition, min=0, max=100 }," +
-					"{@type=korap:token, wrap={@type=korap:term, key=NN, layer=p, match=match:eq}}" +
+					"], min=0, max=100 }," +
+					"{@type=korap:token, wrap={@type=korap:term, layer=p, key=NN, match=match:eq}}" +
 				"]}" ;
 		ppt = new PoliqarpPlusTree("<s><np>([base=bar][base=foo])*[p=NN]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -362,13 +384,13 @@
 		// ([base=bar][base=foo])*[p=NN]
 		String occ8 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:group, operands=[" +	
+					"{@type=korap:group, operation=operation:repetition, operands=[" +	
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=bar, layer=lemma, match=match:eq}}," +
-							"{@type=korap:token, wrap={@type=korap:term, key=foo, layer=lemma, match=match:eq}}" +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=bar, match=match:eq}}," +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=foo, match=match:eq}}" +
 						"]}" +
-					"], operation=operation:repetition, min=0, max=100 }," +
-					"{@type=korap:token, wrap={@type=korap:term, key=NN, layer=p, match=match:eq}}" +
+					"], min=0, max=100 }," +
+					"{@type=korap:token, wrap={@type=korap:term, layer=p, key=NN, match=match:eq}}" +
 				"]}" ;
 		ppt = new PoliqarpPlusTree("([base=bar][base=foo])*[p=NN]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -376,7 +398,7 @@
 		
 		// [base=foo]+
 		String occ9 = "{@type=korap:group, operation=operation:repetition, operands=[" +
-					     "{@type=korap:token, wrap={@type=korap:term, key=foo, layer=lemma, match=match:eq}}" +
+					     "{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=foo, match=match:eq}}" +
 					  "], min=1, max=100}"; 
 		ppt = new PoliqarpPlusTree("[base=foo]+");
 		map = ppt.getRequestMap().get("query").toString();
@@ -384,7 +406,7 @@
 		
 		// [base=foo]?
 		String occ10 = "{@type=korap:group, operation=operation:repetition, operands=[" +
-					     "{@type=korap:token, wrap={@type=korap:term, key=foo, layer=lemma, match=match:eq}}" +
+					     "{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=foo, match=match:eq}}" +
 					  "], min=0, max=1}"; 
 		ppt = new PoliqarpPlusTree("[base=foo]?");
 		map = ppt.getRequestMap().get("query").toString();
@@ -392,7 +414,7 @@
 		
 		// [base=foo]{2,5}
 		String occ11 = "{@type=korap:group, operation=operation:repetition, operands=[" +
-					     "{@type=korap:token, wrap={@type=korap:term, key=foo, layer=lemma, match=match:eq}}" +
+					     "{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=foo, match=match:eq}}" +
 					  "], min=2, max=5}"; 
 		ppt = new PoliqarpPlusTree("[base=foo]{2,5}");
 		map = ppt.getRequestMap().get("query").toString();
@@ -400,7 +422,7 @@
 		
 		// [base=foo]{2}
 		String occ12 = "{@type=korap:group, operation=operation:repetition, operands=[" +
-					     "{@type=korap:token, wrap={@type=korap:term, key=foo, layer=lemma, match=match:eq}}" +
+					     "{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=foo, match=match:eq}}" +
 					  "], min=2, max=2}"; 
 		ppt = new PoliqarpPlusTree("[base=foo]{2}");
 		map = ppt.getRequestMap().get("query").toString();
@@ -411,16 +433,16 @@
 	public void testTokenSequence() throws QueryException {
 		// [base=Mann][orth=Frau]
 		String seq1 = "{@type=korap:group, operation=operation:sequence, operands=[" +
-				"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}, " +
-				"{@type=korap:token, wrap={@type=korap:term, key=Frau, layer=orth, match=match:eq}}" +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}, " +
+				"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Frau, match=match:eq}}" +
 				"]}";
 		assertTrue(equalsQueryContent(seq1, "[base=Mann][orth=Frau]"));
 		
 		// [base=Mann][orth=Frau][p=NN]
 		String seq2 = "{@type=korap:group, operation=operation:sequence, operands=[" +
-				"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}, " +
-				"{@type=korap:token, wrap={@type=korap:term, key=Frau, layer=orth, match=match:eq}}, " +
-				"{@type=korap:token, wrap={@type=korap:term, key=NN,layer=p, match=match:eq}}" +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}, " +
+				"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Frau, match=match:eq}}, " +
+				"{@type=korap:token, wrap={@type=korap:term, layer=p, key=NN, match=match:eq}}" +
 				"]}";
 		assertTrue(equalsQueryContent(seq2, "[base=Mann][orth=Frau][p=NN]"));
 	}
@@ -431,10 +453,10 @@
 		String disj1 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
 					"{@type=korap:group, operation=operation:or, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=der, layer=lemma, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=das, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=der, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=das, match=match:eq}}" +
 					"]}," +
-					"{@type=korap:token, wrap={@type=korap:term, key=Schild, layer=lemma, match=match:eq}}" +
+					"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Schild, match=match:eq}}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("([base=der]|[base=das])[base=Schild]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -443,10 +465,10 @@
 		// [base=Schild]([base=der]|[base=das])
 		String disj2 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=Schild, layer=lemma, match=match:eq}}," +
+					"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Schild, match=match:eq}}," +
 					"{@type=korap:group, operation=operation:or, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=der, layer=lemma, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=das, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=der, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=das, match=match:eq}}" +
 					"]}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("[base=Schild]([base=der]|[base=das])");
@@ -457,12 +479,12 @@
 		String disj3 = 
 				"{@type=korap:group, operation=operation:or, operands=[" +
 					"{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=katze, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=der, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=katze, match=match:eq}}" +
 					"]}," +
 					"{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=eine, layer=orth, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=baum, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=eine, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=baum, match=match:eq}}" +
 					"]}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("([orth=der][base=katze])|([orth=eine][base=baum])");
@@ -473,12 +495,12 @@
 		String disj4 = 
 				"{@type=korap:group, operation=operation:or, operands=[" +
 					"{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=katze, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=der, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=katze, match=match:eq}}" +
 					"]}," +
 					"{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=eine, layer=orth, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=baum, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=eine, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=baum, match=match:eq}}" +
 					"]}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("[orth=der][base=katze]|[orth=eine][base=baum]");
@@ -493,16 +515,16 @@
 		String disj5 = 
 				"{@type=korap:group, operation=operation:or, operands=[" +
 					"{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=katze, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=der, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=katze, match=match:eq}}" +
 					"]}," +
 					"{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=hund, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=der, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=hund, match=match:eq}}" +
 					"]}," +
 					"{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=baum, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=der, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=baum, match=match:eq}}" +
 					"]}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("[orth=der][base=katze]|[orth=der][base=hund]|[orth=der][base=baum]");
@@ -512,11 +534,11 @@
 		// [orth=der]([base=katze]|[base=hund]|[base=baum])
 		String disj6 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=der, match=match:eq}}," +
 					"{@type=korap:group, operation=operation:or, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=katze, layer=lemma, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=hund, layer=lemma, match=match:eq}}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=baum, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=katze, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=hund, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=baum, match=match:eq}}" +
 					"]}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("[orth=der]([base=katze]|[base=hund]|[base=baum])");
@@ -528,7 +550,7 @@
 	public void testTokenElemSequence() throws QueryException {
 		// [base=Mann]<vp>
 		String seq1 = "{@type=korap:group, operation=operation:sequence, operands=[" +
-				"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}, " +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}, " +
 				"{@type=korap:span, key=vp}" +
 				"]}";
 		assertTrue(equalsQueryContent(seq1, "[base=Mann]<vp>"));
@@ -536,14 +558,14 @@
 		// <vp>[base=Mann]
 		String seq2 = "{@type=korap:group, operation=operation:sequence, operands=[" +
 				"{@type=korap:span, key=vp}, "+
-				"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}} " +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}} " +
 				"]}";
 		assertTrue(equalsQueryContent(seq2, "<vp>[base=Mann]"));
 		
 		// <vp>[base=Mann]<pp>
 		String seq3 = "{@type=korap:group, operation=operation:sequence, operands=[" +
 				"{@type=korap:span, key=vp}, "+
-				"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}, " +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}, " +
 				"{@type=korap:span, key=pp} "+
 				"]}";
 		assertTrue(equalsQueryContent(seq3, "<vp>[base=Mann]<pp>"));
@@ -569,30 +591,34 @@
 	
 	@Test 
 	public void testClasses() throws QueryException {
+		String query;
 		// {[base=Mann]}
 		String cls1 = "{@type=korap:group, operation=operation:class, class=0, operands=[" +
-				"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}" +
+				"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("{[base=Mann]}");
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(cls1.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
 		// {[base=Mann][orth=Frau]}
+		query = "{[base=Mann][orth=Frau]}";
 		String cls2 = "{@type=korap:group, operation=operation:class, class=0, operands=[" +
 				 "{@type=korap:group, operation=operation:sequence, operands=[" +
-				  "{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}," +
-				  "{@type=korap:token, wrap={@type=korap:term, key=Frau, layer=orth, match=match:eq}}" +
+				  "{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}," +
+				  "{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Frau, match=match:eq}}" +
 				 "]}" +
 				"]}";
-		assertTrue(equalsQueryContent(cls2, "{[base=Mann][orth=Frau]}"));
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(cls2.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
 		// [p=NN]{[base=Mann][orth=Frau]}
 		String cls3 = "{@type=korap:group, operation=operation:sequence, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=NN, layer=p, match=match:eq}}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=p, key=NN, match=match:eq}}," +
 						"{@type=korap:group, operation=operation:class, class=0, operands=[" +
 							"{@type=korap:group, operation=operation:sequence, operands=[" +
-								"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}," +
-								"{@type=korap:token, wrap={@type=korap:term, key=Frau, layer=orth, match=match:eq}}" +
+								"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}," +
+								"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Frau, match=match:eq}}" +
 							"]}" +
 						"]}" +
 					  "]}";
@@ -604,11 +630,11 @@
 		String cls4 = "{@type=korap:group, operation=operation:sequence, operands=[" +
 						"{@type=korap:group, operation=operation:class, class=0, operands=[" +
 						   "{@type=korap:group, operation=operation:sequence, operands=[" +
-						     "{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}," +
-						     "{@type=korap:token, wrap={@type=korap:term, key=Frau, layer=orth, match=match:eq}}" +
+						     "{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}," +
+						     "{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Frau, match=match:eq}}" +
 						   "]}" +
 						"]}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=NN, layer=p, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=p, key=NN, match=match:eq}}" +
 					  "]}";
 		ppt = new PoliqarpPlusTree("{[base=Mann][orth=Frau]}[p=NN]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -618,9 +644,9 @@
 		String cls5 = "{@type=korap:group, operation=operation:class, class=2, operands=[" +
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
 						   "{@type=korap:group, operation=operation:class, class=1, operands=[" +
-						     "{@type=korap:token, wrap={@type=korap:term, key=ADJA, layer=p, foundry=tt, match=match:eq}}" +
+						     "{@type=korap:token, wrap={@type=korap:term, foundry=tt, layer=p, key=ADJA, match=match:eq}}" +
 						   "]}," +
-						   "{@type=korap:token, wrap={@type=korap:term, key=NN, layer=p, foundry=mate, match=match:eq}}" + 
+						   "{@type=korap:token, wrap={@type=korap:term, foundry=mate, layer=p, key=NN, match=match:eq}}" + 
 						"]}" +
 					  "]}";
 		ppt = new PoliqarpPlusTree("{2: {1:[tt/p=ADJA]}[mate/p=NN]}");
@@ -640,7 +666,7 @@
 		// contains(<s>,[base=Mann])
 		String pos2 = "{@type=korap:group, operation=operation:position, frame=frame:contains, operands=[" +
 				  "{@type=korap:span, key=s}," +
-				  "{@type=korap:token, wrap= {@type=korap:term, key=Mann, layer=lemma, match=match:eq}}" +
+				  "{@type=korap:token, wrap= {@type=korap:term, layer=lemma, key=Mann, match=match:eq}}" +
 				"]}";
 		assertTrue(equalsQueryContent(pos2, "contains(<s>,[base=Mann])"));
 		
@@ -648,8 +674,8 @@
 		String pos3 = "{@type=korap:group, operation=operation:position, frame=frame:contains, operands=[" +
 				  	"{@type=korap:span, key=s}," +
 				  	"{@type=korap:group, operation=operation:sequence, operands=[" +
-				  		"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
-				  		"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
+				  		"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=der, match=match:eq}}," +
+				  		"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Mann, match=match:eq}}" +
 				  	"]}" +
 				  "]}";
 		ppt = new PoliqarpPlusTree("contains(<s>,[orth=der][orth=Mann])");
@@ -659,10 +685,10 @@
 		// [base=Auto]contains(<s>,[base=Mann])
 		String pos4 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=Auto, layer=lemma, match=match:eq}}," +
+					"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Auto, match=match:eq}}," +
 					"{@type=korap:group, operation=operation:position, frame=frame:contains, operands=[" +
 				  		"{@type=korap:span, key=s}," +
-				  		"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, match=match:eq}}" +
+				  		"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Mann, match=match:eq}}" +
 				  	"]}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("[base=Auto]contains(<s>,[base=Mann])");
@@ -674,7 +700,7 @@
 					"{@type=korap:group, operation=operation:position, frame=frame:contains, operands=[" +
 				  		"{@type=korap:span, key=s}," +
 				  		"{@type=korap:group, operation=operation:repetition, " +
-				  			"operands=[{@type=korap:token, wrap={@type=korap:term, key=N, layer=pos, match=match:eq}}" +
+				  			"operands=[{@type=korap:token, wrap={@type=korap:term, layer=pos, key=N, match=match:eq}}" +
 				  			"], min=0, max=100" +
 				  		"}" +
 				  	"]}";
@@ -685,11 +711,11 @@
 		// [base=Auto]contains(<s>,[pos=N]*)
 		String pos6 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=Auto, layer=lemma, match=match:eq}}," +
+					"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Auto, match=match:eq}}," +
 					"{@type=korap:group, operation=operation:position, frame=frame:contains, operands=[" +
 				  		"{@type=korap:span, key=s}," +
 				  		"{@type=korap:group, operation=operation:repetition, " +
-				  			"operands=[{@type=korap:token, wrap={@type=korap:term, key=N, layer=pos, match=match:eq}}" +
+				  			"operands=[{@type=korap:token, wrap={@type=korap:term, layer=pos, key=N, match=match:eq}}" +
 				  			"], min=0, max=100" +
 				  		"}" +
 				  	"]}" +
@@ -707,7 +733,7 @@
 				"{@type=korap:span, key=s}," +
 				"{@type=korap:group, operation=operation:position, frame=frame:startswith, operands=[" +
 					"{@type=korap:span, key=np}," +
-					"{@type=korap:token, wrap={@type=korap:term, key=Der, layer=orth, match=match:eq}}" +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Der, match=match:eq}}" +
 				"]}" +
 			"]}";
 		ppt = new PoliqarpPlusTree("contains(<s>, startswith(<np>,[orth=Der]))");
@@ -717,13 +743,13 @@
 	
 	@Test
 	public void testShrinkSplit() throws QueryException {
-		// shrink([orth=Der]{[orth=Mann]})
+		// focus([orth=Der]{[orth=Mann]})
 		String shr1 = 
 			"{@type=korap:reference, classRef=[0], operands=[" +
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=Der, layer=orth, match=match:eq}}," +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Der, match=match:eq}}," +
 					"{@type=korap:group, operation=operation:class, class=0, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Mann, match=match:eq}}" +
 					"]}" +
 				"]}" +
 			"]}";
@@ -731,15 +757,15 @@
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(shr1.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
-		// shrink([orth=Der]{[orth=Mann][orth=geht]})
+		// focus([orth=Der]{[orth=Mann][orth=geht]})
 		String shr2 = 
 			"{@type=korap:reference, classRef=[0], operands=[" +
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=Der, layer=orth, match=match:eq}}," +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Der, match=match:eq}}," +
 					"{@type=korap:group, operation=operation:class, class=0, operands=[" +
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}," +
-							"{@type=korap:token, wrap={@type=korap:term, key=geht, layer=orth, match=match:eq}}" +
+							"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Mann, match=match:eq}}," +
+							"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=geht, match=match:eq}}" +
 						"]}" +
 					"]}" +
 				"]}" +
@@ -748,15 +774,15 @@
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(shr2.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
-		// shrink(1:[orth=Der]{1:[orth=Mann][orth=geht]})
+		// focus(1:[orth=Der]{1:[orth=Mann][orth=geht]})
 		String shr3 = 
 			"{@type=korap:reference, classRef=[1], operands=[" +
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=Der, layer=orth, match=match:eq}}," +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Der, match=match:eq}}," +
 					"{@type=korap:group, operation=operation:class, class=1, operands=[" +
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}," +
-							"{@type=korap:token, wrap={@type=korap:term, key=geht, layer=orth, match=match:eq}}" +
+							"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Mann, match=match:eq}}," +
+							"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=geht, match=match:eq}}" +
 						"]}" +
 					"]}" +
 				"]}" +
@@ -765,7 +791,7 @@
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(shr3.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
-		// shrink(1:startswith(<s>,{1:<np>}))
+		// focus(1:startswith(<s>,{1:<np>}))
 		String shr4 = 
 			"{@type=korap:reference, classRef=[1], operands=[" +
 				"{@type=korap:group, operation=operation:position, frame=frame:startswith, operands=[" +
@@ -779,19 +805,19 @@
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(shr4.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
-		// shrink(3: startswith(<s>, {3:[base=der]{1:[mate/p=ADJA]{2:[tt/p=NN]}}})) 
+		// focus(3: startswith(<s>, {3:[base=der]{1:[mate/p=ADJA]{2:[tt/p=NN]}}})) 
 		String shr5 = 
 			"{@type=korap:reference, classRef=[3], operands=[" +
 				"{@type=korap:group, operation=operation:position, frame=frame:startswith, operands=[" +
 					"{@type=korap:span, key=s}," +
 					"{@type=korap:group, operation=operation:class, class=3, operands=[" +
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=der, layer=lemma, match=match:eq}}," +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=der, match=match:eq}}," +
 							"{@type=korap:group, operation=operation:class, class=1, operands=[" +
 								"{@type=korap:group, operation=operation:sequence, operands=[" +
-									"{@type=korap:token, wrap={@type=korap:term, key=ADJA, layer=p, foundry=mate, match=match:eq}}," +
+									"{@type=korap:token, wrap={@type=korap:term, foundry=mate, layer=p, key=ADJA, match=match:eq}}," +
 									"{@type=korap:group, operation=operation:class, class=2, operands=[" +
-										"{@type=korap:token, wrap={@type=korap:term, key=NN, layer=p, foundry=tt, match=match:eq}}" +
+										"{@type=korap:token, wrap={@type=korap:term, foundry=tt, layer=p, key=NN, match=match:eq}}" +
 									"]}" + 
 								"]}" +
 							"]}" +
@@ -810,12 +836,12 @@
 					"{@type=korap:span, key=s}," +
 					"{@type=korap:group, operation=operation:class, class=3, operands=[" +
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=der, layer=lemma, match=match:eq}}," +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=der, match=match:eq}}," +
 							"{@type=korap:group, operation=operation:class, class=1, operands=[" +
 								"{@type=korap:group, operation=operation:sequence, operands=[" +
-									"{@type=korap:token, wrap={@type=korap:term, key=ADJA, layer=p, foundry=mate, match=match:eq}}," +
+									"{@type=korap:token, wrap={@type=korap:term, foundry=mate, layer=p, key=ADJA, match=match:eq}}," +
 									"{@type=korap:group, operation=operation:class, class=2, operands=[" +
-										"{@type=korap:token, wrap={@type=korap:term, key=NN, layer=p, foundry=tt, match=match:eq}}" +
+										"{@type=korap:token, wrap={@type=korap:term, foundry=tt, layer=p, key=NN, match=match:eq}}" +
 									"]}" + 
 								"]}" +
 							"]}" +
@@ -834,12 +860,12 @@
 					"{@type=korap:span, key=s}," +
 					"{@type=korap:group, operation=operation:class, class=3, operands=[" +
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=der, layer=lemma, match=match:eq}}," +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=der, match=match:eq}}," +
 							"{@type=korap:group, operation=operation:class, class=1, operands=[" +
 								"{@type=korap:group, operation=operation:sequence, operands=[" +
-									"{@type=korap:token, wrap={@type=korap:term, key=ADJA, layer=p, foundry=mate, match=match:eq}}," +
+									"{@type=korap:token, wrap={@type=korap:term, foundry=mate, layer=p, key=ADJA, match=match:eq}}," +
 									"{@type=korap:group, operation=operation:class, class=2, operands=[" +
-										"{@type=korap:token, wrap={@type=korap:term, key=NN, layer=p, foundry=tt, match=match:eq}}" +
+										"{@type=korap:token, wrap={@type=korap:term, foundry=tt, layer=p, key=NN, match=match:eq}}" +
 									"]}" + 
 								"]}" +
 							"]}" +
@@ -856,10 +882,10 @@
 			"{@type=korap:reference, classRef=[1], operands=[" +
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
 					"{@type=korap:group, operation=operation:class, class=0, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=der, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=der, match=match:eq}}" +
 					"]}," +
 					"{@type=korap:group, operation=operation:class, class=1, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=ADJA, layer=pos, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=pos, key=ADJA, match=match:eq}}" +
 					"]}" +
 				"]}" +
 			"]}";
@@ -873,7 +899,7 @@
 	@Test
 	public void testFoundries() throws QueryException {
 		// [tt/base=Mann]
-		String layer1 = "{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=lemma, foundry=tt, match=match:eq}}";
+		String layer1 = "{@type=korap:token, wrap={@type=korap:term, foundry=tt, layer=lemma, key=Mann, match=match:eq}}";
 		ppt = new PoliqarpPlusTree("[tt/base=Mann]");
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(layer1.replaceAll(" ", ""), map.replaceAll(" ", ""));
@@ -885,10 +911,10 @@
 		// [orth=der]^[orth=Mann]
 		String align1 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
-					"{@type=korap:group, align=left, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
-					"]}" +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=der, match=match:eq}}," +
+					"{@type=korap:group, operation=operation:alignment, operands=[" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Mann, match=match:eq}}" +
+					"], align=align:left}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("[orth=der]^[orth=Mann]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -898,13 +924,13 @@
 		String query = "[orth=der]^[orth=große][orth=Mann]";
 		String align1b = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=der, layer=orth, match=match:eq}}," +
-					"{@type=korap:group, align=left, operands=[" +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=der, match=match:eq}}," +
+					"{@type=korap:group, operation=operation:alignment, operands=[" +
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=große, layer=orth, match=match:eq}}," +
-							"{@type=korap:token, wrap={@type=korap:term, key=Mann, layer=orth, match=match:eq}}" +
+							"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=große, match=match:eq}}," +
+							"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Mann, match=match:eq}}" +
 						"]}" +
-					"]}" +
+					"], align=align:left}" +
 				"]}";
 		ppt = new PoliqarpPlusTree(query);
 		map = ppt.getRequestMap().get("query").toString();
@@ -914,12 +940,12 @@
 		String align2 = 
 				"{@type=korap:group, operation=operation:or, operands=[" +
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=a, layer=lemma, match=match:eq}}," +
-							"{@type=korap:group, align=left, operands=[" +
-								"{@type=korap:token, wrap={@type=korap:term, key=b, layer=lemma, match=match:eq}}" +
-							"]}" +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=a, match=match:eq}}," +
+							"{@type=korap:group, operation=operation:alignment, operands=[" +
+								"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=b, match=match:eq}}" +
+							"], align=align:left}" +
 						"]}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=c, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=c, match=match:eq}}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("([base=a]^[base=b])|[base=c]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -929,15 +955,15 @@
 		String align3 = 
 				"{@type=korap:group, operation=operation:or, operands=[" +
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=a, layer=lemma, match=match:eq}}," +
-							"{@type=korap:group, align=left, operands=[" +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=a, match=match:eq}}," +
+							"{@type=korap:group, operation=operation:alignment, operands=[" +
 								"{@type=korap:group, operation=operation:sequence, operands=[" +
-									"{@type=korap:token, wrap={@type=korap:term, key=b, layer=lemma, match=match:eq}}," +
-									"{@type=korap:token, wrap={@type=korap:term, key=c, layer=lemma, match=match:eq}}" +
+									"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=b, match=match:eq}}," +
+									"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=c, match=match:eq}}" +
 								"]}" +
-							"]}" +
+							"], align=align:left}" +
 						"]}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=d, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=d, match=match:eq}}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("([base=a]^[base=b][base=c])|[base=d]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -947,17 +973,17 @@
 		String align4 = 
 				"{@type=korap:group, operation=operation:or, operands=[" +
 						"{@type=korap:group, operation=operation:sequence, operands=[" +
-							"{@type=korap:token, wrap={@type=korap:term, key=a, layer=lemma, match=match:eq}}," +
-							"{@type=korap:group, align=left, operands=[" +
+							"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=a, match=match:eq}}," +
+							"{@type=korap:group, operation=operation:alignment, operands=[" +
 								"{@type=korap:group, operation=operation:sequence, operands=[" +
-									"{@type=korap:token, wrap={@type=korap:term, key=b, layer=lemma, match=match:eq}}," +
-									"{@type=korap:group, align=left, operands=[" +
-										"{@type=korap:token, wrap={@type=korap:term, key=c, layer=lemma, match=match:eq}}" +
-									"]}" +
+									"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=b, match=match:eq}}," +
+									"{@type=korap:group, operation=operation:alignment, operands=[" +
+										"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=c, match=match:eq}}" +
+									"], align=align:left}" +
 								"]}" +
-							"]}" +
+							"], align=align:left}" +
 						"]}," +
-						"{@type=korap:token, wrap={@type=korap:term, key=d, layer=lemma, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=d, match=match:eq}}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("([base=a]^[base=b]^[base=c])|[base=d]");
 		map = ppt.getRequestMap().get("query").toString();
@@ -970,27 +996,44 @@
 	public void testSimpleQueries() throws QueryException {
 		// Baum
 		String simple1 = 
-				"{@type=korap:token, wrap={@type=korap:term, key=Baum, layer=orth, match=match:eq}}";
+				"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Baum, match=match:eq}}";
 		ppt = new PoliqarpPlusTree("Baum");
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(simple1.replaceAll(" ", ""), map.replaceAll(" ", ""));
+
+		// Baum/i
+		String simple1b = 
+				"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Baum, match=match:eq, caseInsensitive=true}}";
+		ppt = new PoliqarpPlusTree("Baum/i");
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(simple1b.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
 		// Der Baum
 		String simple2 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=Der, layer=orth, match=match:eq}}, " +
-					"{@type=korap:token, wrap={@type=korap:term, key=Baum, layer=orth, match=match:eq}}" +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Der, match=match:eq}}, " +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Baum, match=match:eq}}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("Der Baum");
 		map = ppt.getRequestMap().get("query").toString();
 		assertEquals(simple2.replaceAll(" ", ""), map.replaceAll(" ", ""));
 		
+		// Der Baum/i
+		String simple2b = 
+				"{@type=korap:group, operation=operation:sequence, operands=[" +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Der, match=match:eq}}, " +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Baum, match=match:eq, caseInsensitive=true}}" +
+				"]}";
+		ppt = new PoliqarpPlusTree("Der Baum/i");
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(simple2b.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
 		// Der große Baum
 		String simple3 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=Der, layer=orth, match=match:eq}}, " +
-					"{@type=korap:token, wrap={@type=korap:term, key=große, layer=orth, match=match:eq}}, " +						
-					"{@type=korap:token, wrap={@type=korap:term, key=Baum, layer=orth, match=match:eq}}" +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Der, match=match:eq}}, " +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=große, match=match:eq}}, " +						
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Baum, match=match:eq}}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("Der große Baum");
 		map = ppt.getRequestMap().get("query").toString();
@@ -999,8 +1042,8 @@
 		// Baum | Stein
 		String simple4 = 
 				"{@type=korap:group, operation=operation:or, operands=[" +
-					"{@type=korap:token, wrap={@type=korap:term, key=Baum, layer=orth, match=match:eq}}, " +						
-					"{@type=korap:token, wrap={@type=korap:term, key=Stein, layer=orth, match=match:eq}}" +
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Baum, match=match:eq}}, " +						
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Stein, match=match:eq}}" +
 				"]}";
 		ppt = new PoliqarpPlusTree("Baum | Stein");
 		map = ppt.getRequestMap().get("query").toString();
@@ -1011,10 +1054,10 @@
 		String simple5 = 
 				"{@type=korap:group, operation=operation:sequence, operands=[" +
 					"{@type=korap:group, operation=operation:or, operands=[" +
-						"{@type=korap:token, wrap={@type=korap:term, key=Baum, layer=orth, match=match:eq}}, " +						
-						"{@type=korap:token, wrap={@type=korap:term, key=Stein, layer=orth, match=match:eq}}" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Baum, match=match:eq}}, " +						
+						"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Stein, match=match:eq}}" +
 					"]}," +
-					"{@type=korap:token, wrap={@type=korap:term, key=Haus, layer=orth, match=match:eq}} " +			
+					"{@type=korap:token, wrap={@type=korap:term, layer=orth, key=Haus, match=match:eq}} " +			
 				"]}";
 		ppt = new PoliqarpPlusTree(query);
 		map = ppt.getRequestMap().get("query").toString();