Index: lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java	(revision 1563195)
+++ lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java	(working copy)
@@ -58,7 +58,12 @@
   /** Sets the phrase slop for this query.
    * @see PhraseQuery#setSlop(int)
    */
-  public void setSlop(int s) { slop = s; }
+  public void setSlop(int s) {
+    if (s < 0) {
+      throw new IllegalArgumentException("slop value cannot be negative");
+    }
+    slop = s; 
+  }
 
   /** Sets the phrase slop for this query.
    * @see PhraseQuery#getSlop()
Index: lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java	(revision 1563195)
+++ lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java	(working copy)
@@ -68,7 +68,12 @@
     results are sorted by exactness.
 
     <p>The slop is zero by default, requiring exact matches.*/
-  public void setSlop(int s) { slop = s; }
+  public void setSlop(int s) {
+    if (s < 0) {
+      throw new IllegalArgumentException("slop value cannot be negative");
+    }
+    slop = s; 
+  }
   /** Returns the slop.  See setSlop(). */
   public int getSlop() { return slop; }
 
Index: lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java	(revision 1563195)
+++ lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java	(working copy)
@@ -568,4 +568,16 @@
     return terms;
   }
   
+  public void testNegativeSlop() throws Exception {
+    MultiPhraseQuery query = new MultiPhraseQuery();
+    query.add(new Term("field", "two"));
+    query.add(new Term("field", "one"));
+    try {
+      query.setSlop(-2);
+      fail("didn't get expected exception");
+    } catch (IllegalArgumentException expected) {
+      // expected exception
+    }
+  }
+  
 }
Index: lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java	(revision 1563195)
+++ lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java	(working copy)
@@ -678,4 +678,16 @@
     reader.close();
     dir.close();
   }
+  
+  public void testNegativeSlop() throws Exception {
+    PhraseQuery query = new PhraseQuery();
+    query.add(new Term("field", "two"));
+    query.add(new Term("field", "one"));
+    try {
+      query.setSlop(-2);
+      fail("didn't get expected exception");
+    } catch (IllegalArgumentException expected) {
+      // expected exception
+    }
+  }
 }
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/simple/SimpleQueryParser.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/simple/SimpleQueryParser.java	(revision 1563195)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/simple/SimpleQueryParser.java	(working copy)
@@ -21,10 +21,12 @@
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.FuzzyQuery;
 import org.apache.lucene.search.MatchAllDocsQuery;
 import org.apache.lucene.search.PrefixQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.util.QueryBuilder;
+import org.apache.lucene.util.automaton.LevenshteinAutomata;
 
 import java.util.Collections;
 import java.util.Map;
@@ -48,6 +50,8 @@
  *  <li>'{@code -}' negates a single token: <tt>-token0</tt>
  *  <li>'{@code "}' creates phrases of terms: <tt>"term1 term2 ..."</tt>
  *  <li>'{@code *}' at the end of terms specifies prefix query: <tt>term*</tt>
+ *  <li>'{@code ~}N' at the end of terms specifies fuzzy query: <tt>term~1</tt>
+ *  <li>'{@code ~}N' at the end of phrases specifies near query: <tt>"term1 term2"~5</tt>
  *  <li>'{@code (}' and '{@code )}' specifies precedence: <tt>token1 + (token2 | token3)</tt>
  * </ul>
  * <p>
@@ -111,7 +115,12 @@
   public static final int ESCAPE_OPERATOR      = 1<<6;
   /** Enables {@code WHITESPACE} operators: ' ' '\n' '\r' '\t' */
   public static final int WHITESPACE_OPERATOR  = 1<<7;
+  /** Enables {@code FUZZY} operators: (~) on single terms */
+  public static final int FUZZY_OPERATOR       = 1<<8;
+  /** Enables {@code NEAR} operators: (~) on phrases */
+  public static final int NEAR_OPERATOR        = 1<<9;
 
+
   private BooleanClause.Occur defaultOperator = BooleanClause.Occur.SHOULD;
 
   /** Creates a new parser searching over a single field. */
@@ -266,6 +275,7 @@
     int start = ++state.index;
     int copied = 0;
     boolean escaped = false;
