Issue #160: bad handling of the ',' in #BED(searchexpr,options) corrected.

Change-Id: I159d252a25b6b2e526cea4d0d2d834258848d9b9
diff --git a/src/main/antlr/cosmas/c2ps.g b/src/main/antlr/cosmas/c2ps.g
index 8908a49..2a63bb7 100644
--- a/src/main/antlr/cosmas/c2ps.g
+++ b/src/main/antlr/cosmas/c2ps.g
@@ -9,6 +9,12 @@
 //
 //  v0.7 - 25.07.23/FB
 //    - added: #REG(x)
+//  v0.8 - 06.11.23/FB
+//    - accepts #BED(searchword, sa) : comma attached to searchword.
+//    - more generally: comma at end of searchword, which is not enclosed by "..." is
+//      excluded from searchword now.
+//    - a comma inside a searchword is accepted if enclosed by "...".
+//
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
 grammar c2ps;
@@ -124,8 +130,23 @@
 	:	'&' SEARCHWORD1 ; // rewrite rules funktionieren im lexer nicht: -> ^(OPLEM $SEARCHWORD1.text); 
 
 // SEARCHWORD2: schluckt Blanks. Diese müssen nachträglich als Wortdelimiter erkannt werden.
+
+// current syntax, drawback is:
+// e.g. aber, -> SEARCHWORD1 = "aber,"
+// but correct should be -> SEARCHWORD1 = "aber"  
+//SEARCHWORD1
+//	:	~('"' | ' ' | '#' | ')' | '(' )+ ;
+
+// new syntax (06.11.23/FB):
+// accept for searchword1 either a single ',' or exclude trailing ',' from searchword1:
+// E.g. Haus, -> searchword1=Haus.
+// For a ',' inside a search word, see searchword2. 
+// exclude trailing "," from searchword1.
 SEARCHWORD1
