Index: QueryParser.jj
===================================================================
RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/queryParser/QueryParser.jj,v
retrieving revision 1.22
diff -u -r1.22 QueryParser.jj
--- QueryParser.jj	7 Nov 2002 05:55:40 -0000	1.22
+++ QueryParser.jj	18 Nov 2002 19:22:05 -0000
@@ -68,6 +68,7 @@
 import java.text.*;
 import java.util.*;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.index.WildcardTerm;
 import org.apache.lucene.analysis.*;
 import org.apache.lucene.document.*;
 import org.apache.lucene.search.*;
@@ -291,6 +292,26 @@
                           inclusive);
   }
 
+    private void analyzeToken(Vector v, String term) {
+        org.apache.lucene.analysis.Token t;
+        TokenStream source;
+        //put term through analyzer
+        source = analyzer.tokenStream(field, new StringReader(term));
+        while (true) {
+            try {
+                t = source.next();
+            }
+            catch (IOException e) {
+                t = null;
+            }
+            if (t == null) {
+                break;
+            }
+            //found valid term add to Vector
+            v.add(new Term(field,t.termText()));
+        }
+    }
+
   public static void main(String[] args) throws Exception {
     QueryParser qp = new QueryParser("field",
                            new org.apache.lucene.analysis.SimpleAnalyzer());
@@ -324,7 +345,7 @@
 | <#_WHITESPACE: ( " " | "\t" ) >
 }
 
-<DEFAULT, RangeIn, RangeEx> SKIP : {
+<DEFAULT, Phrase, RangeIn, RangeEx> SKIP : {
   <<_WHITESPACE>>
 }
 
@@ -347,7 +368,7 @@
 | <RPAREN:    ")" >
 | <COLON:     ":" >
 | <CARAT:     "^" > : Boost
-| <QUOTED:     "\"" (~["\""])+ "\"">
+| <QUOTE:     "\"" > : Phrase
 | <TERM:      <_TERM_START_CHAR> (<_TERM_CHAR>)*  >
 | <FUZZY:     "~" >
 | <SLOP:      "~" (<_NUM_CHAR>)+ >
@@ -358,6 +379,12 @@
 | <RANGEEX_START: "{" > : RangeEx
 }
 
+<Phrase> TOKEN :{
+<PHRASE_TERM: <_TERM_START_CHAR> (<_TERM_CHAR>)* >
+|<PHRASE_WILDTERM: <_TERM_START_CHAR> (<_TERM_CHAR> | ( [ "*", "?" ] ))* >
+|<END_QUOTE: "\"" > : DEFAULT
+}
+
 <Boost> TOKEN : {
 <NUMBER:    (<_NUM_CHAR>)+ ( "." (<_NUM_CHAR>)+ )? > : DEFAULT
 }
@@ -504,16 +531,48 @@
 
           q = getRangeQuery(field, analyzer, goop1.image, goop2.image, false);
         }
-     | term=<QUOTED>
+     | <QUOTE> { 
+                //retrieved quote
+                Vector phraseVector = new Vector();
+            }
+        ( term=<PHRASE_TERM> { 
+                //put term through analyzer
+                analyzeToken(phraseVector,term.image);
+            }
+        | term=<PHRASE_WILDTERM> { 
+                //found wildcard term, do not put through analyzer
+                phraseVector.add(new WildcardTerm(field,term.image));
+            }
+        )* <END_QUOTE> {
+            //look through phraseVector
+            if (phraseVector.isEmpty()) {
+                q = null;
+            } else if (phraseVector.size()==1) {
+                //optimize one term case
+                Object o = phraseVector.firstElement();
+                if (o instanceof WildcardTerm) {
+                    //one term wildcard = WildcardQuery
+                    q=new WildcardQuery((Term)o);
+                } else if (o instanceof Term) {
+                    q=new TermQuery((Term)o);
+                } else {
+                    q=null; //should never happen
+                }
+            } else {
+                q = new PhrasePrefixQuery();
+                for (Iterator i=phraseVector.iterator();i.hasNext();) {
+                    Object o = i.next();
+                    ((PhrasePrefixQuery)q).add( (Term)o );
+                }
+            }
+        }
        [ slop=<SLOP> ]
        [ <CARAT> boost=<NUMBER> ]
        {
-         q = getFieldQuery(field, analyzer,
-                           term.image.substring(1, term.image.length()-1));
-         if (slop != null && q instanceof PhraseQuery) {
+         if (slop != null && q instanceof PhrasePrefixQuery) {
            try {
              int s = Float.valueOf(slop.image.substring(1)).intValue();
-             ((PhraseQuery) q).setSlop(s);
+             ((PhrasePrefixQuery) q).setSlop(s);
            }
            catch (Exception ignored) { }
          }
