- QueryException for malformed/failing queries 
- debugging align operator, still work to do for complex aligns (e.g. embedded in cq_disj_segments)
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 65a907c..aef3f6e 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
@@ -23,6 +23,7 @@
 import de.ids_mannheim.korap.query.PoliqarpPlusLexer;
 import de.ids_mannheim.korap.query.PoliqarpPlusParser;
 import de.ids_mannheim.korap.query.serialize.AbstractSyntaxTree;
+import de.ids_mannheim.korap.util.QueryException;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -127,6 +128,7 @@
 	 * 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) {
 		try {
@@ -137,7 +139,12 @@
 				query = query.replaceAll(" ", "");
 				process(query);
 			} else {
-				throw new RuntimeException("Error handling query.");
+				try {
+					throw new QueryException("Error handling query.");
+				} catch (QueryException e1) {
+					e1.printStackTrace();
+					System.exit(1);
+				}
 			}
 		}
 		System.out.println(">>> "+requestMap.get("query")+" <<<");
@@ -178,11 +185,15 @@
 	
 	@Override
 	public void process(String query) {
-		ParseTree tree;
+		ParseTree tree = null;
 		try {
 			tree = parsePoliqarpQuery(query);
-		} catch (IllegalArgumentException e) {
-			tree = parsePoliqarpQuery(query.replaceAll(" ", ""));
+		} catch (QueryException e) {
+			try {
+				tree = parsePoliqarpQuery(query.replaceAll(" ", ""));
+			} catch (QueryException e1) {
+				System.exit(1);
+			}
 		}
 		System.out.println("Processing PoliqarpPlus");
 		prepareContext();
@@ -262,7 +273,7 @@
 						stackedTokens++;
 						objectStack.push(sequence);
 						stackedObjects++;
-					// else, it's a group (with shrink()/spanclass/... as child)
+					// else, it's a group (with shrink()/spanclass/align... as child)
 					} else {
 						sequence.put("@type", "korap:group");
 					}
@@ -506,6 +517,36 @@
 			} 
 		}
 		
+		if (nodeCat.equals("cq_seg_align")) {
+			LinkedHashMap<String,Object> alignGroup = new LinkedHashMap<String,Object>();
+			objectStack.push(alignGroup);
+			stackedObjects++;
+			// Step I: get info
+			// find position of ^ operator
+			Integer i;
+			for (i=0; i<node.getChildCount(); i++) {
+				if (node.getChild(i).toStringTree(poliqarpParser).startsWith("^")) {
+					break;
+				}
+			}
+			// fill group
+			alignGroup.put("@type", "korap:group");
+			alignGroup.put("relation", "align");
+			alignGroup.put("align", i);
+			alignGroup.put("operands", new ArrayList<Object>());
+			// Step II: decide where to put the group
+			// add group 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 relevant info)
+			if (node.getParent().getChildCount()>1) {
+				ArrayList<Object> topSequenceOperands = (ArrayList<Object>) objectStack.get(1).get("operands");
+				topSequenceOperands.add(alignGroup); 
+			} else if (openNodeCats.get(2).equals("query")) {
+				requestMap.put("query", alignGroup);	
+			} else {
+				ArrayList<Object> topSequenceOperands = (ArrayList<Object>) objectStack.get(1).get("operands");
+				topSequenceOperands.add(alignGroup); 
+			}
+		}
+		
 		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> elem;
@@ -747,24 +788,23 @@
 		return false;
 	}
 	
