Merge remote-tracking branch 'origin/master' into fcs-ql-branch
diff --git a/.gitignore b/.gitignore
index 4e86098..8e98dc1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,14 @@
 
 # /
+/target
+/.settings
 /.project
 /.classpath
-/.settings
-/target
+*~
+.*
+!.gitignore
+
+/src/main/resources
 
 # /src/main/antlr/cosmas/
 /src/main/antlr/cosmas/c2ps_regex.g
diff --git a/Changes b/Changes
index 1a233bd..8c6defd 100644
--- a/Changes
+++ b/Changes
@@ -1,8 +1,10 @@
-0.22 2016-06-03
+0.22 2016-06-15
         - Spans now always wrap terms (diewald)
 	- Cosmas-II "und", "oder", and "nicht" operations
 	  now serialize to unordered sequences (diewald)
 	- Cleanup POM (diewald)
+	- Fix deserialization of unnecessary brackets
+	  around terms in Poliqarp (diewald)
 
 0.21 2015-10-27
         - Improved meta query builder (hanl)
diff --git a/src/main/antlr/poliqarpplus/PoliqarpPlusLexer.g4 b/src/main/antlr/poliqarpplus/PoliqarpPlusLexer.g4
index 68c0bef..8648d87 100644
--- a/src/main/antlr/poliqarpplus/PoliqarpPlusLexer.g4
+++ b/src/main/antlr/poliqarpplus/PoliqarpPlusLexer.g4
@@ -100,4 +100,4 @@
 fragment RE_dquote            : '"'  (RE_expr | '\'' | ':' )* '"';
 fragment RE_squote            : '\''  (RE_expr | '\"' | ':' )* '\'';
  
-REGEX             : ( RE_dquote | RE_squote | );
+REGEX             : ( RE_dquote | RE_squote );
diff --git a/src/main/antlr/poliqarpplus/PoliqarpPlusParser.g4 b/src/main/antlr/poliqarpplus/PoliqarpPlusParser.g4
index c48a3f9..f1f9110 100644
--- a/src/main/antlr/poliqarpplus/PoliqarpPlusParser.g4
+++ b/src/main/antlr/poliqarpplus/PoliqarpPlusParser.g4
@@ -57,14 +57,13 @@
 ;
 
 value
-: WORD 
-| NUMBER
-| regex
+: (WORD | NUMBER) | regex
 ;
  
 /* Fields */
 term       
-: NEG* (foundry SLASH)? layer termOp key (COLON value)? flag? 
+: NEG* (foundry SLASH)? layer termOp key (COLON value)? flag?
+| LRPAREN term RRPAREN
 ;
 
 termOp
@@ -125,8 +124,7 @@
 ;
 
 span
-: LT ((foundry SLASH)? layer termOp)? key NEG* (LRPAREN term RRPAREN|LRPAREN termGroup RRPAREN)? GT
-| LT ((foundry SLASH)? layer termOp)? key NEG* (term|termGroup)? GT
+: LT ((foundry SLASH)? layer termOp)? key NEG* ((LRPAREN term RRPAREN|LRPAREN termGroup RRPAREN)? | (term|termGroup)?) GT
 ;
 
 position
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
index 03117dd..8eb859d 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessor.java
@@ -769,8 +769,16 @@
     @SuppressWarnings("unchecked")
     private LinkedHashMap<String, Object> parseTermOrTermGroup (ParseTree node,
             boolean negatedGlobal, String mode) {
+
         String nodeCat = getNodeCat(node);
+
         if (nodeCat.equals("term")) {
+
+            // Term is defined recursive with non-necessary brackets
+            if (getNodeCat(node.getChild(0)).equals("(")) {
+                return parseTermOrTermGroup(node.getChild(1), negatedGlobal, mode);
+            };
+
             String key = null;
             LinkedHashMap<String, Object> term = KoralObjectGenerator
                     .makeTerm();
diff --git a/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java b/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java
index fd939b3..d7bddfa 100644
--- a/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java
+++ b/src/test/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusQueryProcessorTest.java
@@ -280,7 +280,7 @@
 
         query = "<\".*\">";
         qs.setQuery(query, "poliqarpplus");
-        res = mapper.readTree(qs.toJSON());
+       res = mapper.readTree(qs.toJSON());
         assertEquals("koral:span", res.at("/query/@type").asText());
         assertEquals(".*", res.at("/query/wrap/key").asText());
         assertEquals("type:regex", res.at("/query/wrap/type").asText());
@@ -994,6 +994,26 @@
                 .asText());
     }
 
+    @Test
+    public void testUnnecessaryParentheses () throws JsonProcessingException,
+            IOException {
+        query = "[(base=Mann)]";
+        qs.setQuery(query, "poliqarpplus");
+        res = mapper.readTree(qs.toJSON());
+        assertEquals("koral:token", res.at("/query/@type").asText());
+        assertEquals("Mann", res.at("/query/wrap/key").asText());
+        assertEquals("lemma", res.at("/query/wrap/layer").asText());
+        assertEquals("match:eq", res.at("/query/wrap/match").asText());
+
+        query = "[(((base=Mann)))]";
+        qs.setQuery(query, "poliqarpplus");
+        res = mapper.readTree(qs.toJSON());
+        assertEquals("koral:token", res.at("/query/@type").asText());
+        assertEquals("Mann", res.at("/query/wrap/key").asText());
+        assertEquals("lemma", res.at("/query/wrap/layer").asText());
+        assertEquals("match:eq", res.at("/query/wrap/match").asText());
+
+    };
 
     @Test
     public void testTokenSequence () throws JsonProcessingException,