Merge branch 'opPROX' of ssh://korap.ids-mannheim.de:29418/KorAP/Koral into opPROX

Change-Id: I4a066545ecdf4fd73463453b0a36e66421773d76
diff --git a/src/main/antlr/cosmas/c2ps.g b/src/main/antlr/cosmas/c2ps.g
index dd750f3..269f27f 100644
--- a/src/main/antlr/cosmas/c2ps.g
+++ b/src/main/antlr/cosmas/c2ps.g
@@ -96,7 +96,15 @@
 fragment GROUP
 	:	('min' | 'max');
 
-OP_PROX	:	('/' | '%') DIST (',' DIST)* (',' GROUP)? ;
+// version (12.01.24/FB):
+// accept correct and incorrect chars till the next blank, that way the incorrect chars
+// are submitted to the sub-grammer c2ps_opPROX where they are detected and an appropriate 
+// error message is inserted:
+OP_PROX		:	('/' | '%') DIST (~' ')*; 
+
+// old version: accepts only correctly formulated options, so the incorrect
+// chars/options are hard to detect:
+// OP_PROX	:	('/' | '%') DIST (',' DIST)* (',' GROUP)?  ;
 
 OP_IN	:	'#IN' | '#IN(' OP_IN_OPTS? ')' ; 
 
@@ -310,4 +318,3 @@
 opALL	:	( '#ALL(' | '#EXKLUSIVE(' ) searchExpr ')'  -> ^(OPALL searchExpr) ;
 
 opREG	:	OP_REG -> ^(OPREG {c2ps_opREG.encode($OP_REG.text, OPREG)}) ;
-
diff --git a/src/main/antlr/cosmas/c2ps_opPROX.g b/src/main/antlr/cosmas/c2ps_opPROX.g
index ab0f4cb..1569d1a 100644
--- a/src/main/antlr/cosmas/c2ps_opPROX.g
+++ b/src/main/antlr/cosmas/c2ps_opPROX.g
@@ -16,46 +16,14 @@
 	  DIST_LIST; DIST; RANGE; VAL0; 
 	  MEAS; // measure
 	  DIR; PLUS; MINUS; BOTH;
-	  GRP; MIN; MAX; }
+	  GRP; MIN; MAX;
+	  }
 	  
 @header {package de.ids_mannheim.korap.query.parse.cosmas;
 		 import  de.ids_mannheim.korap.util.C2RecognitionException;}
 		 
 @lexer::header {package de.ids_mannheim.korap.query.parse.cosmas;}
 
-@members {
-    public void displayRecognitionError(String[] tokenNames,
-                                        RecognitionException e) {
-        String hdr = getErrorHeader(e);
-        String msg = getErrorMessage(e, tokenNames);
-        System.err.println("Debug: displayRecognitionError: hdr = " + hdr + ".");
-        System.err.println("Debug: displayRecognitionError: msg='" + msg + "'.");
-        System.err.println("Debug: displayRecognitionError: e = " + e.toString() + ".");
-        
-        if( e instanceof C2RecognitionException )
-        	{
-        	C2RecognitionException c2e = (C2RecognitionException) e;
-        	String c2msg = hdr + ": PROX options mismatch at '" + c2e.getMismatchedToken() + "'...";
-        	
-        	emitErrorMessage(c2msg);
-        	}
-        else
-        	emitErrorMessage(hdr + " prox options mismatch...");
-       
-        // Now do something with hdr and msg...
-    }
-}
-
-@rulecatch {
-  catch (C2RecognitionException c2e) {
-    //Custom handling of an exception. Any java code is allowed.
-    System.err.printf("Debug: overall rulecatch for c2ps_opPROX: c2RecognitionException.\n");
-    //reportError(c2e);
-    //recover(c2e.input, (RecognitionException) c2e);
-    //throw (RecognitionException)c2e;
-    //System.err.printf("Debug: overall rulecatch: back from reportError(c2e).\n");
-  }
-} // rulecatch
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 //
@@ -66,6 +34,12 @@
 DISTVALUE
 	:	('0' .. '9')+ ;
 	
+// trying to catch everything (at the end of the option sequence) that should not appear inside the prox. options:
+// e.g. /w5umin -> remain = 'umin'.
+
+PROX_REMAIN
+	: (',')? ('b'..'h'|'j'..'l'|'n'|'o'|'q'|'r'|'u'|'v'|'y'|'z'|'B'..'H'|'J'..'L'|'N'|'O'|'Q'|'R'|'U'|'V'|'Y'|'Z') (~ ' ')* ;
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 //
 // 						PROX-Parser