-	private static void checkUnbalancedPars(String q) throws IllegalArgumentException {
+	private static void checkUnbalancedPars(String q) throws QueryException {
 		int openingPars = StringUtils.countMatches(q, "(");
 		int closingPars = StringUtils.countMatches(q, ")");
 		int openingBrkts = StringUtils.countMatches(q, "[");
 		int closingBrkts = StringUtils.countMatches(q, "]");
 		int openingBrcs = StringUtils.countMatches(q, "{");
 		int closingBrcs = StringUtils.countMatches(q, "}");
-		// TODO change to Query Exception as soon as KorAP-lucene-index installs
-		if (openingPars != closingPars) throw new IllegalArgumentException(
+		if (openingPars != closingPars) throw new QueryException(
 				"Your query string contains an unbalanced number of parantheses.");
-		if (openingBrkts != closingBrkts) throw new IllegalArgumentException(
+		if (openingBrkts != closingBrkts) throw new QueryException(
 				"Your query string contains an unbalanced number of brackets.");
-		if (openingBrcs != closingBrcs) throw new IllegalArgumentException(
+		if (openingBrcs != closingBrcs) throw new QueryException(
 				"Your query string contains an unbalanced number of braces.");
 		
 	}
 	
-	private static ParserRuleContext parsePoliqarpQuery (String p) throws IllegalArgumentException {
+	private static ParserRuleContext parsePoliqarpQuery (String p) throws QueryException {
 		checkUnbalancedPars(p);
 		
 		Lexer poliqarpLexer = new PoliqarpPlusLexer((CharStream)null);
@@ -792,8 +832,7 @@
 	      System.err.println( e.getMessage() );
 	    }
 	    
-	    // TODO change to Query Exception as soon as KorAP-lucene-index installs
-	    if (tree==null) throw new IllegalArgumentException(
+	    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
@@ -816,19 +855,20 @@
 //				"<s>([base=bar][base=foo])*",
 //				"<s>[orth=Mann]([base=bar][base=foo])*",
 //				"<s><np>([base=bar][base=foo])*",
-				"shrink(1:contains(<s>,{1:<np>}))",
-				"contains(<s>,startswith(<np>,[p=Det]))",
-				"shrink(1: contains(<s>,{1:<np>}))",
-				"contains(<s>, startswith(<np>,[p=Det]))",
-				
-				
-				
+//				"shrink(1:contains(<s>,{1:<np>}))",
+//				"contains(<s>,startswith(<np>,[p=Det]))",
+//				"shrink(1: contains(<s>,{1:<np>}))",
+//				"contains(<s>, startswith(<np>,[p=Det]))",
+//				
+//				"[orth=der]^[orth=Mann]",
+//				"([base=bar][base=foo])*",
+				"([base=a]^[base=b])|[base=c]"
 		};
-//		PoliqarpPlusTree.verbose=true;
+		PoliqarpPlusTree.debug=true;
 		for (String q : queries) {
 			try {
 				System.out.println(q);
-//				System.out.println(PoliqarpPlusTree.parsePoliqarpQuery(q).toStringTree(PoliqarpPlusTree.poliqarpParser));
+				System.out.println(PoliqarpPlusTree.parsePoliqarpQuery(q).toStringTree(PoliqarpPlusTree.poliqarpParser));
 				@SuppressWarnings("unused")
 				PoliqarpPlusTree pt = new PoliqarpPlusTree(q);
 				System.out.println(q);
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java b/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java
index 0f68298..a1aacdd 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java
@@ -3,6 +3,9 @@
 import com.fasterxml.jackson.core.JsonGenerationException;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
+
+import de.ids_mannheim.korap.util.QueryException;
+
 import org.slf4j.LoggerFactory;
 
 import java.io.File;
@@ -26,6 +29,7 @@
 
     /**
      * @param args
+     * @throws QueryException 
      */
     public static void main(String[] args) {
         /*
@@ -81,7 +85,9 @@
                 e.printStackTrace();
             } catch (IOException e) {
                 e.printStackTrace();
-            }
+            } catch (QueryException e) {
+				e.printStackTrace();
+			}
         }
     }
 
@@ -95,9 +101,10 @@
      * @throws JsonGenerationException
      * @throws JsonMappingException
      * @throws IOException
+     * @throws QueryException 
      */
     public void run(String query, String queryLanguage, String outFile)
-            throws JsonGenerationException, JsonMappingException, IOException {
+            throws JsonGenerationException, JsonMappingException, IOException, QueryException {
         if (queryLanguage.equals("poliqarp")) {
             ast = new PoliqarpPlusTree(query);
 //		} else if (queryLanguage.equals("cosmas")) {
@@ -105,7 +112,7 @@
         } else if (queryLanguage.equals("poliqarpplus")) {
             ast = new PoliqarpPlusTree(query);
         } else {
-            throw new IllegalArgumentException(queryLanguage + " is not a supported query language!");
+            throw new QueryException(queryLanguage + " is not a supported query language!");
         }
         Map<String, Object> requestMap = ast.getRequestMap();
         mapper.writeValue(new File(outFile), requestMap);
@@ -113,7 +120,7 @@
 
     public String run(String query, String ql, List<String> parents,
                       String cli, String cri, int cls, int crs, int page, int num)
-            throws IllegalArgumentException{
+            throws QueryException{
         if (ql.toLowerCase().equals("poliqarp")) {
             ast = new PoliqarpPlusTree(query);
 //		} else if (ql.toLowerCase().equals("cosmas")) {
@@ -121,7 +128,7 @@
         } else if (ql.toLowerCase().equals("poliqarpplus")) {
             ast = new PoliqarpPlusTree(query);
         } else {
-            throw new IllegalArgumentException(ql + " is not a supported query language!");
+            throw new QueryException(ql + " is not a supported query language!");
         }
         Map<String, Object> requestMap = ast.getRequestMap();
         MetaQuery metaQuery = new MetaQuery();