+    boolean hasSlop = false;
 
     while (state.index < state.length) {
       if (!escaped) {
@@ -279,10 +289,23 @@
 
           continue;
         } else if (state.data[state.index] == '"') {
-          // this should be the end of the phrase
-          // all characters found will used for
-          // creating the phrase query
-          break;
+          // if there are still characters after the closing ", check for a
+          // tilde
+          if (state.length > (state.index + 1) &&
+              state.data[state.index+1] == '~' &&
+              (flags & NEAR_OPERATOR) != 0) {
+            state.index++;
+            // check for characters after the tilde
+            if (state.length > (state.index + 1)) {
+              hasSlop = true;
+            }
+            break;
+          } else {
+            // this should be the end of the phrase
+            // all characters found will used for
+            // creating the phrase query
+            break;
+          }
         }
       }
 
@@ -305,7 +328,12 @@
       // a complete phrase has been found and is parsed through
       // through the analyzer from the given field
       String phrase = new String(state.buffer, 0, copied);
-      Query branch = newPhraseQuery(phrase);
+      Query branch;
+      if (hasSlop) {
+        branch = newPhraseQuery(phrase, parseFuzziness(state));
+      } else {
+        branch = newPhraseQuery(phrase, 0);
+      }
       buildQueryTree(state, branch);
 
       ++state.index;
@@ -316,6 +344,7 @@
     int copied = 0;
     boolean escaped = false;
     boolean prefix = false;