@@ -73,24 +47,22 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
 
-opPROX[int pos]	:	proxTyp proxDist[$pos] (',' proxDist[$pos])* (',' proxGroup)? 
+opPROX[int pos]	:	proxTyp proxDist[$pos] (',' proxDist[$pos])* (',' proxGroup)?  (proxRemain[$pos])?
 		
-		-> ^(PROX_OPTS {$proxTyp.tree} ^(DIST_LIST proxDist+) {$proxGroup.tree});
+		-> ^(PROX_OPTS {$proxTyp.tree} ^(DIST_LIST proxDist+) {$proxGroup.tree} {$proxRemain.tree});
 	
+proxRemain[int pos] : PROX_REMAIN
+
+		-> { c2ps_opPROX.checkRemain(DIST, $PROX_REMAIN.text, $pos) };
+
 proxTyp	:  '/' -> ^(TYP PROX)	// klassischer Abstand.
 		|  '%' -> ^(TYP EXCL);	// ausschließender Abstand.
 
 // proxDist: e.g. +5w or -s0 or /w2:4 etc.
 // kein proxDirection? hier, weil der Default erst innerhalb von Regel proxDirection erzeugt werden kann.
-/* incomplete original version:
-proxDist:	proxDirection (v1=proxDistValue m1=proxMeasure | m2=proxMeasure v2=proxDistValue)
-
-		-> {$v1.tree != null}? ^(DIST {$proxDirection.tree} {$v1.tree} {$m1.tree})
-		->		 		       ^(DIST {$proxDirection.tree} {$v2.tree} {$m2.tree});
-*/
 
 // new rule: accepts options in any order:
-// count each option type and find out if any one  is missing or occures multiple times.
+// count each option type and find out if any one is missing or occures multiple times.
 // 28.11.23/FB
 
 proxDist[int pos]
@@ -126,6 +98,8 @@
 	:	DISTVALUE;
 	
 proxGroup
-	:	'min' -> ^(GRP MIN)
-	|	'max' -> ^(GRP MAX);
+	:	('min'|'MIN') -> ^(GRP MIN)
+	|	('max'|'MAX') -> ^(GRP MAX);
+	
+
 	
