- subspan() operator in Poliqarp to define spanRefs directly. 
- intended to use submatch() for this, but this operator is still in use (though deprecated) as an alternative to focus()
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 ade5135..5bf42a5 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
@@ -234,6 +234,32 @@
 			stackedObjects++;
 		}
 
+		if (nodeCat.equals("relation")) {
+			LinkedHashMap<String, Object> relationGroup = makeGroup("relation");
+			LinkedHashMap<String, Object> relation = makeRelation();
+			relationGroup.put("relation", relation);
+			if (node.getChild(0).getText().equals("dominates")) {
+				relation.put("layer", "c");
+			}
+			ParseTree relSpec = getFirstChildWithCat(node, "relSpec");
+			ParseTree repetition = getFirstChildWithCat(node, "repetition");
+			if (relSpec != null) {
+				ParseTree foundry = getFirstChildWithCat(relSpec, "foundry");
+				ParseTree layer = getFirstChildWithCat(relSpec, "layer");
+				ParseTree key = getFirstChildWithCat(relSpec, "key");
+				if (foundry != null) relation.put("foundry", foundry.getText());
+				if (layer != null) relation.put("layer", layer.getText());
+				if (key != null) relation.put("key", key.getText());
+			}
+			if (repetition != null) {
+				Integer[] minmax =  parseRepetition(repetition);
+				relation.put("boundary", makeBoundary(minmax[0], minmax[1]));
+			}
+			putIntoSuperObject(relationGroup);
+			objectStack.push(relationGroup);
+			stackedObjects++;
+		}
+		
 		if (nodeCat.equals("spanclass")) {
 			// Step I: get info
 			int classId = 0;
@@ -256,7 +282,6 @@
 			stackedObjects++;
 		}
 
-
 		if (nodeCat.equals("matching")) {
 			// Step I: get info
 			ArrayList<Integer> classRefs = new ArrayList<Integer>();
@@ -272,7 +297,9 @@
 							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.");
+							String err = "The specified class reference in the shrink/split-Operator is not a number.";
+							errorMsgs.add(err);
+							throw new QueryException(err);
 						}
 					}
 				}
@@ -282,6 +309,7 @@
 			LinkedHashMap<String, Object> referenceGroup = makeReference(classRefs);
 
 			String type = node.getChild(0).toStringTree(parser);
+			// Default is focus(), if deviating catch here
 			if (type.equals("split")) referenceGroup.put("operation", "operation:split");
 			if (type.equals("submatch") || type.equals("shrink")) {
 				String warning = type + "() is deprecated in favor of focus()";
@@ -300,6 +328,23 @@
 			visited.add(node.getChild(0));
 		}
 
+		if (nodeCat.equals("subspan")) {
+			LinkedHashMap<String,Object> subspan = makeReference(null);
+			subspan.put("operands", new ArrayList<Object>());
+			ParseTree startpos = getFirstChildWithCat(node,"startpos");
+			ParseTree length = getFirstChildWithCat(node,"length");
+			ArrayList<Integer> spanRef = new ArrayList<Integer>();
+			spanRef.add(Integer.parseInt(startpos.getText()));
+			if (length != null) {
+				spanRef.add(Integer.parseInt(length.getText()));
+			}
+			subspan.put("spanRef", spanRef);
+			putIntoSuperObject(subspan);
+			objectStack.push(subspan);
+			stackedObjects++;
+			visited.add(node.getChild(0));
+		}
+		
 		if (nodeCat.equals("meta")) {
 			LinkedHashMap<String, Object> metaFilter = new LinkedHashMap<String, Object>();
 			requestMap.put("meta", metaFilter);
@@ -466,7 +511,7 @@
 			if (!getNodeCat(node.getChild(node.getChildCount()-1)).equals(")")) rightOp = node.getChild(node.getChildCount()-1);
 			else rightOp = node.getChild(node.getChildCount()-2);
 			// establish boolean relation
-			ParseTree boolOp = getFirstChildWithCat(node, "booleanOp"); 
+			ParseTree boolOp = getFirstChildWithCat(node, "boolOp"); 
 			String operator = boolOp.getText().equals("&") ? "and" : "or";
 			termGroup = makeTermGroup(operator);
 			ArrayList<Object> operands = (ArrayList<Object>) termGroup.get("operands");
@@ -622,9 +667,13 @@
 //				"[base=geht][base=der][]*[base=Mann]",
 //				"<cnx/c=vp (class=header&id=7)>",
 //				"<cnx/c=vp class=header&id=a>",
-				"[][]*[base=Mann]"
+				"[][]*[base=Mann]",
+				"focus(2&3|4:contains({2:<s>},[base=mann]))",
+				"relatesTo(cnx/c:<s>,<np>)",
+				"dominates(cnx/c*:<np>,[base=Baum])",
+				"subspan(2,3:<s>)"
 		};
