Prox: error messages for wrong prox. options.

Change-Id: Iac430c5bba3dfe30606a8079060f4a6c5bdb4781
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 1bf077e..1569d1a 100644
--- a/src/main/antlr/cosmas/c2ps_opPROX.g
+++ b/src/main/antlr/cosmas/c2ps_opPROX.g
@@ -16,7 +16,8 @@
 	  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;}
@@ -33,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
@@ -40,10 +47,14 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
 
-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.
 
@@ -87,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 da3ea4a..c798468 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,6 +15,8 @@
 public class c2ps_opPROX 
 
 {
+	final static boolean bDebug = true;
+	
 	// type of an Error CommonToken:
 	final static int typeERROR = 1; 
 	// Prox error codes defined in StatusCodes.java.
@@ -58,6 +60,10 @@
 		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);
 
@@ -77,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. 
@@ -97,7 +103,8 @@
 		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 )
@@ -116,8 +123,8 @@
 			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 )
@@ -131,15 +138,26 @@
 		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) throws RecognitionException
@@ -150,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 e733f52..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
@@ -46,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);
@@ -156,8 +156,7 @@
     	//		func, node.getText(), node.getChildCount());
     	if( node == null )
     		{
-    		// 
-    		System.err.printf("Warning: %s: node == null: no action requested.\n", func);
+    		// System.err.printf("Warning: %s: node == null: no action requested.\n", func);
     		return false;
     		}
     	
@@ -173,7 +172,7 @@
     	    			node.getChild(1) != null ? node.getChild(1).getText() : "???",
     	    			node.getChild(2) != null ? node.getChild(2).getText() : "???");
     		*/
-    		// TODO: StatusCode.MALFORMED_QUERY etc. einsetzen!
+    		
     		int
     			errPos  = node.getChild(0) != null ? Integer.parseInt(node.getChild(0).getText()) : 0;
     		int
@@ -230,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) 
 	        	{
@@ -1864,13 +1863,14 @@
             	}
             }
         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("Debug: out: parseCosmasQuery: RecognitionException!\n");
+        	// 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,
@@ -1899,11 +1899,15 @@
         // tree might already be null if another error was reported above.
         if( reportErrorsinTree(tree) == true )
         {
-        	System.out.printf("Debug: parseCosmasQuery: reportErrorsinTree at least 1 error message found. Setting tree = null.\n");
+        	if( DEBUG )
+        		System.out.printf("Debug: parseCosmasQuery: reportErrorsinTree at least 1 error message found. Setting tree = null.\n");
             return null;
         }
         else
-        	System.out.printf("Debug: parseCosmasQuery: reportErrorsinTree has found no error messages.\n");
+        	{
+        	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 9dab811..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
@@ -22,4 +22,5 @@
 	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