\ No newline at end of file
diff --git a/src/main/java/de/ids_mannheim/korap/query/parse/cosmas/c2ps_opPROX.java b/src/main/java/de/ids_mannheim/korap/query/parse/cosmas/c2ps_opPROX.java
index 82bc9b9..6229719 100644
--- a/src/main/java/de/ids_mannheim/korap/query/parse/cosmas/c2ps_opPROX.java
+++ b/src/main/java/de/ids_mannheim/korap/query/parse/cosmas/c2ps_opPROX.java
@@ -15,14 +15,13 @@
 public class c2ps_opPROX 
 
 {
-	final static int typeERROR = 1; // type of an Error CommonToken.
-	final static int ERR_MEAS_NULL = 300;
-	final static int ERR_MEAS_TOOGREAT = 301;
-	final static int ERR_VAL_NULL = 302;
-	final static int ERR_VAL_TOOGREAT = 303;
-	final static int ERR_DIR_TOOGREAT = 304;
+	final static boolean bDebug = false;
 	
-	private static CommonTree buildErrorTree(String text, int errCode, int typeDIST, int pos)
+	// type of an Error CommonToken:
+	final static int typeERROR = 1; 
+	// Prox error codes defined in StatusCodes.java.
+	
+	private static CommonTree buildErrorTree(String text, int errCode, int typeDIST, int pos) 
 	
 	{
 	CommonTree
@@ -30,9 +29,9 @@
 	CommonTree
 		errorNode = new CommonTree(new CommonToken(typeERROR, "ERROR"));
 	CommonTree
-		errorPos  = new CommonTree(new CommonToken(typeERROR, Integer.toString(errCode)));
+		errorPos  = new CommonTree(new CommonToken(typeERROR, String.valueOf(pos)));
 	CommonTree
-		errorArg  = new CommonTree(new CommonToken(1, text));
+		errorCode = new CommonTree(new CommonToken(typeERROR, String.valueOf(errCode)));
 	CommonTree
 		errorMes;
 	String
@@ -40,27 +39,31 @@
 	
 	switch( errCode )
 		{
-	case ERR_MEAS_NULL:
+	case StatusCodes.ERR_PROX_MEAS_NULL:
 		mess      = String.format("Abstandsoperator an der Stelle '%s' es fehlt eine der folgenden Angaben: w,s,p!", text);
 		errorMes  = new CommonTree(new CommonToken(typeERROR, mess));
 		break;
-	case ERR_MEAS_TOOGREAT:
+	case StatusCodes.ERR_PROX_MEAS_TOOGREAT:
 		mess      = String.format("Abstandsoperator an der Stelle '%s': Bitte nur 1 der folgenden Angaben einsetzen: w,s,p! " +
-							 "Falls Mehrfachangabe erwünscht, dann durch Kommata trennen (z.B.: /+w2,s0).", text);
+							 "Falls Mehrfachangabe erwünscht, müssen diese durch Kommata getrennt werden (z.B.: /+w2,s0).", text);
 		errorMes  = new CommonTree(new CommonToken(typeERROR, mess));
 		break;
-	case ERR_VAL_NULL:
+	case StatusCodes.ERR_PROX_VAL_NULL:
 		mess      = String.format("Abstandsoperator an der Stelle '%s': Bitte einen numerischen Wert einsetzen (z.B. /+w5)! ", text);
 		errorMes  = new CommonTree(new CommonToken(typeERROR, mess));
 		break;
-	case ERR_VAL_TOOGREAT:
+	case StatusCodes.ERR_PROX_VAL_TOOGREAT:
 		mess      = String.format("Abstandsoperator an der Stelle '%s': Bitte nur 1 numerischen Wert einsetzen (z.B. /+w5)! ", text);
 		errorMes  = new CommonTree(new CommonToken(typeERROR, mess));
 		break;
-	case ERR_DIR_TOOGREAT:
+	case StatusCodes.ERR_PROX_DIR_TOOGREAT:
 		mess      = String.format("Abstandsoperator an der Stelle '%s': Bitte nur 1 Angabe '+' oder '-' oder keine! ", text);
 		errorMes  = new CommonTree(new CommonToken(typeERROR, mess));
 		break;
+	case StatusCodes.ERR_PROX_WRONG_CHARS:
+		mess      = String.format("Abstandsoperator an der Stelle '%s': unbekannte Abstandsoption(en)!", text);
+		errorMes  = new CommonTree(new CommonToken(typeERROR, mess));
+		break;
 	default:
 		mess = String.format("Abstandsoperator an der Stelle '%s': unbekannter Fehler. Korrekte Syntax z.B.: /+w2 oder /w10,s0.", text);
 
@@ -69,12 +72,9 @@
 	
 	errorTree.addChild(errorNode);
 	errorNode.addChild(errorPos);
-	errorNode.addChild(errorArg);
+	errorNode.addChild(errorCode);
 	errorNode.addChild(errorMes);
 
-	// test - 09.01.24/FB
-	//addError("ab");
-	
 	return errorTree;
 	}
 
@@ -83,7 +83,7 @@
 	 * - accepts options in any order.
 	 * - creates CommonTree in that order: Direction .. Distance value .. Measure.
 	 * - sets default direction to BOTH if not set yet.
-	 * - unfortunatly, in ANTLR3 it seems that there is no way inside the Parser Grammar to get 
+	 * - unfortunately, in ANTLR3 it seems that there is no way inside the Parser Grammar to get 
 	 *   the absolute token position from the beginning of the query. Something like $ProxDist.pos or
 	 *   $start.pos is not available, so we have no info in this function about the position at which
 	 *   an error occurs. 
@@ -103,17 +103,18 @@
 		CommonTree tree2 = (CommonTree)ctMeas;
 		CommonTree tree3 = (CommonTree)ctVal;
 		
-		System.err.printf("Debug: encodeDIST: scanned input='%s' countM=%d countD=%d countV=%d pos=%d.\n", 
+		if( bDebug )
+			System.err.printf("Debug: encodeDIST: scanned input='%s' countM=%d countD=%d countV=%d pos=%d.\n", 
 					text, countM, countD, countV, pos);
 
 		if( countM == 0 )
-			return buildErrorTree(text, ERR_MEAS_NULL, typeDIST, pos);
+			return buildErrorTree(text, StatusCodes.ERR_PROX_MEAS_NULL, typeDIST, pos);
 		if( countM > 1 )
-			return buildErrorTree(text, ERR_MEAS_TOOGREAT, typeDIST, pos);
+			return buildErrorTree(text, StatusCodes.ERR_PROX_MEAS_TOOGREAT, typeDIST, pos);
 		if( countV == 0 )
-			return buildErrorTree(text, ERR_VAL_NULL, typeDIST, pos);
+			return buildErrorTree(text, StatusCodes.ERR_PROX_VAL_NULL, typeDIST, pos);
 		if( countV > 1 )
-			return buildErrorTree(text, ERR_VAL_TOOGREAT, typeDIST, pos);
+			return buildErrorTree(text, StatusCodes.ERR_PROX_VAL_TOOGREAT, typeDIST, pos);
 		
 		if( countD == 0 )
 			{
@@ -122,13 +123,13 @@
 			CommonTree treeBOTH = new CommonTree(new CommonToken(typeDIR, "BOTH"));
 			treeDIR.addChild(treeBOTH);
 			
-			System.err.printf("Debug: encodeDIST: tree for DIR: '%s'.\n", 
-					treeDIR.toStringTree());
+			if( bDebug )
+				System.err.printf("Debug: encodeDIST: tree for DIR: '%s'.\n", treeDIR.toStringTree());
 			tree1 = treeDIR;
 			}
 		else if( countD > 1 )
-			return buildErrorTree(text, ERR_DIR_TOOGREAT, typeDIST, pos);
-		
+			return buildErrorTree(text, StatusCodes.ERR_PROX_DIR_TOOGREAT, typeDIST, pos);
+	
 		// create DIST tree:
 		CommonTree 
 			tree = new CommonTree(new CommonToken(typeDIST, "DIST"));
@@ -137,18 +138,29 @@
 		tree.addChild(tree3); // tree3 before tree2 expected by serialization.
 		tree.addChild(tree2);
 		
-		System.err.printf("Debug: encodeDIST: returning '%s'.\n", tree.toStringTree());
+		if( bDebug )
+			System.err.printf("Debug: encodeDIST: returning '%s'.\n", tree.toStringTree());
 		
 		return tree;
 	} // encodeDIST
 	
-	public static boolean checkDIST(String input)
+	/* checkRemain:
+	 * 
+	 * - the chars in proxRemain are not allowed in prox. options.
+	 * - return an error tree.
+	 * 12.01.24/FB
+	 */
+	
+	public static Object checkRemain(int typeDIST, String proxRemain, int pos)
 	
 	{
-		return true;
+		if( bDebug )
+			System.out.printf("Debug: checkRemain: '%s' at pos %d.\n", proxRemain, pos);
+		
+		return buildErrorTree(proxRemain, StatusCodes.ERR_PROX_WRONG_CHARS, typeDIST, pos);
 	}
 	
-	public static Tree check (String input, int pos) 
+	public static Tree check (String input, int pos) throws RecognitionException
 	{
         ANTLRStringStream ss = new ANTLRStringStream(input);
         c2ps_opPROXLexer lex = new c2ps_opPROXLexer(ss);
@@ -156,10 +168,8 @@
         c2ps_opPROXParser g = new c2ps_opPROXParser(tokens);
         c2ps_opPROXParser.opPROX_return c2PQReturn = null;
 
-        /**/
-        System.out.printf("check opPROX: pos=%d input='%s'.\n", pos, input);
-        System.out.flush();
-        /**/
+        if( bDebug )
+        	System.out.printf("check opPROX: pos=%d input='%s'.\n", pos, input);
 
         try {
             c2PQReturn = g.opPROX(pos);
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java
index 47eb907..285a3e7 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/Cosmas2QueryProcessor.java
@@ -1,5 +1,6 @@
 package de.ids_mannheim.korap.query.serialize;
 
+import de.ids_mannheim.korap.query.parse.cosmas.c2ps_opPROX; // error codes.
 import de.ids_mannheim.korap.query.object.ClassRefCheck;
 import de.ids_mannheim.korap.query.object.ClassRefOp;
 import de.ids_mannheim.korap.query.object.CosmasPosition;
@@ -45,7 +46,7 @@
  */
 public class Cosmas2QueryProcessor extends Antlr3AbstractQueryProcessor {
 
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
 
     private static Logger log =
             LoggerFactory.getLogger(Cosmas2QueryProcessor.class);
@@ -133,32 +134,59 @@
     public static Pattern wildcardQuestionPattern = Pattern.compile("([?])");
 
 	/**
-	 * searchforError
+	 * reportErrorsinTree:
+	 * - traverse the AST tree and search for nodes of type ERROR, they contain
+	 *   the errCode, the error message and the error char position.
 	 * - returns true if an error node is found in the tree referenced by 'node'.
-	 * - adds the corresponding error message to the error list.
+	 * - adds error code, error position and error message to the error list.
+	 * Arguments:
+	 * node		: might be null if it has been reseted previously by another error handler.
 	 * @param node
 	 * @return: true: error node was found,
 	 * 			false; no error node found.
 	 * 19.12.23/FB
 	 */
     
-    private boolean searchforError(Tree node)
+    private boolean reportErrorsinTree(Tree node)
     
     {
-    	//System.err.printf("Debug: searchforError: '%s' has %d children.\n",
-    	//		node.toStringTree(), node.getChildCount());
+    	final String func = "reportErrorsinTree";
+    	
+    	//System.err.printf("Debug: %s: '%s' has %d children.\n",
+    	//		func, node.getText(), node.getChildCount());
+    	if( node == null )
+    		{
+    		// System.err.printf("Warning: %s: node == null: no action requested.\n", func);
+    		return false;
+    		}
     	
     	if( node.getType() == 1 && node.getText().compareTo("ERROR") == 0 )
 	    	{
 	    	// error node found:
-    		//System.err.printf("Debug: searchforError: error node found: %s.\n", node.toStringTree());
-    		String
-    			message = String.format("Fehler %s gefunden bei '%s': %s.",
-    					node.getChild(0) != null ? node.getChild(0).getText() : "",
-    	    			node.getChild(1) != null ? node.getChild(1).getText() : "",
-    	    			node.getChild(2) != null ? node.getChild(2).getText() : "");
+    		// child[0] : error pos.
+    		// child[1] : error code. 
+    		// child[2] : error message, containing offending string.
+    		/*
+    		System.err.printf("Debug: %s: child[0]='%s' child[1]='%s' child[2]='%s'.\n", func,
+    					node.getChild(0) != null ? node.getChild(0).getText() : "???",
+    	    			node.getChild(1) != null ? node.getChild(1).getText() : "???",
+    	    			node.getChild(2) != null ? node.getChild(2).getText() : "???");
+    		*/
     		
-    		addError(345, message);
+    		int
+    			errPos  = node.getChild(0) != null ? Integer.parseInt(node.getChild(0).getText()) : 0;
+    		int
+    			errCode = node.getChild(1) != null ? Integer.parseInt(node.getChild(1).getText()) : StatusCodes.ERR_PROX_UNKNOWN; 
+    		String
+    			errMess = node.getChild(2) != null ? node.getChild(2).getText() : "Genaue Fehlermeldung nicht auffindbar.";
+    		
+			ArrayList<Object> 
+				errorSpecs = new ArrayList<Object>();
+			
+	        errorSpecs.add(errCode);
+	        errorSpecs.add(errMess);
+	        errorSpecs.add(errPos);
+    		addError(errorSpecs);
     		return true;
 	    	}
     	
@@ -173,14 +201,14 @@
     				son.getTokenStartIndex(),
     				son.getTokenStopIndex());
     		*/
-
-    		if( searchforError(son) )
+    		// return the first error found only:
+    		if( reportErrorsinTree(son) )
     			return true; // error found, stop here.
 	    	}
     	
     	// no error node:
     	return false;
-    }
+    } // reportErrorsinTree
 
     /**
      * @param tree
@@ -201,7 +229,7 @@
 	        	// query from requestMap is unformatted JSON. Make it pretty before displaying:
 	        	ObjectMapper mapper = new ObjectMapper();
 	        	String jsonQuery = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(requestMap.get("query"));
-				System.out.printf("Cosmas2QueryProcessor: JSON output: %s\n\n", jsonQuery);
+				System.out.printf("Cosmas2QueryProcessor: JSON output:\n%s\n\n", jsonQuery);
 				} 
 	        catch (JsonProcessingException e) 
 	        	{
@@ -790,14 +818,7 @@
         Tree typ = prox_opts.getChild(0);
         Tree dist_list = prox_opts.getChild(1);
     	
-    	// search for an error and if there is one, add it to the list:
-  	    if( searchforError(prox_opts) )
-			{
-        	return;
-	    	}
-
-        
-        // Step I: create group
+    	// Step I: create group
         Map<String, Object> group =
                 KoralObjectGenerator.makeGroup(KoralOperation.SEQUENCE);
 
@@ -1828,30 +1849,35 @@
             // Use custom error reporters
             lex.setErrorReporter(errorListener);
             ((c2psParser) parser).setErrorReporter(errorListener);
-            
+
             c2psParser.c2ps_query_return c2Return =
                     ((c2psParser) parser).c2ps_query(); // statt t().
 
             // AST Tree anzeigen:
             tree = (Tree) c2Return.getTree();
-            if (DEBUG) log.debug(tree.toStringTree());
+
+            if (DEBUG) 
+            	{
+            	System.out.printf("Debug: parseCosmasQuery: tree = '%s'.\n", tree.toStringTree());
+            	log.debug(tree.toStringTree());
+            	}
             }
         catch (FailedPredicateException fe)
-	        {
+	        { // unused so far - 11.01.24/FB
         	System.out.printf("parseCosmasQuery: FailedPredicateException!\n");
             addError(StatusCodes.MALFORMED_QUERY,
                     "failed predicate on prox something.");
 	        }
         catch (RecognitionException e) {
-            System.out.printf("parseCosmasQuery: RecognitionException!\n");
-        	log.error(
+        	// unused so far - 11.01.24/FB
+        	System.out.printf("Debug: out: parseCosmasQuery: RecognitionException!\n");
+            log.error(
                     "Could not parse query. Please make sure it is well-formed.");
             addError(StatusCodes.MALFORMED_QUERY,
                     "Could not parse query. Please make sure it is well-formed.");
         }
 
         String treestring = tree.toStringTree();
-        System.err.printf("Debug: parseCosmasQuery: tree = '%s'.\n",  treestring);
         
         boolean erroneous = false;
         if (parser.failed() || parser.getNumberOfSyntaxErrors() > 0) {
@@ -1859,21 +1885,30 @@
             tree = null;
         }
 
-        System.err.printf("Debug: parseCosmasQuery: failed=%b no. of synt. err = %d.\n",
-        			parser.failed(), parser.getNumberOfSyntaxErrors());
-        
         if (erroneous || treestring.contains("<mismatched token")
                 || treestring.contains("<error")
                 || treestring.contains("<unexpected")) 
         {
-        	System.err.printf("Debug: parseCosmasQuery: tree: '%s'.\n", treestring);
-        	System.err.printf("Debug: parseCosmasQuery: FullErrorMsg:  '%s'.\n", errorListener.generateFullErrorMsg().toString());
+        	//System.err.printf("Debug: parseCosmasQuery: tree: '%s'.\n", treestring);
+        	//System.err.printf("Debug: parseCosmasQuery: FullErrorMsg:  '%s'.\n", errorListener.generateFullErrorMsg().toString());
         	log.error(errorListener.generateFullErrorMsg().toString());
             addError(errorListener.generateFullErrorMsg());
         }
-        
-        addError(1234, "Test-Message");
-        
+
+        // collect and report errors found by other functions than the lexer/parser:
+        // tree might already be null if another error was reported above.
+        if( reportErrorsinTree(tree) == true )
+        {
+        	if( DEBUG )
+        		System.out.printf("Debug: parseCosmasQuery: reportErrorsinTree at least 1 error message found. Setting tree = null.\n");
+            return null;
+        }
+        else
+        	{
+        	if(DEBUG)
+        		System.out.printf("Debug: parseCosmasQuery: reportErrorsinTree has found no error messages.\n");
+        	}
+    	
         return tree;
-    }
+    } // parseCosmasQuery
 }
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 ce7802f..edc527e 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
@@ -105,7 +105,8 @@
         int i = 0;
         String[] queries = null;
         String ql = "poliqarpplus";
-        boolean bDebug = false;
+        boolean 
+        	bDebug = false;
 
         if (args.length < 2) {
             System.err.println("\nUsage: QuerySerializer \"query\" queryLanguage [-show]");
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java b/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java
index 656228d..b8c0765 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java
@@ -14,4 +14,13 @@
 	public final static int QUERY_TOO_COMPLEX = 311;
 	public final static int UNKNOWN_QUERY_ERROR = 399;
 	public final static int SERIALIZATION_FAILED = 300;
+	
+	// error codes for PROX syntax errors:
+	final public static int ERR_PROX_UNKNOWN 		= 320;
+	public final static int ERR_PROX_MEAS_NULL 		= 321;
+	public final static int ERR_PROX_MEAS_TOOGREAT 	= 322;
+	public final static int ERR_PROX_VAL_NULL 		= 323;
+	public final static int ERR_PROX_VAL_TOOGREAT 	= 324;
+	public final static int ERR_PROX_DIR_TOOGREAT 	= 325;
+	public final static int ERR_PROX_WRONG_CHARS	= 326;
 }
\ No newline at end of file