-//		PoliqarpPlusTree.verbose=true;
+		PoliqarpPlusTree.verbose=true;
 		for (String q : queries) {
 			try {
 				System.out.println(q);
diff --git a/src/test/java/PoliqarpPlusTreeTest.java b/src/test/java/PoliqarpPlusTreeTest.java
index 567395c..4f835fb 100644
--- a/src/test/java/PoliqarpPlusTreeTest.java
+++ b/src/test/java/PoliqarpPlusTreeTest.java
@@ -994,7 +994,7 @@
 	}
 	
 	@Test
-	public void testShrinkSplit() throws QueryException {
+	public void testFocusSplit() throws QueryException {
 		// focus([orth=Der]{[orth=Mann]})
 		String shr1 = 
 			"{@type=korap:reference, operation=operation:focus, classRef=[0], operands=[" +
@@ -1147,6 +1147,124 @@
 		
 	}
 	
+	@Test
+	public void testSubspan() throws QueryException {
+		query = "subspan(1:<s>)";
+		expected = 
+			"{@type=korap:reference, operation=operation:focus, operands=[" +
+					"{@type=korap:span, key=s}" +
+				"], spanRef=[1]" +
+			"}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(expected.replaceAll(" ", ""), map.replaceAll(" ", ""));
+	
+		query = "subspan(1,4:<s>)";
+		expected = 
+			"{@type=korap:reference, operation=operation:focus, operands=[" +
+					"{@type=korap:span, key=s}" +
+				"], spanRef=[1,4]" +
+			"}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(expected.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
+		query = "subspan(1,4:contains(<s>,[base=Haus]))";
+		expected = 
+			"{@type=korap:reference, operation=operation:focus, operands=[" +
+				"{@type=korap:group, operation=operation:position, frame=frame:contains, operands=[" +
+					"{@type=korap:span, key=s}," +
+					"{@type=korap:token, wrap= {@type=korap:term, layer=lemma, key=Haus, match=match:eq}}" +
+				"]}" +
+				"], spanRef=[1,4]" +
+			"}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(expected.replaceAll(" ", ""), map.replaceAll(" ", ""));
+	}
+	
+	@Test
+	public void testRelations() throws QueryException {
+		query = "relatesTo(<s>,<np>)";
+		expected = 
+			"{@type=korap:group, operation=operation:relation, operands=[" +
+					"{@type=korap:span, key=s}," +
+					"{@type=korap:span, key=np}" +
+				"], relation={@type=korap:relation}" +
+			"}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(expected.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
+		query = "relatesTo([base=Baum],<np>)";
+		expected = 
+				"{@type=korap:group, operation=operation:relation, operands=[" +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Baum, match=match:eq}}," +
+						"{@type=korap:span, key=np}" +
+					"], relation={@type=korap:relation}" +
+				"}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(expected.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
+		query = "dominates(<np>,[base=Baum])";
+		expected = 
+				"{@type=korap:group, operation=operation:relation, operands=[" +
+						"{@type=korap:span, key=np}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Baum, match=match:eq}}" +
+					"], relation={@type=korap:relation, layer=c}" +
+				"}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(expected.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
+		query = "dominates(cnx/c:<np>,[base=Baum])";
+		expected = 
+				"{@type=korap:group, operation=operation:relation, operands=[" +
+						"{@type=korap:span, key=np}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Baum, match=match:eq}}" +
+					"], relation={@type=korap:relation, layer=c, foundry=cnx}" +
+				"}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(expected.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
+		query = "dominates(cnx/c*:<np>,[base=Baum])";
+		expected = 
+				"{@type=korap:group, operation=operation:relation, operands=[" +
+						"{@type=korap:span, key=np}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Baum, match=match:eq}}" +
+					"], relation={@type=korap:relation, layer=c, foundry=cnx, boundary={@type=korap:boundary, min=0}}" +
+				"}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(expected.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
+		query = "dominates(cnx/c{1,5}:<np>,[base=Baum])";
+		expected = 
+				"{@type=korap:group, operation=operation:relation, operands=[" +
+						"{@type=korap:span, key=np}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Baum, match=match:eq}}" +
+					"], relation={@type=korap:relation, layer=c, foundry=cnx, boundary={@type=korap:boundary, min=1, max=5}}" +
+				"}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(expected.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
+		query = "relatesTo(mate/d=HEAD:<np>,[base=Baum])";
+		expected = 
+				"{@type=korap:group, operation=operation:relation, operands=[" +
+						"{@type=korap:span, key=np}," +
+						"{@type=korap:token, wrap={@type=korap:term, layer=lemma, key=Baum, match=match:eq}}" +
+					"], relation={@type=korap:relation, foundry=mate, layer=d, key=HEAD}" +
+				"}";
+		ppt = new PoliqarpPlusTree(query);
+		map = ppt.getRequestMap().get("query").toString();
+		assertEquals(expected.replaceAll(" ", ""), map.replaceAll(" ", ""));
+		
+	}
+	
+	
 	
 	@Test
 	public void testFoundries() throws QueryException {