Index: src/test/org/apache/lucene/queryParser/TestMultiFieldQueryParser.java =================================================================== --- src/test/org/apache/lucene/queryParser/TestMultiFieldQueryParser.java (revision 469990) +++ src/test/org/apache/lucene/queryParser/TestMultiFieldQueryParser.java (working copy) @@ -54,7 +54,7 @@ q = mfqp.parse("+one +two"); assertEquals("+(b:one t:one) +(b:two t:two)", q.toString()); - q = mfqp.parse("+one -two -three)"); + q = mfqp.parse("+one -two -three"); assertEquals("+(b:one t:one) -(b:two t:two) -(b:three t:three)", q.toString()); q = mfqp.parse("one^2 two"); Index: src/test/org/apache/lucene/queryParser/TestQueryParser.java =================================================================== --- src/test/org/apache/lucene/queryParser/TestQueryParser.java (revision 469990) +++ src/test/org/apache/lucene/queryParser/TestQueryParser.java (working copy) @@ -573,14 +573,24 @@ assertEquals(1.0f, q.getBoost(), 0.01f); } - public void testException() throws Exception { + public void assertParseException(String queryString) throws Exception { try { - assertQueryEquals("\"some phrase", null, "abc"); - fail("ParseException expected, not thrown"); + Query q = getQuery(queryString, null); } catch (ParseException expected) { + return; } + fail("ParseException expected, not thrown"); } + public void testException() throws Exception { + assertParseException("\"some phrase"); + assertParseException("(foo bar"); + assertParseException("foo bar))"); + assertParseException("field:term:with:colon some more terms"); + assertParseException("(sub query)^5.0^2.0 plus more"); + assertParseException("secret AND illegal) AND access:confidential"); + } + public void testCustomQueryParserWildcard() { try { new QPTestParser("contents", new WhitespaceAnalyzer()).parse("a?t"); Index: src/java/org/apache/lucene/queryParser/QueryParser.java =================================================================== --- src/java/org/apache/lucene/queryParser/QueryParser.java (revision 469990) +++ src/java/org/apache/lucene/queryParser/QueryParser.java (working copy) @@ -120,7 +120,8 @@ public Query parse(String query) throws ParseException { ReInit(new FastCharStream(new StringReader(query))); try { - return Query(field); + // TopLevelQuery is a Query followed by the end-of-input (EOF) + return TopLevelQuery(field); } catch (ParseException tme) { // rethrow to include the original query: @@ -701,6 +702,15 @@ throw new Error("Missing return statement in function"); } +// This makes sure that there is no garbage after the query string + final public Query TopLevelQuery(String field) throws ParseException { + Query q; + q = Query(field); + jj_consume_token(0); + {if (true) return q;} + throw new Error("Missing return statement in function"); + } + final public Query Query(String field) throws ParseException { Vector clauses = new Vector(); Query q, firstQuery=null; Index: src/java/org/apache/lucene/queryParser/QueryParser.jj =================================================================== --- src/java/org/apache/lucene/queryParser/QueryParser.jj (revision 469990) +++ src/java/org/apache/lucene/queryParser/QueryParser.jj (working copy) @@ -143,7 +143,8 @@ public Query parse(String query) throws ParseException { ReInit(new FastCharStream(new StringReader(query))); try { - return Query(field); + // TopLevelQuery is a Query followed by the end-of-input (EOF) + return TopLevelQuery(field); } catch (ParseException tme) { // rethrow to include the original query: @@ -747,6 +748,18 @@ { return ret; } } +// This makes sure that there is no garbage after the query string +Query TopLevelQuery(String field) : +{ + Query q; +} +{ + q=Query(field) + { + return q; + } +} + Query Query(String field) : { Vector clauses = new Vector();