Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParser.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParser.java	(revision 1575468)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParser.java	(working copy)
@@ -95,12 +95,19 @@
    *  @param matchVersion  Lucene version to match. See <a href="#version">above</a>.
    *  @param f  the default field for query terms.
    *  @param a   used to find terms in the query text.
+   *  @deprecated use {@link #QueryParser(Version, String, Analyzer, Analyzer)} instead
    */
+   @Deprecated
    public QueryParser(Version matchVersion, String f, Analyzer a) {
     this(new FastCharStream(new StringReader("")));
     init(matchVersion, f, a);
   }
 
+  public QueryParser(Version matchVersion, String f, Analyzer a, Analyzer multitermAnalyzer) {
+    this(new FastCharStream(new StringReader("")));
+    init(matchVersion, f, a, multitermAnalyzer);
+  }
+
 // *   Query  ::= ( Clause )*
 // *   Clause ::= ["+", "-"] [<TERM> ":"] ( <TERM> | "(" Query ")" )
   final public int Conjunction() throws ParseException {
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParser.jj
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParser.jj	(revision 1575468)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParser.jj	(working copy)
@@ -119,11 +119,18 @@
    *  @param matchVersion  Lucene version to match. See <a href="#version">above</a>.
    *  @param f  the default field for query terms.
    *  @param a   used to find terms in the query text.
+   *  @deprecated use {@link #QueryParser(Version, String, Analyzer, Analyzer)} instead
    */
+   @Deprecated
    public QueryParser(Version matchVersion, String f, Analyzer a) {
     this(new FastCharStream(new StringReader("")));
     init(matchVersion, f, a);
   }
+
+   public QueryParser(Version matchVersion, String f, Analyzer a, Analyzer multitermAnalyzer) {
+     this(new FastCharStream(new StringReader("")));
+     init(matchVersion, f, a, multitermAnalyzer);
+   }
 }
 
 PARSER_END(QueryParser)
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParserBase.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParserBase.java	(revision 1575468)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParserBase.java	(working copy)
@@ -71,6 +71,7 @@
   int fuzzyPrefixLength = FuzzyQuery.defaultPrefixLength;
   Locale locale = Locale.getDefault();
   TimeZone timeZone = TimeZone.getDefault();
+  Analyzer multiTermAnalyzer = null;
 
   // the default date resolution
   DateTools.Resolution dateResolution = null;
@@ -92,12 +93,29 @@
    *  @param matchVersion  Lucene version to match.
    *  @param f  the default field for query terms.
    *  @param a   used to find terms in the query text.
+   *  @deprecated use {@link #init(Version, String, Analyzer, Analyzer)} instead
    */
+  @Deprecated
   public void init(Version matchVersion, String f, Analyzer a) {
     setAnalyzer(a);
     field = f;
     setAutoGeneratePhraseQueries(false);
   }
+  
+  /** Initializes a query parser.  Called by the QueryParser constructor
+   *  If {@link #multiTermAnalyzer} is not null, that analyzer will be used
+   *  for analysis of multiterms, and the values of {@link #getAnalyzeRangeTerms()}
+   *  and {@link #getLowercaseExpandedTerms()} will be ignored.
+   *  
+   *  @param matchVersion  Lucene version to match.
+   *  @param f  the default field for query terms.
+   *  @param a   used to find terms in the query text.
+   *  @param multiTermAnalyzer used for multiterms: prefix, wildcard, fuzzy, regex, range
+   */
+  public void init(Version matchVersion, String f, Analyzer a, Analyzer multiTermAnalyzer) {
+    init(matchVersion, f, a);
+    setMultiTermAnalyzer(multiTermAnalyzer);
+  }
 
   // the generated parser will create these in QueryParser
   public abstract void ReInit(CharStream stream);
@@ -237,6 +255,14 @@
   }
 
   /**
+   * Set the analyzer to be used for multiTerms: prefix, wildcard, fuzzy, regex, range
+   * @param multiTermAnalyzer analyzer for multiTerm analysis
+   */
+  public void setMultiTermAnalyzer(Analyzer multiTermAnalyzer) {
+    this.multiTermAnalyzer = multiTermAnalyzer;
+  }
+
+  /**
    * Sets the boolean operator of the QueryParser.
    * In default mode (<code>OR_OPERATOR</code>) terms without any modifiers
    * are considered optional: for example <code>capital of Hungary</code> is equal to
@@ -494,7 +520,7 @@
                                 boolean startInclusive,
                                 boolean endInclusive) throws ParseException
   {
-    if (lowercaseExpandedTerms) {
+    if (multiTermAnalyzer == null && lowercaseExpandedTerms) {
       part1 = part1==null ? null : part1.toLowerCase(locale);
       part2 = part2==null ? null : part2.toLowerCase(locale);
     }
@@ -617,15 +643,27 @@
     if (part1 == null) {
       start = null;
     } else {
-      start = analyzeRangeTerms ? analyzeMultitermTerm(field, part1) : new BytesRef(part1);
+      if (multiTermAnalyzer != null){
+        start = analyzeMultitermTerm(field, part1, multiTermAnalyzer);
+      } else if (getAnalyzeRangeTerms()){
+        start = analyzeMultitermTerm(field, part1, getAnalyzer());
+      } else {
+        start = new BytesRef(part1);
+      }
     }
      
     if (part2 == null) {
       end = null;
     } else {
-      end = analyzeRangeTerms ? analyzeMultitermTerm(field, part2) : new BytesRef(part2);
+      if (multiTermAnalyzer != null){
+        end = analyzeMultitermTerm(field, part2, multiTermAnalyzer);
+      } else if (getAnalyzeRangeTerms()){
+        end = analyzeMultitermTerm(field, part2, getAnalyzer());
+      } else {
+        end = new BytesRef(part2);
+      }
     }
-      
+            
     final TermRangeQuery query = new TermRangeQuery(field, start, end, startInclusive, endInclusive);
 
     query.setRewriteMethod(multiTermRewriteMethod);
@@ -723,9 +761,13 @@
     }
     if (!allowLeadingWildcard && (termStr.startsWith("*") || termStr.startsWith("?")))
       throw new ParseException("'*' or '?' not allowed as first character in WildcardQuery");
-    if (lowercaseExpandedTerms) {
+
+    if (multiTermAnalyzer != null) {
+      termStr = analyzeMultitermTerm(field, termStr, multiTermAnalyzer).utf8ToString();
+    } else if (lowercaseExpandedTerms) {
       termStr = termStr.toLowerCase(locale);
     }
+
     Term t = new Term(field, termStr);
     return newWildcardQuery(t);
   }
@@ -752,9 +794,12 @@
    */
   protected Query getRegexpQuery(String field, String termStr) throws ParseException
   {
-    if (lowercaseExpandedTerms) {
+    if (multiTermAnalyzer != null) {
+      termStr = analyzeMultitermTerm(field, termStr, multiTermAnalyzer).utf8ToString();
+    } else if (lowercaseExpandedTerms) {
       termStr = termStr.toLowerCase(locale);
     }
+
     Term t = new Term(field, termStr);
     return newRegexpQuery(t);
   }
@@ -786,9 +831,13 @@
   {
     if (!allowLeadingWildcard && termStr.startsWith("*"))
       throw new ParseException("'*' not allowed as first character in PrefixQuery");
-    if (lowercaseExpandedTerms) {
+    
+    if (multiTermAnalyzer != null) {
+      termStr = analyzeMultitermTerm(field, termStr, multiTermAnalyzer).utf8ToString();
+    } else if (lowercaseExpandedTerms) {
       termStr = termStr.toLowerCase(locale);
     }
+
     Term t = new Term(field, termStr);
     return newPrefixQuery(t);
   }
@@ -806,7 +855,9 @@
    */
   protected Query getFuzzyQuery(String field, String termStr, float minSimilarity) throws ParseException
   {
-    if (lowercaseExpandedTerms) {
+    if (multiTermAnalyzer != null) {
+      termStr = analyzeMultitermTerm(field, termStr, multiTermAnalyzer).utf8ToString();
+    } else if (lowercaseExpandedTerms) {
       termStr = termStr.toLowerCase(locale);
     }
     Term t = new Term(field, termStr);
