Fix handling of apostrophes in VC multiword & regex values (fixes #85)

Change-Id: I42b8e60ac1caae31b7ddf4122f9ad76cd99a702f
diff --git a/Changes b/Changes
index 51adfa2..b11c8de 100644
--- a/Changes
+++ b/Changes
@@ -1,6 +1,8 @@
-0.37 2020-11-19
+0.37 2020-12-02
     - [feature] Introduced query references in Poliqarp (diewald)
     - [bugfix] Ignore empty corpus queries (diewald)
+    - [bugfix] Fix handling of apostrophes in multiword and regex
+      values in virtual corpora (#85; diewald)
 
 0.36 2020-07-24
     - [security] Upgraded version of Google Guava
diff --git a/src/main/antlr/collection/CollectionQueryLexer.g4 b/src/main/antlr/collection/CollectionQueryLexer.g4
index 80dc91c..a829b39 100644
--- a/src/main/antlr/collection/CollectionQueryLexer.g4
+++ b/src/main/antlr/collection/CollectionQueryLexer.g4
@@ -66,5 +66,5 @@
 WORD				: ALPHABET+;
 //WORD                : ALPHABET* ALPHA ALPHABET*;  // needs to have at least one alphabetical letter (non-numeric)
 
-REGEX     		    : SLASH ~['/']*? (BACKSLASH SLASH ~['/']*?)* SLASH;
-MULTIWORD   		    : QUOTE ~['"']*? (BACKSLASH QUOTE ~['"']*?)* QUOTE; 
+REGEX     		    : SLASH ~[/]*? (BACKSLASH SLASH ~[/]*?)* SLASH;
+MULTIWORD   		    : QUOTE ~["]*? (BACKSLASH QUOTE ~["]*?)* QUOTE; 
diff --git a/src/test/java/de/ids_mannheim/korap/query/test/collection/CollectionQueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/test/collection/CollectionQueryProcessorTest.java
index 5f97e40..aa5ae40 100644
--- a/src/test/java/de/ids_mannheim/korap/query/test/collection/CollectionQueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/test/collection/CollectionQueryProcessorTest.java
@@ -215,6 +215,17 @@
         assertEquals("corenlp/morpho", res.at("/collection/operands/1/value").asText());
     }
 
+    @Test
+    public void testVerbatimApo () throws JsonProcessingException, IOException {
+        collection = "corpusTitle=\"C't\"";
+        qs.setQuery(query, ql);
+        qs.setCollection(collection);
+        res = mapper.readTree(qs.toJSON());
+        assertEquals("koral:doc", res.at("/collection/@type").asText());
+        assertEquals("corpusTitle", res.at("/collection/key").asText());
+        assertEquals("C't", res.at("/collection/value").asText());
+        assertEquals("match:eq", res.at("/collection/match").asText());
+    }   
     
     @Test
     public void testFlag () throws JsonProcessingException, IOException {
@@ -288,6 +299,19 @@
     } 
 
 	@Test
+    public void testRegexApos () throws JsonProcessingException, IOException {    
+        collection = "textClass=/po.'litik/";
+        qs.setQuery(query, ql);
+        qs.setCollection(collection);
+        res = mapper.readTree(qs.toJSON());
+        assertEquals("koral:doc", res.at("/collection/@type").asText());
+        assertEquals("textClass", res.at("/collection/key").asText());
+        assertEquals("po.'litik", res.at("/collection/value").asText());
+        assertEquals("type:regex", res.at("/collection/type").asText());
+        assertEquals("match:eq", res.at("/collection/match").asText());
+    } 
+    
+	@Test
     public void testRegexFailure () throws JsonProcessingException, IOException {    
         collection = "textClass=/po/litik/";
         qs.setQuery(query, ql);