-	:	~('"' | ' ' | '#' | ')' | '(' )+ ;
+	:	(',' | ~('"' | ' ' | '#' | ')' | '(' | ',')+)  ;
+
+// searchword2 accepts a ',' inside a searchword enclosed by "...".
+// E.g. "Haus,tür": OK.
 
 SEARCHWORD2
 	:	'"' (~('"') | '\\"')+ '"' ;
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 8bbfa35..41704fe 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
@@ -41,7 +41,7 @@
  */
 public class Cosmas2QueryProcessor extends Antlr3AbstractQueryProcessor {
 
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;
 
     private static Logger log =
             LoggerFactory.getLogger(Cosmas2QueryProcessor.class);
@@ -483,7 +483,7 @@
         boolean
         	bDebug = false;
         
-        if( DEBUG )
+        if( bDebug )
         	{
         	//System.out.printf("Debug: processOPREG: node='%s' nChilds=%d.\n", node.toStringTree(), nChild+1);
             System.out.printf("Debug: processOPREG: child: >>%s<< cat=%s type=%d.\n",
@@ -646,7 +646,8 @@
         // Map<String, Object> posgroup =
         // makePosition(null);
         boolean isExclusion = isExclusion(node);
-
+        boolean bDebug = false;
+        
         int focusClassCounter = classCounter;
         Map<String, Object> posGroup;
         
@@ -660,7 +661,7 @@
         }
         else {
             posGroup = KoralObjectGenerator.makeGroup(KoralOperation.POSITION);
-            if (DEBUG) log.debug(posGroup.toString());
+            if (bDebug) log.debug(posGroup.toString());
         }
 
         Map<String, Object> positionOptions;
@@ -1607,7 +1608,9 @@
     private void putIntoSuperObject (Map<String, Object> object, int objStackPosition) 
     
     	{
-    	if( DEBUG )
+    	boolean bDebug = false;
+    	
+    	if( bDebug )
 	    	{
 	    	System.out.printf("Debug: putIntosuperObject(<>,int): objectStack.size=%d objStackPos=%d object=%s.\n", 
 	    				objectStack.size(), objStackPosition, object == null ? "null" : "not null");
@@ -1625,7 +1628,7 @@
             ArrayList<Object> topObjectOperands =
                     (ArrayList<Object>) objectStack.get(objStackPosition).get("operands");
             
-            if( DEBUG )
+            if( bDebug )
             	System.out.printf("Debug: putIntosuperObject: topObjectOperands = [%s].\n", topObjectOperands == null ? "null" : "not null");
             
             objectStack.get(objStackPosition);
diff --git a/src/test/java/de/ids_mannheim/korap/test/cosmas2/Cosmas2QueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/test/cosmas2/Cosmas2QueryProcessorTest.java
index 759810f..e3d1ea8 100644
--- a/src/test/java/de/ids_mannheim/korap/test/cosmas2/Cosmas2QueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/test/cosmas2/Cosmas2QueryProcessorTest.java
@@ -5,6 +5,7 @@
 
 import org.junit.Test;
 
+import com.fasterxml.jackson.core.JsonPointer;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -1197,7 +1198,9 @@
 
     }
 
-
+    /* some tests added - 08.11.23/FB
+     */
+    
     @Test
     public void testOPBED () throws JsonProcessingException, IOException {
         query = "#BED(der , sa)";
@@ -1227,6 +1230,95 @@
         assertEquals("s", res.at("/query/operands/0/operands/0/wrap/key")
                 .asText());
 
+        // 08.11.23/FB
+        // treats now "der," as "der" + ",":
+        query = "#BED(der, sa)";
+        qs.setQuery(query, "cosmas2");
+        res = mapper.readTree(qs.toJSON());
+        assertEquals("koral:reference", res.at("/query/@type").asText());
+        assertEquals("operation:focus", res.at("/query/operation").asText());
+        assertEquals(129, res.at("/query/classRef/0").asInt());
+        assertEquals("koral:group", res.at("/query/operands/0/@type").asText());
+        assertEquals("operation:position", res
+                .at("/query/operands/0/operation").asText());
+        assertEquals("frames:startsWith", res.at("/query/operands/0/frames/0")
+                .asText());
+        assertEquals("koral:group", res.at("/query/operands/0/@type").asText());
+        assertEquals("operation:class",
+                res.at("/query/operands/0/operands/1/operation").asText());
+        assertEquals(129, res.at("/query/operands/0/operands/1/classOut")
+                .asInt());
+        assertEquals("koral:token",
+                res.at("/query/operands/0/operands/1/operands/0/@type")
+                        .asText());
+        assertEquals("der",
+                res.at("/query/operands/0/operands/1/operands/0/wrap/key")
+                        .asText());
+        assertEquals("koral:span", res.at("/query/operands/0/operands/0/@type")
+                .asText());
+        assertEquals("s", res.at("/query/operands/0/operands/0/wrap/key")
+                .asText());
+        
+        
+        // 08.11.23/FB
+        // treats now "der,sa" as "der" + "," + "sa":
+        query = "#BED(der,sa)";
+        qs.setQuery(query, "cosmas2");
+        res = mapper.readTree(qs.toJSON());
+        assertEquals("koral:reference", res.at("/query/@type").asText());
+        assertEquals("operation:focus", res.at("/query/operation").asText());
+        assertEquals(129, res.at("/query/classRef/0").asInt());
+        assertEquals("koral:group", res.at("/query/operands/0/@type").asText());
+        assertEquals("operation:position", res
+                .at("/query/operands/0/operation").asText());
+        assertEquals("frames:startsWith", res.at("/query/operands/0/frames/0")
+                .asText());
+        assertEquals("koral:group", res.at("/query/operands/0/@type").asText());
+        assertEquals("operation:class",
+                res.at("/query/operands/0/operands/1/operation").asText());
+        assertEquals(129, res.at("/query/operands/0/operands/1/classOut")
+                .asInt());
+        assertEquals("koral:token",
+                res.at("/query/operands/0/operands/1/operands/0/@type")
+                        .asText());
+        assertEquals("der",
+                res.at("/query/operands/0/operands/1/operands/0/wrap/key")
+                        .asText());
+        assertEquals("koral:span", res.at("/query/operands/0/operands/0/@type")
+                .asText());
+        assertEquals("s", res.at("/query/operands/0/operands/0/wrap/key")
+                .asText());
+        
+        // 08.11.23/FB
+        // treats now "der,s0," as "der,s0" unchanged while written inside "...":
+        query = "#BED(\"der,so\", sa)";
+        qs.setQuery(query, "cosmas2");
+        res = mapper.readTree(qs.toJSON());
+        
+        assertEquals("koral:reference", res.at("/query/@type").asText());
+        assertEquals("operation:focus", res.at("/query/operation").asText());
+        assertEquals(129, res.at("/query/classRef/0").asInt());
+        assertEquals("koral:group", res.at("/query/operands/0/@type").asText());
+        assertEquals("operation:position", res
+                .at("/query/operands/0/operation").asText());
+        assertEquals("frames:startsWith", res.at("/query/operands/0/frames/0")
+                .asText());
+        assertEquals("koral:group", res.at("/query/operands/0/@type").asText());
+        assertEquals("operation:class",
+                res.at("/query/operands/0/operands/1/operation").asText());
+        assertEquals(129, res.at("/query/operands/0/operands/1/classOut")
+                .asInt());
+        assertEquals("koral:token",
+                res.at("/query/operands/0/operands/1/operands/0/@type")
+                        .asText());
+        assertEquals("der,so",
+                res.at("/query/operands/0/operands/1/operands/0/wrap/key")
+                        .asText());
+        assertEquals("koral:span", res.at("/query/operands/0/operands/0/@type")
+                .asText());
+        assertEquals("s", res.at("/query/operands/0/operands/0/wrap/key")
+                .asText());
+        
         query = "#COND(der , sa)";
         qs.setQuery(query, "cosmas2");
         res = mapper.readTree(qs.toJSON());
@@ -1925,4 +2017,7 @@
         StringUtils.removeBlanksAtBothSides(sb);
         assertEquals("abc",sb.toString());
     }
+    
+  
+    
 }