+    boolean fuzzy = false;
 
     while (state.index < state.length) {
       if (!escaped) {
@@ -329,19 +358,14 @@
           ++state.index;
 
           continue;
-        } else if ((state.data[state.index] == '"' && (flags & PHRASE_OPERATOR) != 0)
-            || (state.data[state.index] == '|' && (flags & OR_OPERATOR) != 0)
-            || (state.data[state.index] == '+' && (flags & AND_OPERATOR) != 0)
-            || (state.data[state.index] == '(' && (flags & PRECEDENCE_OPERATORS) != 0)
-            || (state.data[state.index] == ')' && (flags & PRECEDENCE_OPERATORS) != 0)
-            || ((state.data[state.index] == ' '
-            || state.data[state.index] == '\t'
-            || state.data[state.index] == '\n'
-            || state.data[state.index] == '\r') && (flags & WHITESPACE_OPERATOR) != 0)) {
+        } else if (tokenFinished(state)) {
           // this should be the end of the term
           // all characters found will used for
           // creating the term query
           break;
+        } else if (copied > 0 && state.data[state.index] == '~' && (flags & FUZZY_OPERATOR) != 0) {
+          fuzzy = true;
+          break;
         }
 
         // wildcard tracks whether or not the last character
@@ -358,7 +382,17 @@
     if (copied > 0) {
       final Query branch;
 
-      if (prefix) {
+      if (fuzzy && (flags & FUZZY_OPERATOR) != 0) {
+        String token = new String(state.buffer, 0, copied);
+        int fuzziness = parseFuzziness(state);
+        // edit distance has a maximum, limit to the maximum supported
+        fuzziness = Math.min(fuzziness, LevenshteinAutomata.MAXIMUM_SUPPORTED_DISTANCE);
+        if (fuzziness == 0) {
+          branch = newDefaultQuery(token);
+        } else {
+          branch = newFuzzyQuery(token, fuzziness);
+        }
+      } else if (prefix) {
         // if a term is found with a closing '*' it is considered to be a prefix query
         // and will have prefix added as an option
         String token = new String(state.buffer, 0, copied - 1);
@@ -421,6 +455,60 @@
   }
 
   /**
+   * Helper parsing fuzziness from parsing state
+   * @return slop/edit distance, 0 in the case of non-parsing slop/edit string
+   */
+  private int parseFuzziness(State state) {
+    char slopText[] = new char[state.length];
+    int slopLength = 0;
+
+    if (state.data[state.index] == '~') {
+      while (state.index < state.length) {
+        state.index++;
+        // it's possible that the ~ was at the end, so check after incrementing
+        // to make sure we don't go out of bounds
+        if (state.index < state.length) {
+          if (tokenFinished(state)) {
+            break;
+          }
+          slopText[slopLength] = state.data[state.index];
+          slopLength++;
+        }
+      }
+      int fuzziness = 0;
+      try {
+        fuzziness = Integer.parseInt(new String(slopText, 0, slopLength));
+      } catch (NumberFormatException e) {
+        // swallow number format exceptions parsing fuzziness
+      }
+      // negative -> 0
+      if (fuzziness < 0) {
+        fuzziness = 0;
+      }
+      return fuzziness;
+    }
+    return 0;
+  }
+
+  /**
+   * Helper returning true if the state has reached the end of token.
+   */
+  private boolean tokenFinished(State state) {
+    if ((state.data[state.index] == '"' && (flags & PHRASE_OPERATOR) != 0)
+        || (state.data[state.index] == '|' && (flags & OR_OPERATOR) != 0)
+        || (state.data[state.index] == '+' && (flags & AND_OPERATOR) != 0)
+        || (state.data[state.index] == '(' && (flags & PRECEDENCE_OPERATORS) != 0)
+        || (state.data[state.index] == ')' && (flags & PRECEDENCE_OPERATORS) != 0)
+        || ((state.data[state.index] == ' '
+        || state.data[state.index] == '\t'
+        || state.data[state.index] == '\n'
+        || state.data[state.index] == '\r') && (flags & WHITESPACE_OPERATOR) != 0)) {
+      return true;
+    }
+    return false;
+  }
+
+  /**
    * Factory method to generate a standard query (no phrase or prefix operators).
    */
   protected Query newDefaultQuery(String text) {
@@ -436,12 +524,12 @@
   }
 
   /**
-   * Factory method to generate a phrase query.
+   * Factory method to generate a fuzzy query.
    */
-  protected Query newPhraseQuery(String text) {
+  protected Query newFuzzyQuery(String text, int fuzziness) {
     BooleanQuery bq = new BooleanQuery(true);
     for (Map.Entry<String,Float> entry : weights.entrySet()) {
-      Query q = createPhraseQuery(entry.getKey(), text);
+      Query q = new FuzzyQuery(new Term(entry.getKey(), text), fuzziness);
       if (q != null) {
         q.setBoost(entry.getValue());
         bq.add(q, BooleanClause.Occur.SHOULD);
@@ -451,6 +539,21 @@
   }
 
   /**
+   * Factory method to generate a phrase query with slop.
+   */
+  protected Query newPhraseQuery(String text, int slop) {
+    BooleanQuery bq = new BooleanQuery(true);
+    for (Map.Entry<String,Float> entry : weights.entrySet()) {
+      Query q = createPhraseQuery(entry.getKey(), text, slop);
+      if (q != null) {
+        q.setBoost(entry.getValue());
+        bq.add(q, BooleanClause.Occur.SHOULD);
+      }
+    }
+    return simplify(bq);
+  }
+
+  /**
    * Factory method to generate a prefix query.
    */
   protected Query newPrefixQuery(String text) {
Index: lucene/queryparser/src/test/org/apache/lucene/queryparser/simple/TestSimpleQueryParser.java
===================================================================
--- lucene/queryparser/src/test/org/apache/lucene/queryparser/simple/TestSimpleQueryParser.java	(revision 1563195)
+++ lucene/queryparser/src/test/org/apache/lucene/queryparser/simple/TestSimpleQueryParser.java	(working copy)
@@ -27,6 +27,7 @@
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.FuzzyQuery;
 import org.apache.lucene.search.MatchAllDocsQuery;
 import org.apache.lucene.search.PhraseQuery;
 import org.apache.lucene.search.PrefixQuery;
@@ -34,14 +35,17 @@
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util._TestUtil;
+import org.apache.lucene.util.automaton.LevenshteinAutomata;
 
 import static org.apache.lucene.queryparser.simple.SimpleQueryParser.AND_OPERATOR;
 import static org.apache.lucene.queryparser.simple.SimpleQueryParser.ESCAPE_OPERATOR;
+import static org.apache.lucene.queryparser.simple.SimpleQueryParser.FUZZY_OPERATOR;
 import static org.apache.lucene.queryparser.simple.SimpleQueryParser.NOT_OPERATOR;
 import static org.apache.lucene.queryparser.simple.SimpleQueryParser.OR_OPERATOR;
 import static org.apache.lucene.queryparser.simple.SimpleQueryParser.PHRASE_OPERATOR;
 import static org.apache.lucene.queryparser.simple.SimpleQueryParser.PRECEDENCE_OPERATORS;
 import static org.apache.lucene.queryparser.simple.SimpleQueryParser.PREFIX_OPERATOR;
+import static org.apache.lucene.queryparser.simple.SimpleQueryParser.NEAR_OPERATOR;
 import static org.apache.lucene.queryparser.simple.SimpleQueryParser.WHITESPACE_OPERATOR;
 
 /** Tests for {@link SimpleQueryParser} */
@@ -58,6 +62,18 @@
     return parser.parse(text);
   }
 
+  /**
+   * helper to parse a query with whitespace+lowercase analyzer across "field",
+   * with default operator of MUST
+   */
+  private Query parse(String text, int flags) {
+    Analyzer analyzer = new MockAnalyzer(random());
+    SimpleQueryParser parser = new SimpleQueryParser(analyzer,
+        Collections.singletonMap("field", 1f), flags);
+    parser.setDefaultOperator(Occur.MUST);
+    return parser.parse(text);
+  }
+
   /** test a simple term */
   public void testTerm() throws Exception {
     Query expected = new TermQuery(new Term("field", "foobar"));
@@ -65,6 +81,24 @@
     assertEquals(expected, parse("foobar"));
   }
 
+  /** test a fuzzy query */
+  public void testFuzzy() throws Exception {
+    Query regular = new TermQuery(new Term("field", "foobar"));
+    Query expected = new FuzzyQuery(new Term("field", "foobar"), 2);
+
+    assertEquals(expected, parse("foobar~2"));
+    assertEquals(regular, parse("foobar~"));
+    assertEquals(regular, parse("foobar~a"));
+    assertEquals(regular, parse("foobar~1a"));
+
+    BooleanQuery bool = new BooleanQuery();
+    FuzzyQuery fuzzy = new FuzzyQuery(new Term("field", "foo"), LevenshteinAutomata.MAXIMUM_SUPPORTED_DISTANCE);
+    bool.add(fuzzy, Occur.MUST);
+    bool.add(new TermQuery(new Term("field", "bar")), Occur.MUST);
+
+    assertEquals(bool, parse("foo~" + LevenshteinAutomata.MAXIMUM_SUPPORTED_DISTANCE + 1 + " bar"));
+  }
+
   /** test a simple phrase */
   public void testPhrase() throws Exception {
     PhraseQuery expected = new PhraseQuery();
@@ -74,6 +108,43 @@
     assertEquals(expected, parse("\"foo bar\""));
   }
 
+  /** test a simple phrase with various slop settings */
+  public void testPhraseWithSlop() throws Exception {
+    PhraseQuery expectedWithSlop = new PhraseQuery();
+    expectedWithSlop.add(new Term("field", "foo"));
+    expectedWithSlop.add(new Term("field", "bar"));
+    expectedWithSlop.setSlop(2);
+
+    assertEquals(expectedWithSlop, parse("\"foo bar\"~2"));
+
+    PhraseQuery expectedWithMultiDigitSlop = new PhraseQuery();
+    expectedWithMultiDigitSlop.add(new Term("field", "foo"));
+    expectedWithMultiDigitSlop.add(new Term("field", "bar"));
+    expectedWithMultiDigitSlop.setSlop(10);
+
+    assertEquals(expectedWithMultiDigitSlop, parse("\"foo bar\"~10"));
+
+    PhraseQuery expectedNoSlop = new PhraseQuery();
+    expectedNoSlop.add(new Term("field", "foo"));
+    expectedNoSlop.add(new Term("field", "bar"));
+
+    assertEquals("Ignore trailing tilde with no slop", expectedNoSlop, parse("\"foo bar\"~"));
+    assertEquals("Ignore non-numeric trailing slop", expectedNoSlop, parse("\"foo bar\"~a"));
+    assertEquals("Ignore non-numeric trailing slop", expectedNoSlop, parse("\"foo bar\"~1a"));
+    assertEquals("Ignore negative trailing slop", expectedNoSlop, parse("\"foo bar\"~-1"));
+
+    PhraseQuery pq = new PhraseQuery();
+    pq.add(new Term("field", "foo"));
+    pq.add(new Term("field", "bar"));
+    pq.setSlop(12);
+
+    BooleanQuery expectedBoolean = new BooleanQuery();
+    expectedBoolean.add(pq, Occur.MUST);
+    expectedBoolean.add(new TermQuery(new Term("field", "baz")), Occur.MUST);
+
+    assertEquals(expectedBoolean, parse("\"foo bar\"~12 baz"));
+  }
+
   /** test a simple prefix */
   public void testPrefix() throws Exception {
     PrefixQuery expected = new PrefixQuery(new Term("field", "foobar"));
@@ -533,17 +604,33 @@
     assertEquals(expected, parseKeyword("\t\tfoo foo foo", ~WHITESPACE_OPERATOR));
   }
 
+  public void testDisableFuzziness() {
+    Query expected = new TermQuery(new Term("field", "foo~1"));
+    assertEquals(expected, parseKeyword("foo~1", ~FUZZY_OPERATOR));
+  }
+
+  public void testDisableSlop() {
+    PhraseQuery expectedPhrase = new PhraseQuery();
+    expectedPhrase.add(new Term("field", "foo"));
+    expectedPhrase.add(new Term("field", "bar"));
+
+    BooleanQuery expected = new BooleanQuery();
+    expected.add(expectedPhrase, Occur.MUST);
+    expected.add(new TermQuery(new Term("field", "~2")), Occur.MUST);
+    assertEquals(expected, parse("\"foo bar\"~2", ~NEAR_OPERATOR));
+  }
+
   // we aren't supposed to barf on any input...
   public void testRandomQueries() throws Exception {
     for (int i = 0; i < 1000; i++) {
       String query = _TestUtil.randomUnicodeString(random());
       parse(query); // no exception
-      parseKeyword(query, _TestUtil.nextInt(random(), 0, 256)); // no exception
+      parseKeyword(query, _TestUtil.nextInt(random(), 0, 1024)); // no exception
     }
   }
 
   public void testRandomQueries2() throws Exception {
-    char chars[] = new char[] { 'a', '1', '|', '&', ' ', '(', ')', '"', '-' };
+    char chars[] = new char[] { 'a', '1', '|', '&', ' ', '(', ')', '"', '-', '~'};
     StringBuilder sb = new StringBuilder();
     for (int i = 0; i < 1000; i++) {
       sb.setLength(0);
@@ -552,7 +639,7 @@
         sb.append(chars[random().nextInt(chars.length)]);
       }
       parse(sb.toString()); // no exception
-      parseKeyword(sb.toString(), _TestUtil.nextInt(random(), 0, 256)); // no exception
+      parseKeyword(sb.toString(), _TestUtil.nextInt(random(), 0, 1024)); // no exception
     }
   }
 }
\ No newline at end of file
Index: solr/core/src/java/org/apache/solr/search/SimpleQParserPlugin.java
===================================================================
--- solr/core/src/java/org/apache/solr/search/SimpleQParserPlugin.java	(revision 1563195)
+++ solr/core/src/java/org/apache/solr/search/SimpleQParserPlugin.java	(working copy)
@@ -18,11 +18,9 @@
  */
 
 import org.apache.lucene.analysis.Analyzer;
-import org.apache.lucene.index.Term;
 import org.apache.lucene.queryparser.simple.SimpleQueryParser;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.PrefixQuery;
 import org.apache.lucene.search.Query;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.SimpleParams;
@@ -73,36 +71,21 @@
   /** The name that can be used to specify this plugin should be used to parse the query. */
   public static String NAME = "simple";
 
-  /** Enables {@code AND} operator (+) */
-  private static final String AND_OPERATOR         = "AND";
-  /** Enables {@code NOT} operator (-) */
-  private static final String NOT_OPERATOR         = "NOT";
-  /** Enables {@code OR} operator (|) */
-  private static final String OR_OPERATOR          = "OR";
-  /** Enables {@code PREFIX} operator (*) */
-  private static final String PREFIX_OPERATOR      = "PREFIX";
-  /** Enables {@code PHRASE} operator (") */
-  private static final String PHRASE_OPERATOR      = "PHRASE";
-  /** Enables {@code PRECEDENCE} operators: {@code (} and {@code )} */
-  private static final String PRECEDENCE_OPERATORS = "PRECEDENCE";
-  /** Enables {@code ESCAPE} operator (\) */
-  private static final String ESCAPE_OPERATOR      = "ESCAPE";
-  /** Enables {@code WHITESPACE} operators: ' ' '\n' '\r' '\t' */
-  private static final String WHITESPACE_OPERATOR  = "WHITESPACE";
-
   /** Map of string operators to their int counterparts in SimpleQueryParser. */
   private static final Map<String, Integer> OPERATORS = new HashMap<String, Integer>();
 
   /* Setup the map of possible operators. */
   static {
-    OPERATORS.put(AND_OPERATOR,         SimpleQueryParser.AND_OPERATOR);
-    OPERATORS.put(NOT_OPERATOR,         SimpleQueryParser.NOT_OPERATOR);
-    OPERATORS.put(OR_OPERATOR,          SimpleQueryParser.OR_OPERATOR);
-    OPERATORS.put(PREFIX_OPERATOR,      SimpleQueryParser.PREFIX_OPERATOR);
-    OPERATORS.put(PHRASE_OPERATOR,      SimpleQueryParser.PHRASE_OPERATOR);
-    OPERATORS.put(PRECEDENCE_OPERATORS, SimpleQueryParser.PRECEDENCE_OPERATORS);
-    OPERATORS.put(ESCAPE_OPERATOR,      SimpleQueryParser.ESCAPE_OPERATOR);
-    OPERATORS.put(WHITESPACE_OPERATOR,  SimpleQueryParser.WHITESPACE_OPERATOR);
+    OPERATORS.put(SimpleParams.AND_OPERATOR,         SimpleQueryParser.AND_OPERATOR);
+    OPERATORS.put(SimpleParams.NOT_OPERATOR,         SimpleQueryParser.NOT_OPERATOR);
+    OPERATORS.put(SimpleParams.OR_OPERATOR,          SimpleQueryParser.OR_OPERATOR);
+    OPERATORS.put(SimpleParams.PREFIX_OPERATOR,      SimpleQueryParser.PREFIX_OPERATOR);
+    OPERATORS.put(SimpleParams.PHRASE_OPERATOR,      SimpleQueryParser.PHRASE_OPERATOR);
+    OPERATORS.put(SimpleParams.PRECEDENCE_OPERATORS, SimpleQueryParser.PRECEDENCE_OPERATORS);
+    OPERATORS.put(SimpleParams.ESCAPE_OPERATOR,      SimpleQueryParser.ESCAPE_OPERATOR);
+    OPERATORS.put(SimpleParams.WHITESPACE_OPERATOR,  SimpleQueryParser.WHITESPACE_OPERATOR);
+    OPERATORS.put(SimpleParams.FUZZY_OPERATOR,       SimpleQueryParser.FUZZY_OPERATOR);
+    OPERATORS.put(SimpleParams.NEAR_OPERATOR,        SimpleQueryParser.NEAR_OPERATOR);
   }
 
   /** No initialization is necessary so this method is empty. */
Index: solr/solrj/src/java/org/apache/solr/common/params/SimpleParams.java
===================================================================
--- solr/solrj/src/java/org/apache/solr/common/params/SimpleParams.java	(revision 1563195)
+++ solr/solrj/src/java/org/apache/solr/common/params/SimpleParams.java	(working copy)
@@ -26,4 +26,25 @@
 
   /** Override the currently enabled/disabled query operators. */
   public static String QO = "q.operators";
+  
+  /** Enables {@code AND} operator (+) */
+  public static final String AND_OPERATOR         = "AND";
+  /** Enables {@code NOT} operator (-) */
+  public static final String NOT_OPERATOR         = "NOT";
+  /** Enables {@code OR} operator (|) */
+  public static final String OR_OPERATOR          = "OR";
+  /** Enables {@code PREFIX} operator (*) */
+  public static final String PREFIX_OPERATOR      = "PREFIX";
+  /** Enables {@code PHRASE} operator (") */
+  public static final String PHRASE_OPERATOR      = "PHRASE";
+  /** Enables {@code PRECEDENCE} operators: {@code (} and {@code )} */
+  public static final String PRECEDENCE_OPERATORS = "PRECEDENCE";
+  /** Enables {@code ESCAPE} operator (\) */
+  public static final String ESCAPE_OPERATOR      = "ESCAPE";
+  /** Enables {@code WHITESPACE} operators: ' ' '\n' '\r' '\t' */
+  public static final String WHITESPACE_OPERATOR  = "WHITESPACE";
+  /** Enables {@code FUZZY} operator (~) */
+  public static final String FUZZY_OPERATOR       = "FUZZY";
+  /** Enables {@code NEAR} operator (~) */
+  public static final String NEAR_OPERATOR        = "NEAR";
 }
