You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by sy...@apache.org on 2016/09/11 21:30:47 UTC

[16/50] [abbrv] lucenenet git commit: Ported QueryParser.Surround namespace + tests.

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Parser/QueryParserTokenManager.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Parser/QueryParserTokenManager.cs b/Lucene.Net.QueryParser/Surround/Parser/QueryParserTokenManager.cs
new file mode 100644
index 0000000..ac3d611
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Parser/QueryParserTokenManager.cs
@@ -0,0 +1,760 @@
+\ufeffusing System;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+
+namespace Lucene.Net.QueryParser.Surround.Parser
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Token Manager.
+    /// </summary>
+    public class QueryParserTokenManager //: QueryParserConstants
+    {
+        private void InitBlock()
+        {
+            StreamWriter temp_writer;
+            temp_writer = new StreamWriter(Console.OpenStandardOutput(), Console.Out.Encoding);
+            temp_writer.AutoFlush = true;
+            debugStream = temp_writer;
+        }
+
+        /// <summary>Debug output. </summary>
+        public StreamWriter debugStream;
+        /// <summary>Set debug output. </summary>
+        public virtual void SetDebugStream(StreamWriter ds)
+        {
+            debugStream = ds;
+        }
+        private int JjStopStringLiteralDfa_1(int pos, long active0)
+        {
+            switch (pos)
+            {
+                default:
+                    return -1;
+            }
+        }
+        private int JjStartNfa_1(int pos, long active0)
+        {
+            return JjMoveNfa_1(JjStopStringLiteralDfa_1(pos, active0), pos + 1);
+        }
+        private int JjStopAtPos(int pos, int kind)
+        {
+            jjmatchedKind = kind;
+            jjmatchedPos = pos;
+            return pos + 1;
+        }
+        private int jjMoveStringLiteralDfa0_1()
+        {
+            switch (curChar)
+            {
+                case (char)40:
+                    return JjStopAtPos(0, 13);
+                case (char)41:
+                    return JjStopAtPos(0, 14);
+                case (char)44:
+                    return JjStopAtPos(0, 15);
+                case (char)58:
+                    return JjStopAtPos(0, 16);
+                case (char)94:
+                    return JjStopAtPos(0, 17);
+                default:
+                    return JjMoveNfa_1(0, 0);
+            }
+        }
+        internal static readonly ulong[] jjbitVec0 = {
+            0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+        };
+        internal static readonly ulong[] jjbitVec2 = {
+            0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
+        };
+        private int JjMoveNfa_1(int startState, int curPos)
+        {
+            int startsAt = 0;
+            jjnewStateCnt = 38;
+            int i = 1;
+            jjstateSet[0] = startState;
+            int kind = 0x7fffffff;
+            for (; ; )
+            {
+                if (++jjround == 0x7fffffff)
+                    ReInitRounds();
+                if (curChar < 64)
+                {
+                    ulong l = (ulong)(1L << (int)curChar);
+                    do
+                    {
+                        switch (jjstateSet[--i])
+                        {
+                            case 0:
+                                if ((0x7bffe8faffffd9ffL & l) != 0L)
+                                {
+                                    if (kind > 22)
+                                        kind = 22;
+                                    JjCheckNAddStates(0, 4);
+                                }
+                                else if ((0x100002600L & l) != 0L)
+                                {
+                                    if (kind > 7)
+                                        kind = 7;
+                                }
+                                else if (curChar == 34)
+                                    JjCheckNAddStates(5, 7);
+                                if ((0x3fc000000000000L & l) != 0L)
+                                    JjCheckNAddStates(8, 11);
+                                else if (curChar == 49)
+                                    JjCheckNAddTwoStates(20, 21);
+                                break;
+                            case 19:
+                                if ((0x3fc000000000000L & l) != 0L)
+                                    JjCheckNAddStates(8, 11);
+                                break;
+                            case 20:
+                                if ((0x3ff000000000000L & l) != 0L)
+                                    JjCheckNAdd(17);
+                                break;
+                            case 21:
+                                if ((0x3ff000000000000L & l) != 0L)
+                                    JjCheckNAdd(18);
+                                break;
+                            case 22:
+                                if (curChar == 49)
+                                    JjCheckNAddTwoStates(20, 21);
+                                break;
+                            case 23:
+                                if (curChar == 34)
+                                    JjCheckNAddStates(5, 7);
+                                break;
+                            case 24:
+                                if ((0xfffffffbffffffffL & l) != (ulong)0L)
+                                    JjCheckNAddTwoStates(24, 25);
+                                break;
+                            case 25:
+                                if (curChar == 34)
+                                    jjstateSet[jjnewStateCnt++] = 26;
+                                break;
+                            case 26:
+                                if (curChar == 42 && kind > 18)
+                                    kind = 18;
+                                break;
+                            case 27:
+                                if ((0xfffffffbffffffffL & l) != (ulong)0L)
+                                    JjCheckNAddStates(12, 14);
+                                break;
+                            case 29:
+                                if (curChar == 34)
+                                    JjCheckNAddStates(12, 14);
+                                break;
+                            case 30:
+                                if (curChar == 34 && kind > 19)
+                                    kind = 19;
+                                break;
+                            case 31:
+                                if ((0x7bffe8faffffd9ffL & l) == 0L)
+                                    break;
+                                if (kind > 22)
+                                    kind = 22;
+                                JjCheckNAddStates(0, 4);
+                                break;
+                            case 32:
+                                if ((0x7bffe8faffffd9ffL & l) != 0L)
+                                    JjCheckNAddTwoStates(32, 33);
+                                break;
+                            case 33:
+                                if (curChar == 42 && kind > 20)
+                                    kind = 20;
+                                break;
+                            case 34:
+                                if ((0x7bffe8faffffd9ffL & l) != 0L)
+                                    JjCheckNAddTwoStates(34, 35);
+                                break;
+                            case 35:
+                                if ((0x8000040000000000L & l) == (ulong)0L)
+                                    break;
+                                if (kind > 21)
+                                    kind = 21;
+                                JjCheckNAddTwoStates(35, 36);
+                                break;
+                            case 36:
+                                if ((0xfbffecfaffffd9ffL & l) == (ulong)0L)
+                                    break;
+                                if (kind > 21)
+                                    kind = 21;
+                                JjCheckNAdd(36);
+                                break;
+                            case 37:
+                                if ((0x7bffe8faffffd9ffL & l) == 0L)
+                                    break;
+                                if (kind > 22)
+                                    kind = 22;
+                                JjCheckNAdd(37);
+                                break;
+                            default: break;
+                        }
+                    } while (i != startsAt);
+                }
+                else if (curChar < 128)
+                {
+                    // NOTE: See the note in the Classic.QueryParserTokenManager.cs file.
+                    // I am working under the assumption 63 is the correct value, since it
+                    // made the tests pass there.
+                    ulong l = (ulong)(1L << (curChar & 63));
+                    //long l = 1L << (curChar & 077);
+                    do
+                    {
+                        switch (jjstateSet[--i])
+                        {
+                            case 0:
+                                if ((0xffffffffbfffffffL & l) != (ulong)0L)
+                                {
+                                    if (kind > 22)
+                                        kind = 22;
+                                    JjCheckNAddStates(0, 4);
+                                }
+                                if ((0x400000004000L & l) != 0L)
+                                {
+                                    if (kind > 12)
+                                        kind = 12;
+                                }
+                                else if ((0x80000000800000L & l) != 0L)
+                                {
+                                    if (kind > 11)
+                                        kind = 11;
+                                }
+                                else if (curChar == 97)
+                                    jjstateSet[jjnewStateCnt++] = 9;
+                                else if (curChar == 65)
+                                    jjstateSet[jjnewStateCnt++] = 6;
+                                else if (curChar == 111)
+                                    jjstateSet[jjnewStateCnt++] = 3;
+                                else if (curChar == 79)
+                                    jjstateSet[jjnewStateCnt++] = 1;
+                                if (curChar == 110)
+                                    jjstateSet[jjnewStateCnt++] = 15;
+                                else if (curChar == 78)
+                                    jjstateSet[jjnewStateCnt++] = 12;
+                                break;
+                            case 1:
+                                if (curChar == 82 && kind > 8)
+                                    kind = 8;
+                                break;
+                            case 2:
+                                if (curChar == 79)
+                                    jjstateSet[jjnewStateCnt++] = 1;
+                                break;
+                            case 3:
+                                if (curChar == 114 && kind > 8)
+                                    kind = 8;
+                                break;
+                            case 4:
+                                if (curChar == 111)
+                                    jjstateSet[jjnewStateCnt++] = 3;
+                                break;
+                            case 5:
+                                if (curChar == 68 && kind > 9)
+                                    kind = 9;
+                                break;
+                            case 6:
+                                if (curChar == 78)
+                                    jjstateSet[jjnewStateCnt++] = 5;
+                                break;
+                            case 7:
+                                if (curChar == 65)
+                                    jjstateSet[jjnewStateCnt++] = 6;
+                                break;
+                            case 8:
+                                if (curChar == 100 && kind > 9)
+                                    kind = 9;
+                                break;
+                            case 9:
+                                if (curChar == 110)
+                                    jjstateSet[jjnewStateCnt++] = 8;
+                                break;
+                            case 10:
+                                if (curChar == 97)
+                                    jjstateSet[jjnewStateCnt++] = 9;
+                                break;
+                            case 11:
+                                if (curChar == 84 && kind > 10)
+                                    kind = 10;
+                                break;
+                            case 12:
+                                if (curChar == 79)
+                                    jjstateSet[jjnewStateCnt++] = 11;
+                                break;
+                            case 13:
+                                if (curChar == 78)
+                                    jjstateSet[jjnewStateCnt++] = 12;
+                                break;
+                            case 14:
+                                if (curChar == 116 && kind > 10)
+                                    kind = 10;
+                                break;
+                            case 15:
+                                if (curChar == 111)
+                                    jjstateSet[jjnewStateCnt++] = 14;
+                                break;
+                            case 16:
+                                if (curChar == 110)
+                                    jjstateSet[jjnewStateCnt++] = 15;
+                                break;
+                            case 17:
+                                if ((0x80000000800000L & l) != 0L && kind > 11)
+                                    kind = 11;
+                                break;
+                            case 18:
+                                if ((0x400000004000L & l) != 0L && kind > 12)
+                                    kind = 12;
+                                break;
+                            case 24:
+                                JjAddStates(15, 16);
+                                break;
+                            case 27:
+                                if ((0xffffffffefffffffL & l) != (ulong)0L)
+                                    JjCheckNAddStates(12, 14);
+                                break;
+                            case 28:
+                                if (curChar == 92)
+                                    jjstateSet[jjnewStateCnt++] = 29;
+                                break;
+                            case 29:
+                                if (curChar == 92)
+                                    JjCheckNAddStates(12, 14);
+                                break;
+                            case 31:
+                                if ((0xffffffffbfffffffL & l) == (ulong)0L)
+                                    break;
+                                if (kind > 22)
+                                    kind = 22;
+                                JjCheckNAddStates(0, 4);
+                                break;
+                            case 32:
+                                if ((0xffffffffbfffffffL & l) != (ulong)0L)
+                                    JjCheckNAddTwoStates(32, 33);
+                                break;
+                            case 34:
+                                if ((0xffffffffbfffffffL & l) != (ulong)0L)
+                                    JjCheckNAddTwoStates(34, 35);
+                                break;
+                            case 36:
+                                if ((0xffffffffbfffffffL & l) == (ulong)0L)
+                                    break;
+                                if (kind > 21)
+                                    kind = 21;
+                                jjstateSet[jjnewStateCnt++] = 36;
+                                break;
+                            case 37:
+                                if ((0xffffffffbfffffffL & l) == (ulong)0L)
+                                    break;
+                                if (kind > 22)
+                                    kind = 22;
+                                JjCheckNAdd(37);
+                                break;
+                            default: break;
+                        }
+                    } while (i != startsAt);
+                }
+                else
+                {
+                    int hiByte = (int)(curChar >> 8);
+                    int i1 = hiByte >> 6;
+                    //long l1 = 1L << (hiByte & 077);
+                    ulong l1 = (ulong)(1L << (hiByte & 63));
+                    int i2 = (curChar & 0xff) >> 6;
+                    //long l2 = 1L << (curChar & 077);
+                    ulong l2 = (ulong)(1L << (curChar & 63));
+                    do
+                    {
+                        switch (jjstateSet[--i])
+                        {
+                            case 0:
+                                if (!JjCanMove_0(hiByte, i1, i2, l1, l2))
+                                    break;
+                                if (kind > 22)
+                                    kind = 22;
+                                JjCheckNAddStates(0, 4);
+                                break;
+                            case 24:
+                                if (JjCanMove_0(hiByte, i1, i2, l1, l2))
+                                    JjAddStates(15, 16);
+                                break;
+                            case 27:
+                                if (JjCanMove_0(hiByte, i1, i2, l1, l2))
+                                    JjAddStates(12, 14);
+                                break;
+                            case 32:
+                                if (JjCanMove_0(hiByte, i1, i2, l1, l2))
+                                    JjCheckNAddTwoStates(32, 33);
+                                break;
+                            case 34:
+                                if (JjCanMove_0(hiByte, i1, i2, l1, l2))
+                                    JjCheckNAddTwoStates(34, 35);
+                                break;
+                            case 36:
+                                if (!JjCanMove_0(hiByte, i1, i2, l1, l2))
+                                    break;
+                                if (kind > 21)
+                                    kind = 21;
+                                jjstateSet[jjnewStateCnt++] = 36;
+                                break;
+                            case 37:
+                                if (!JjCanMove_0(hiByte, i1, i2, l1, l2))
+                                    break;
+                                if (kind > 22)
+                                    kind = 22;
+                                JjCheckNAdd(37);
+                                break;
+                            default: break;
+                        }
+                    } while (i != startsAt);
+                }
+                if (kind != 0x7fffffff)
+                {
+                    jjmatchedKind = kind;
+                    jjmatchedPos = curPos;
+                    kind = 0x7fffffff;
+                }
+                ++curPos;
+                if ((i = jjnewStateCnt) == (startsAt = 38 - (jjnewStateCnt = startsAt)))
+                    return curPos;
+                try { curChar = input_stream.ReadChar(); }
+                catch (System.IO.IOException e) { return curPos; }
+            }
+        }
+
+        private int JjMoveStringLiteralDfa0_0()
+        {
+            return JjMoveNfa_0(0, 0);
+        }
+        private int JjMoveNfa_0(int startState, int curPos)
+        {
+            int startsAt = 0;
+            jjnewStateCnt = 3;
+            int i = 1;
+            jjstateSet[0] = startState;
+            int kind = 0x7fffffff;
+            for (; ; )
+            {
+                if (++jjround == 0x7fffffff)
+                    ReInitRounds();
+                if (curChar < 64)
+                {
+                    long l = 1L << curChar;
+                    do
+                    {
+                        switch (jjstateSet[--i])
+                        {
+                            case 0:
+                                if ((0x3ff000000000000L & l) == 0L)
+                                    break;
+                                if (kind > 23)
+                                    kind = 23;
+                                JjAddStates(17, 18);
+                                break;
+                            case 1:
+                                if (curChar == 46)
+                                    JjCheckNAdd(2);
+                                break;
+                            case 2:
+                                if ((0x3ff000000000000L & l) == 0L)
+                                    break;
+                                if (kind > 23)
+                                    kind = 23;
+                                JjCheckNAdd(2);
+                                break;
+                            default: break;
+                        }
+                    } while (i != startsAt);
+                }
+                else if (curChar < 128)
+                {
+                    //long l = 1L << (curChar & 077);
+                    ulong l = (ulong)(1L << (curChar & 63)); 
+                    do
+                    {
+                        switch (jjstateSet[--i])
+                        {
+                            default: break;
+                        }
+                    } while (i != startsAt);
+                }
+                else
+                {
+                    int hiByte = (int)(curChar >> 8);
+                    int i1 = hiByte >> 6;
+                    //long l1 = 1L << (hiByte & 077);
+                    ulong l1 = (ulong)(1L << (hiByte & 63));
+                    int i2 = (curChar & 0xff) >> 6;
+                    //long l2 = 1L << (curChar & 077);
+                    ulong l2 = (ulong)(1L << (curChar & 63));
+                    do
+                    {
+                        switch (jjstateSet[--i])
+                        {
+                            default: break;
+                        }
+                    } while (i != startsAt);
+                }
+                if (kind != 0x7fffffff)
+                {
+                    jjmatchedKind = kind;
+                    jjmatchedPos = curPos;
+                    kind = 0x7fffffff;
+                }
+                ++curPos;
+                if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
+                    return curPos;
+                try { curChar = input_stream.ReadChar(); }
+                catch (System.IO.IOException e) { return curPos; }
+            }
+        }
+        internal static readonly int[] jjnextStates = {
+            32, 33, 34, 35, 37, 24, 27, 28, 20, 17, 21, 18, 27, 28, 30, 24, 
+            25, 0, 1, 
+        };
+        private static bool JjCanMove_0(int hiByte, int i1, int i2, ulong l1, ulong l2)
+        {
+            switch (hiByte)
+            {
+                case 0:
+                    return ((jjbitVec2[i2] & l2) != 0L);
+                default:
+                    if ((jjbitVec0[i1] & l1) != 0L)
+                        return true;
+                    return false;
+            }
+        }
+
+        /** Token literal values. */
+        //public static readonly string[] jjstrLiteralImages = {
+        //    "", null, null, null, null, null, null, null, null, null, null, null, null, 
+        //    "\50", "\51", "\54", "\72", "\136", null, null, null, null, null, null 
+        //};
+
+        public static readonly string[] jjstrLiteralImages = {
+            "", null, null, null, null, null, null, null, null, null, null, null, null, 
+            "\x0028" /*"\50"*/, "\x0029" /*"\51"*/, "\x002C" /*"\54"*/, "\x003A" /*"\72"*/, "\x005E" /*"\136"*/, null, null, null, null, null, null 
+        };
+
+        /** Lexer state names. */
+        public static readonly string[] lexStateNames = {
+           "Boost",
+           "DEFAULT"
+        };
+
+        /** Lex State array. */
+        public static readonly int[] jjnewLexState = {
+           -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, 1, 
+        };
+        internal static readonly long[] jjtoToken = {
+           0xffff01L, 
+        };
+        internal static readonly long[] jjtoSkip = {
+           0x80L, 
+        };
+        protected ICharStream input_stream;
+        private readonly uint[] jjrounds = new uint[38];
+        private readonly int[] jjstateSet = new int[76];
+        protected internal char curChar;
+
+        /** Constructor. */
+        public QueryParserTokenManager(ICharStream stream)
+        {
+            InitBlock();
+            input_stream = stream;
+        }
+
+        /** Constructor. */
+        public QueryParserTokenManager(ICharStream stream, int lexState)
+            : this(stream)
+        {
+            SwitchTo(lexState);
+        }
+
+        /** Reinitialise parser. */
+        public void ReInit(ICharStream stream)
+        {
+            jjmatchedPos = jjnewStateCnt = 0;
+            curLexState = defaultLexState;
+            input_stream = stream;
+            ReInitRounds();
+        }
+        private void ReInitRounds()
+        {
+            int i;
+            jjround = 0x80000001;
+            for (i = 38; i-- > 0; )
+                jjrounds[i] = 0x80000000;
+        }
+
+        /** Reinitialise parser. */
+        public void ReInit(ICharStream stream, int lexState)
+        {
+            ReInit(stream);
+            SwitchTo(lexState);
+        }
+
+        /** Switch to specified lex state. */
+        public void SwitchTo(int lexState)
+        {
+            if (lexState >= 2 || lexState < 0)
+                throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+            else
+                curLexState = lexState;
+        }
+
+        protected Token JjFillToken()
+        {
+            Token t;
+            string curTokenImage;
+            int beginLine;
+            int endLine;
+            int beginColumn;
+            int endColumn;
+            string im = jjstrLiteralImages[jjmatchedKind];
+            curTokenImage = (im == null) ? input_stream.Image : im;
+            beginLine = input_stream.BeginLine;
+            beginColumn = input_stream.BeginColumn;
+            endLine = input_stream.EndLine;
+            endColumn = input_stream.EndColumn;
+            t = Token.NewToken(jjmatchedKind, curTokenImage);
+
+            t.beginLine = beginLine;
+            t.endLine = endLine;
+            t.beginColumn = beginColumn;
+            t.endColumn = endColumn;
+
+            return t;
+        }
+
+        internal int curLexState = 1;
+        internal int defaultLexState = 1;
+        internal int jjnewStateCnt;
+        internal uint jjround;
+        internal int jjmatchedPos;
+        internal int jjmatchedKind;
+
+        /// <summary>Get the next Token.</summary>
+        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
+        public Token GetNextToken()
+        {
+            Token matchedToken;
+            int curPos = 0;
+
+            for (; ; )
+            {
+                try
+                {
+                    curChar = input_stream.BeginToken();
+                }
+                catch (System.IO.IOException e)
+                {
+                    jjmatchedKind = 0;
+                    matchedToken = JjFillToken();
+                    return matchedToken;
+                }
+
+                switch (curLexState)
+                {
+                    case 0:
+                        jjmatchedKind = 0x7fffffff;
+                        jjmatchedPos = 0;
+                        curPos = JjMoveStringLiteralDfa0_0();
+                        break;
+                    case 1:
+                        jjmatchedKind = 0x7fffffff;
+                        jjmatchedPos = 0;
+                        curPos = jjMoveStringLiteralDfa0_1();
+                        break;
+                }
+                if (jjmatchedKind != 0x7fffffff)
+                {
+                    if (jjmatchedPos + 1 < curPos)
+                        input_stream.Backup(curPos - jjmatchedPos - 1);
+                    if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+                    {
+                        matchedToken = JjFillToken();
+                        if (jjnewLexState[jjmatchedKind] != -1)
+                            curLexState = jjnewLexState[jjmatchedKind];
+                        return matchedToken;
+                    }
+                    else
+                    {
+                        if (jjnewLexState[jjmatchedKind] != -1)
+                            curLexState = jjnewLexState[jjmatchedKind];
+                        goto EOFLoop;
+                    }
+                }
+                int error_line = input_stream.EndLine;
+                int error_column = input_stream.EndColumn;
+                string error_after = null;
+                bool EOFSeen = false;
+                try { input_stream.ReadChar(); input_stream.Backup(1); }
+                catch (System.IO.IOException e1)
+                {
+                    EOFSeen = true;
+                    error_after = curPos <= 1 ? "" : input_stream.Image;
+                    if (curChar == '\n' || curChar == '\r')
+                    {
+                        error_line++;
+                        error_column = 0;
+                    }
+                    else
+                        error_column++;
+                }
+                if (!EOFSeen)
+                {
+                    input_stream.Backup(1);
+                    error_after = curPos <= 1 ? "" : input_stream.Image;
+                }
+                throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
+            EOFLoop: ;
+            }
+        }
+
+        private void JjCheckNAdd(int state)
+        {
+            if (jjrounds[state] != jjround)
+            {
+                jjstateSet[jjnewStateCnt++] = state;
+                jjrounds[state] = jjround;
+            }
+        }
+        private void JjAddStates(int start, int end)
+        {
+            do
+            {
+                jjstateSet[jjnewStateCnt++] = jjnextStates[start];
+            } while (start++ != end);
+        }
+        private void JjCheckNAddTwoStates(int state1, int state2)
+        {
+            JjCheckNAdd(state1);
+            JjCheckNAdd(state2);
+        }
+
+        private void JjCheckNAddStates(int start, int end)
+        {
+            do
+            {
+                JjCheckNAdd(jjnextStates[start]);
+            } while (start++ != end);
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Parser/Token.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Parser/Token.cs b/Lucene.Net.QueryParser/Surround/Parser/Token.cs
new file mode 100644
index 0000000..2d9b83d
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Parser/Token.cs
@@ -0,0 +1,142 @@
+\ufeffusing System;
+
+namespace Lucene.Net.QueryParser.Surround.Parser
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+	
+	/// <summary> 
+    /// Describes the input token stream.
+    /// </summary>
+    [Serializable]
+	public class Token
+	{
+		
+		/// <summary> 
+        /// An integer that describes the kind of this token.  This numbering
+		/// system is determined by JavaCCParser, and a table of these numbers is
+		/// stored in the file ...Constants.java.
+		/// </summary>
+		public int kind;
+		
+		/// <summary>The line number of the first character of this Token. </summary>
+		public int beginLine;
+		/// <summary>The column number of the first character of this Token. </summary>
+		public int beginColumn;
+		/// <summary>The line number of the last character of this Token. </summary>
+		public int endLine;
+		/// <summary>The column number of the last character of this Token. </summary>
+		public int endColumn;
+		
+		/// <summary>The string image of the token.</summary>
+		public string image;
+		
+		/// <summary> 
+        /// A reference to the next regular (non-special) token from the input
+		/// stream.  If this is the last token from the input stream, or if the
+		/// token manager has not read tokens beyond this one, this field is
+		/// set to null.  This is true only if this token is also a regular
+		/// token.  Otherwise, see below for a description of the contents of
+		/// this field.
+		/// </summary>
+		public Token next;
+		
+		/// <summary> 
+        /// This field is used to access special tokens that occur prior to this
+		/// token, but after the immediately preceding regular (non-special) token.
+		/// If there are no such special tokens, this field is set to null.
+		/// When there are more than one such special token, this field refers
+		/// to the last of these special tokens, which in turn refers to the next
+		/// previous special token through its specialToken field, and so on
+		/// until the first special token (whose specialToken field is null).
+		/// The next fields of special tokens refer to other special tokens that
+		/// immediately follow it (without an intervening regular token).  If there
+		/// is no such token, this field is null.
+		/// </summary>
+		public Token specialToken;
+
+	    /// <summary> 
+        /// An optional attribute value of the Token.
+	    /// Tokens which are not used as syntactic sugar will often contain
+	    /// meaningful values that will be used later on by the compiler or
+	    /// interpreter. This attribute value is often different from the image.
+	    /// Any subclass of Token that actually wants to return a non-null value can
+	    /// override this method as appropriate.
+	    /// </summary>
+	    public virtual object Value
+	    {
+	        get { return null; }
+	    }
+
+	    /// <summary> 
+        /// No-argument constructor
+        /// </summary>
+		public Token()
+		{
+		}
+		
+		/// <summary> 
+        /// Constructs a new token for the specified Image.
+        /// </summary>
+		public Token(int kind)
+            : this(kind, null)
+		{
+		}
+		
+		/// <summary> 
+        /// Constructs a new token for the specified Image and Kind.
+        /// </summary>
+		public Token(int kind, string image)
+		{
+			this.kind = kind;
+			this.image = image;
+		}
+		
+		/// <summary> 
+        /// Returns the image.
+        /// </summary>
+		public override string ToString()
+		{
+			return image;
+		}
+		
+		/// <summary> 
+        /// Returns a new Token object, by default. However, if you want, you
+		/// can create and return subclass objects based on the value of ofKind.
+		/// Simply add the cases to the switch for all those special cases.
+		/// For example, if you have a subclass of Token called IDToken that
+		/// you want to create if ofKind is ID, simply add something like :
+		/// 
+		/// case MyParserConstants.ID : return new IDToken(ofKind, image);
+		/// 
+		/// to the following switch statement. Then you can cast matchedToken
+		/// variable to the appropriate type and use sit in your lexical actions.
+		/// </summary>
+		public static Token NewToken(int ofKind, string image)
+		{
+			switch (ofKind)
+			{
+				default:  return new Token(ofKind, image);
+			}
+		}
+		
+		public static Token NewToken(int ofKind)
+		{
+			return NewToken(ofKind, null);
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Parser/TokenMgrError.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Parser/TokenMgrError.cs b/Lucene.Net.QueryParser/Surround/Parser/TokenMgrError.cs
new file mode 100644
index 0000000..2ccfc58
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Parser/TokenMgrError.cs
@@ -0,0 +1,170 @@
+\ufeffusing System;
+using System.Text;
+
+namespace Lucene.Net.QueryParser.Surround.Parser
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+	/// <summary>Token Manager Error. </summary>
+	[Serializable]
+	public class TokenMgrError : Exception
+	{
+        /*
+		* Ordinals for various reasons why an Error of this type can be thrown.
+		*/
+
+        /// <summary> Lexical error occurred.</summary>
+        internal const int LEXICAL_ERROR = 0;
+
+        /// <summary> An attempt was made to create a second instance of a static token manager.</summary>
+        internal const int STATIC_LEXER_ERROR = 1;
+
+        /// <summary> Tried to change to an invalid lexical state.</summary>
+        internal const int INVALID_LEXICAL_STATE = 2;
+
+        /// <summary> Detected (and bailed out of) an infinite loop in the token manager.</summary>
+        internal const int LOOP_DETECTED = 3;
+
+        /// <summary> Indicates the reason why the exception is thrown. It will have
+        /// one of the above 4 values.
+        /// </summary>
+        internal int errorCode;
+
+        /// <summary> 
+        /// Replaces unprintable characters by their escaped (or unicode escaped)
+        /// equivalents in the given string
+        /// </summary>
+        protected internal static string AddEscapes(string str)
+        {
+            StringBuilder retval = new StringBuilder();
+            char ch;
+            for (int i = 0; i < str.Length; i++)
+            {
+                switch (str[i])
+                {
+
+                    case (char)(0):
+                        continue;
+
+                    case '\b':
+                        retval.Append("\\b");
+                        continue;
+
+                    case '\t':
+                        retval.Append("\\t");
+                        continue;
+
+                    case '\n':
+                        retval.Append("\\n");
+                        continue;
+
+                    case '\f':
+                        retval.Append("\\f");
+                        continue;
+
+                    case '\r':
+                        retval.Append("\\r");
+                        continue;
+
+                    case '\"':
+                        retval.Append("\\\"");
+                        continue;
+
+                    case '\'':
+                        retval.Append("\\\'");
+                        continue;
+
+                    case '\\':
+                        retval.Append("\\\\");
+                        continue;
+
+                    default:
+                        if ((ch = str[i]) < 0x20 || ch > 0x7e)
+                        {
+                            string s = "0000" + Convert.ToString(ch, 16);
+                            retval.Append("\\u" + s.Substring(s.Length - 4, (s.Length) - (s.Length - 4)));
+                        }
+                        else
+                        {
+                            retval.Append(ch);
+                        }
+                        continue;
+
+                }
+            }
+            return retval.ToString();
+        }
+
+        /// <summary>
+        /// Returns a detailed message for the Error when it is thrown by the
+        /// token manager to indicate a lexical error.
+        /// </summary>
+        /// <remarks>You can customize the lexical error message by modifying this method.</remarks>
+        /// <param name="EOFSeen">indicates if EOF caused the lexical error</param>
+        /// <param name="lexState">lexical state in which this error occurred</param>
+        /// <param name="errorLine">line number when the error occurred</param>
+        /// <param name="errorColumn">column number when the error occurred</param>
+        /// <param name="errorAfter">prefix that was seen before this error occurred</param>
+        /// <param name="curChar">the offending character</param>
+        /// <returns>Detailed error message</returns>
+        protected internal static string LexicalError(bool EOFSeen, int lexState, int errorLine, int errorColumn, string errorAfter, char curChar)
+        {
+            return ("Lexical error at line " +
+                errorLine + ", column " +
+                errorColumn + ".  Encountered: " +
+                (EOFSeen ? "<EOF> " : ("\"" + AddEscapes(Convert.ToString(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+                "after : \"" + AddEscapes(errorAfter) + "\"");
+        }
+
+		/// <summary> 
+        /// You can also modify the body of this method to customize your error messages.
+		/// For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+		/// of end-users concern, so you can return something like :
+		/// 
+		/// "Internal Error : Please file a bug report .... "
+		/// 
+		/// from this method for such cases in the release version of your parser.
+		/// </summary>
+		public override string Message
+		{
+			get { return base.Message; }
+		}
+		
+		/*
+		* Constructors of various flavors follow.
+		*/
+		
+		/// <summary>No arg constructor. </summary>
+		public TokenMgrError()
+		{
+		}
+		
+		/// <summary>Constructor with message and reason. </summary>
+		public TokenMgrError(string message, int reason)
+            : base(message)
+		{
+			errorCode = reason;
+		}
+		
+		/// <summary>Full Constructor. </summary>
+		public TokenMgrError(bool EOFSeen, int lexState, int errorLine, int errorColumn, string errorAfter, char curChar, int reason)
+            : this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason)
+		{
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Query/AndQuery.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Query/AndQuery.cs b/Lucene.Net.QueryParser/Surround/Query/AndQuery.cs
new file mode 100644
index 0000000..aa00e0d
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Query/AndQuery.cs
@@ -0,0 +1,39 @@
+\ufeffusing Lucene.Net.Search;
+using System.Collections.Generic;
+
+namespace Lucene.Net.QueryParser.Surround.Query
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Factory for conjunctions
+    /// </summary>
+    public class AndQuery : ComposedQuery
+    {
+        public AndQuery(IEnumerable<SrndQuery> queries, bool inf, string opName)
+            : base(queries, inf, opName)
+        {
+        }
+
+        public override Search.Query MakeLuceneQueryFieldNoBoost(string fieldName, BasicQueryFactory qf)
+        {
+            return SrndBooleanQuery.MakeBooleanQuery( /* subqueries can be individually boosted */
+              MakeLuceneSubQueriesField(fieldName, qf), BooleanClause.Occur.MUST);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Query/BasicQueryFactory.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Query/BasicQueryFactory.cs b/Lucene.Net.QueryParser/Surround/Query/BasicQueryFactory.cs
new file mode 100644
index 0000000..8992746
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Query/BasicQueryFactory.cs
@@ -0,0 +1,110 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Search.Spans;
+using System.Runtime.CompilerServices;
+
+namespace Lucene.Net.QueryParser.Surround.Query
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+     // Create basic queries to be used during rewrite.
+     // The basic queries are TermQuery and SpanTermQuery.
+     // An exception can be thrown when too many of these are used.
+     // SpanTermQuery and TermQuery use IndexReader.termEnum(Term), which causes the buffer usage.
+     
+     // Use this class to limit the buffer usage for reading terms from an index.
+     // Default is 1024, the same as the max. number of subqueries for a BooleanQuery.
+
+
+
+    /// <summary>
+    /// Factory for creating basic term queries
+    /// </summary>
+    public class BasicQueryFactory
+    {
+        public BasicQueryFactory(int maxBasicQueries)
+        {
+            this.maxBasicQueries = maxBasicQueries;
+            this.queriesMade = 0;
+        }
+
+        public BasicQueryFactory()
+            : this(1024)
+        {
+        }
+
+        private int maxBasicQueries;
+        private int queriesMade;
+
+        public int NrQueriesMade { get { return queriesMade; } }
+        public int MaxBasicQueries { get { return maxBasicQueries; } }
+
+        public override string ToString()
+        {
+            return GetType().Name
+                + "(maxBasicQueries: " + maxBasicQueries
+                + ", queriesMade: " + queriesMade
+                + ")";
+        }
+
+        private bool AtMax
+        {
+            get { return queriesMade >= maxBasicQueries; }
+        }
+
+        [MethodImpl(MethodImplOptions.Synchronized)]
+        protected virtual void CheckMax()
+        {
+            if (AtMax)
+                throw new TooManyBasicQueries(MaxBasicQueries);
+            queriesMade++;
+        }
+
+        public TermQuery NewTermQuery(Term term)
+        {
+            CheckMax();
+            return new TermQuery(term);
+        }
+
+        public SpanTermQuery NewSpanTermQuery(Term term)
+        {
+            CheckMax();
+            return new SpanTermQuery(term);
+        }
+
+        public override int GetHashCode()
+        {
+            return GetType().GetHashCode() ^ (AtMax ? 7 : 31 * 32);
+        }
+
+        /// <summary>
+        /// Two BasicQueryFactory's are equal when they generate
+        /// the same types of basic queries, or both cannot generate queries anymore.
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <returns></returns>
+        public override bool Equals(object obj)
+        {
+            if (!(obj is BasicQueryFactory))
+                return false;
+            BasicQueryFactory other = (BasicQueryFactory)obj;
+            return AtMax == other.AtMax;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Query/ComposedQuery.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Query/ComposedQuery.cs b/Lucene.Net.QueryParser/Surround/Query/ComposedQuery.cs
new file mode 100644
index 0000000..d421ad6
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Query/ComposedQuery.cs
@@ -0,0 +1,144 @@
+\ufeffusing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Lucene.Net.QueryParser.Surround.Query
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Base class for composite queries (such as AND/OR/NOT)
+    /// </summary>
+    public abstract class ComposedQuery : SrndQuery
+    {
+        public ComposedQuery(IEnumerable<SrndQuery> qs, bool operatorInfix, string opName)
+        {
+            Recompose(qs);
+            this.operatorInfix = operatorInfix;
+            this.opName = opName;
+        }
+
+        protected virtual void Recompose(IEnumerable<SrndQuery> queries)
+        {
+            if (queries.Count() < 2) throw new InvalidOperationException("Too few subqueries");
+            this.queries = new List<SrndQuery>(queries);
+        }
+
+        protected string opName;
+        public virtual string OperatorName { get { return opName; } }
+
+        protected IList<SrndQuery> queries;
+
+        public virtual IEnumerator<SrndQuery> GetSubQueriesEnumerator()
+        {
+            return queries.GetEnumerator();
+        }
+
+        public virtual int NrSubQueries { get { return queries.Count; } }
+
+        public virtual SrndQuery GetSubQuery(int qn) { return queries[qn]; }
+
+        private bool operatorInfix;
+        public virtual bool IsOperatorInfix { get { return operatorInfix; } } /* else prefix operator */
+
+        public IEnumerable<Search.Query> MakeLuceneSubQueriesField(string fn, BasicQueryFactory qf)
+        {
+            List<Search.Query> luceneSubQueries = new List<Search.Query>();
+            IEnumerator<SrndQuery> sqi = GetSubQueriesEnumerator();
+            while (sqi.MoveNext())
+            {
+                luceneSubQueries.Add((sqi.Current).MakeLuceneQueryField(fn, qf));
+            }
+            return luceneSubQueries;
+        }
+
+        public override string ToString()
+        {
+            StringBuilder r = new StringBuilder();
+            if (IsOperatorInfix)
+            {
+                InfixToString(r);
+            }
+            else
+            {
+                PrefixToString(r);
+            }
+            WeightToString(r);
+            return r.ToString();
+        }
+
+        // Override for different spacing
+        protected virtual string PrefixSeparator { get { return ", "; } }
+        protected virtual string BracketOpen { get { return "("; } }
+        protected virtual string BracketClose { get { return ")"; } }
+
+        protected virtual void InfixToString(StringBuilder r)
+        {
+            /* Brackets are possibly redundant in the result. */
+            IEnumerator<SrndQuery> sqi = GetSubQueriesEnumerator();
+            r.Append(BracketOpen);
+            if (sqi.MoveNext())
+            {
+                r.Append(sqi.Current.ToString());
+                while (sqi.MoveNext())
+                {
+                    r.Append(" ");
+                    r.Append(OperatorName); /* infix operator */
+                    r.Append(" ");
+                    r.Append(sqi.Current.ToString());
+                }
+            }
+            r.Append(BracketClose);
+        }
+
+        protected virtual void PrefixToString(StringBuilder r)
+        {
+            IEnumerator<SrndQuery> sqi = GetSubQueriesEnumerator();
+            r.Append(OperatorName); /* prefix operator */
+            r.Append(BracketOpen);
+            if (sqi.MoveNext())
+            {
+                r.Append(sqi.Current.ToString());
+                while (sqi.MoveNext())
+                {
+                    r.Append(PrefixSeparator);
+                    r.Append(sqi.Current.ToString());
+                }
+            }
+            r.Append(BracketClose);
+        }
+
+        public override bool IsFieldsSubQueryAcceptable
+        {
+            get
+            {
+                /* at least one subquery should be acceptable */
+                IEnumerator<SrndQuery> sqi = GetSubQueriesEnumerator();
+                while (sqi.MoveNext())
+                {
+                    if ((sqi.Current).IsFieldsSubQueryAcceptable)
+                    {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Query/DistanceQuery.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Query/DistanceQuery.cs b/Lucene.Net.QueryParser/Surround/Query/DistanceQuery.cs
new file mode 100644
index 0000000..1ca7a01
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Query/DistanceQuery.cs
@@ -0,0 +1,117 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Search.Spans;
+using System;
+using System.Collections.Generic;
+
+namespace Lucene.Net.QueryParser.Surround.Query
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Factory for NEAR queries 
+    /// </summary>
+    public class DistanceQuery : ComposedQuery, IDistanceSubQuery
+    {
+        public DistanceQuery(
+            IEnumerable<SrndQuery> queries,
+            bool infix,
+            int opDistance,
+            string opName,
+            bool ordered)
+            : base(queries, infix, opName)
+        {
+            this.opDistance = opDistance; /* the distance indicated in the operator */
+            this.ordered = ordered;
+        }
+
+        private int opDistance;
+        public virtual int OpDistance { get { return opDistance; } }
+
+        private bool ordered;
+        public virtual bool QueriesOrdered { get { return ordered; } }
+
+
+        public virtual string DistanceSubQueryNotAllowed()
+        {
+            var sqi = GetSubQueriesEnumerator();
+            while (sqi.MoveNext())
+            {
+                var dsq = sqi.Current as IDistanceSubQuery;
+                if (dsq != null)
+                {
+                    string m = dsq.DistanceSubQueryNotAllowed();
+                    if (m != null)
+                    {
+                        return m;
+                    }
+                }
+                else
+                {
+                    return "Operator " + OperatorName + " does not allow subquery " + dsq.ToString();
+                }
+            }
+            return null; /* subqueries acceptable */
+        }
+
+        public virtual void AddSpanQueries(SpanNearClauseFactory sncf)
+        {
+            Search.Query snq = GetSpanNearQuery(sncf.IndexReader,
+                                  sncf.FieldName,
+                                  Weight,
+                                  sncf.BasicQueryFactory);
+            sncf.AddSpanQuery(snq);
+        }
+
+        public Search.Query GetSpanNearQuery(
+            IndexReader reader,
+            String fieldName,
+            float boost,
+            BasicQueryFactory qf)
+        {
+            SpanQuery[] spanClauses = new SpanQuery[NrSubQueries];
+            var sqi = GetSubQueriesEnumerator();
+            int qi = 0;
+            while (sqi.MoveNext())
+            {
+                SpanNearClauseFactory sncf = new SpanNearClauseFactory(reader, fieldName, qf);
+
+                ((IDistanceSubQuery)sqi.Current).AddSpanQueries(sncf);
+                if (sncf.Count == 0)
+                { /* distance operator requires all sub queries */
+                    while (sqi.MoveNext())
+                    { /* produce evt. error messages but ignore results */
+                        ((IDistanceSubQuery)sqi.Current).AddSpanQueries(sncf);
+                        sncf.Clear();
+                    }
+                    return SrndQuery.TheEmptyLcnQuery;
+                }
+
+                spanClauses[qi] = sncf.MakeSpanClause();
+                qi++;
+            }
+            SpanNearQuery r = new SpanNearQuery(spanClauses, OpDistance - 1, QueriesOrdered);
+            r.Boost = boost;
+            return r;
+        }
+
+        public override Search.Query MakeLuceneQueryFieldNoBoost(string fieldName, BasicQueryFactory qf)
+        {
+            return new DistanceRewriteQuery(this, fieldName, qf);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Query/DistanceRewriteQuery.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Query/DistanceRewriteQuery.cs b/Lucene.Net.QueryParser/Surround/Query/DistanceRewriteQuery.cs
new file mode 100644
index 0000000..3d3a108
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Query/DistanceRewriteQuery.cs
@@ -0,0 +1,35 @@
+\ufeffnamespace Lucene.Net.QueryParser.Surround.Query
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    internal class DistanceRewriteQuery : RewriteQuery<DistanceQuery>
+    {
+        public DistanceRewriteQuery(
+            DistanceQuery srndQuery,
+            string fieldName,
+            BasicQueryFactory qf)
+            : base(srndQuery, fieldName, qf)
+        {
+        }
+
+        public override Search.Query Rewrite(Index.IndexReader reader)
+        {
+            return srndQuery.GetSpanNearQuery(reader, fieldName, Boost, qf);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Query/DistanceSubQuery.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Query/DistanceSubQuery.cs b/Lucene.Net.QueryParser/Surround/Query/DistanceSubQuery.cs
new file mode 100644
index 0000000..639f9e0
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Query/DistanceSubQuery.cs
@@ -0,0 +1,36 @@
+\ufeffnamespace Lucene.Net.QueryParser.Surround.Query
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Interface for queries that can be nested as subqueries
+    /// into a span near.
+    /// </summary>
+    public interface IDistanceSubQuery
+    {
+        /// <summary>
+        /// When distanceSubQueryNotAllowed() returns non null, the reason why the subquery
+        /// is not allowed as a distance subquery is returned.
+        /// <br>When distanceSubQueryNotAllowed() returns null addSpanNearQueries() can be used
+        /// in the creation of the span near clause for the subquery.
+        /// </summary>
+        string DistanceSubQueryNotAllowed();
+
+        void AddSpanQueries(SpanNearClauseFactory sncf);
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Query/FieldsQuery.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Query/FieldsQuery.cs b/Lucene.Net.QueryParser/Surround/Query/FieldsQuery.cs
new file mode 100644
index 0000000..912bf36
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Query/FieldsQuery.cs
@@ -0,0 +1,105 @@
+\ufeffusing System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Lucene.Net.QueryParser.Surround.Query
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Forms an OR query of the provided query across multiple fields.
+    /// </summary>
+    public class FieldsQuery : SrndQuery /* mostly untested */
+    {
+        private SrndQuery q;
+        private IEnumerable<string> fieldNames;
+        private readonly char fieldOp;
+        private readonly string OrOperatorName = "OR"; /* for expanded queries, not normally visible */
+
+        public FieldsQuery(SrndQuery q, IEnumerable<string> fieldNames, char fieldOp)
+        {
+            this.q = q;
+            this.fieldNames = new List<string>(fieldNames);
+            this.fieldOp = fieldOp;
+        }
+
+        public FieldsQuery(SrndQuery q, string fieldName, char fieldOp)
+        {
+            this.q = q;
+            var fieldNameList = new List<string>();
+            fieldNameList.Add(fieldName);
+            this.fieldNames = fieldNameList;
+            this.fieldOp = fieldOp;
+        }
+
+        public override bool IsFieldsSubQueryAcceptable
+        {
+            get { return false; }
+        }
+
+        public Search.Query MakeLuceneQueryNoBoost(BasicQueryFactory qf)
+        {
+            if (fieldNames.Count() == 1)
+            { /* single field name: no new queries needed */
+                return q.MakeLuceneQueryFieldNoBoost(fieldNames.FirstOrDefault(), qf);
+            }
+            else
+            { /* OR query over the fields */
+                List<SrndQuery> queries = new List<SrndQuery>();
+                foreach (var fieldName in fieldNames)
+                {
+                    var qc = (SrndQuery)q.Clone();
+                    queries.Add(new FieldsQuery(qc, fieldName, fieldOp));
+                }
+                OrQuery oq = new OrQuery(queries,
+                                        true /* infix OR for field names */,
+                                        OrOperatorName);
+                // System.out.println(getClass().toString() + ", fields expanded: " + oq.toString()); /* needs testing */
+                return oq.MakeLuceneQueryField(null, qf);
+            }
+        }
+
+        public override Search.Query MakeLuceneQueryFieldNoBoost(string fieldName, BasicQueryFactory qf)
+        {
+            return MakeLuceneQueryNoBoost(qf); /* use this.fieldNames instead of fieldName */
+        }
+
+        public virtual IEnumerable<string> FieldNames { get { return fieldNames; } }
+
+        public virtual char FieldOperator { get { return fieldOp; } }
+
+        public override string ToString()
+        {
+            StringBuilder r = new StringBuilder();
+            r.Append("(");
+            FieldNamesToString(r);
+            r.Append(q.ToString());
+            r.Append(")");
+            return r.ToString();
+        }
+
+        protected virtual void FieldNamesToString(StringBuilder r)
+        {
+            foreach (var fieldName in FieldNames)
+            {
+                r.Append(fieldName);
+                r.Append(FieldOperator);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Query/NotQuery.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Query/NotQuery.cs b/Lucene.Net.QueryParser/Surround/Query/NotQuery.cs
new file mode 100644
index 0000000..30d40a8
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Query/NotQuery.cs
@@ -0,0 +1,48 @@
+\ufeffusing Lucene.Net.Search;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Lucene.Net.QueryParser.Surround.Query
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Factory for prohibited clauses
+    /// </summary>
+    public class NotQuery : ComposedQuery
+    {
+        public NotQuery(IEnumerable<SrndQuery> queries, string opName)
+            : base(queries, true /* infix */, opName)
+        {
+        }
+
+        public override Search.Query MakeLuceneQueryFieldNoBoost(string fieldName, BasicQueryFactory qf)
+        {
+            var luceneSubQueries = MakeLuceneSubQueriesField(fieldName, qf);
+            BooleanQuery bq = new BooleanQuery();
+            bq.Add(luceneSubQueries.FirstOrDefault(), BooleanClause.Occur.MUST);
+            SrndBooleanQuery.AddQueriesToBoolean(bq,
+                // FIXME: do not allow weights on prohibited subqueries.
+                    //luceneSubQueries.subList(1, luceneSubQueries.size()),
+                    luceneSubQueries.Skip(1).ToList(),
+                // later subqueries: not required, prohibited
+                    BooleanClause.Occur.MUST_NOT);
+            return bq;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Query/OrQuery.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Query/OrQuery.cs b/Lucene.Net.QueryParser/Surround/Query/OrQuery.cs
new file mode 100644
index 0000000..f7d0036
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Query/OrQuery.cs
@@ -0,0 +1,71 @@
+\ufeffusing Lucene.Net.Search;
+using System.Collections.Generic;
+
+namespace Lucene.Net.QueryParser.Surround.Query
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Factory for disjunctions
+    /// </summary>
+    public class OrQuery : ComposedQuery, IDistanceSubQuery
+    {
+        public OrQuery(IEnumerable<SrndQuery> queries, bool infix, string opName)
+            : base(queries, infix, opName)
+        {
+        }
+
+        public override Search.Query MakeLuceneQueryFieldNoBoost(string fieldName, BasicQueryFactory qf)
+        {
+            return SrndBooleanQuery.MakeBooleanQuery(
+                /* subqueries can be individually boosted */
+                MakeLuceneSubQueriesField(fieldName, qf), BooleanClause.Occur.SHOULD);
+        }
+
+        public virtual string DistanceSubQueryNotAllowed()
+        {
+            var sqi = GetSubQueriesEnumerator();
+            while (sqi.MoveNext())
+            {
+                SrndQuery leq = sqi.Current;
+                if (leq is IDistanceSubQuery)
+                {
+                    string m = ((IDistanceSubQuery)leq).DistanceSubQueryNotAllowed();
+                    if (m != null)
+                    {
+                        return m;
+                    }
+                }
+                else
+                {
+                    return "subquery not allowed: " + leq.ToString();
+                }
+            }
+            return null;
+        }
+
+        public virtual void AddSpanQueries(SpanNearClauseFactory sncf)
+        {
+            var sqi = GetSubQueriesEnumerator();
+            while (sqi.MoveNext())
+            {
+                ((IDistanceSubQuery)sqi.Current).AddSpanQueries(sncf);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Query/RewriteQuery.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Query/RewriteQuery.cs b/Lucene.Net.QueryParser/Surround/Query/RewriteQuery.cs
new file mode 100644
index 0000000..030923f
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Query/RewriteQuery.cs
@@ -0,0 +1,85 @@
+\ufeffusing Lucene.Net.Index;
+using System;
+
+namespace Lucene.Net.QueryParser.Surround.Query
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    public abstract class RewriteQuery<SQ> : Search.Query
+    {
+        protected readonly SQ srndQuery;
+        protected readonly string fieldName;
+        protected readonly BasicQueryFactory qf;
+
+        public RewriteQuery(
+            SQ srndQuery,
+            String fieldName,
+            BasicQueryFactory qf)
+        {
+            this.srndQuery = srndQuery;
+            this.fieldName = fieldName;
+            this.qf = qf;
+        }
+
+        public abstract override Search.Query Rewrite(IndexReader reader);
+
+        public override string ToString()
+        {
+            return ToString(null);
+        }
+
+        public override string ToString(string field)
+        {
+            return GetType().Name
+                + (field == null ? "" : "(unused: " + field + ")")
+                + "(" + fieldName
+                + ", " + srndQuery.ToString()
+                + ", " + qf.ToString()
+                + ")";
+        }
+
+        public override int GetHashCode()
+        {
+            return GetType().GetHashCode()
+                ^ fieldName.GetHashCode()
+                ^ qf.GetHashCode()
+                ^ srndQuery.GetHashCode();
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (obj == null)
+                return false;
+            if (!GetType().Equals(obj.GetType()))
+                return false;
+            RewriteQuery<SQ> other = (RewriteQuery<SQ>)obj;
+            return fieldName.Equals(other.fieldName)
+                && qf.Equals(other.qf)
+                && srndQuery.Equals(other.srndQuery);
+        }
+
+        /// <summary>
+        /// Not supported by this query.
+        /// </summary>
+        /// <exception cref="NotSupportedException">throws NotSupportedException always: clone is not supported.</exception>
+        public override object Clone()
+        {
+            throw new NotSupportedException();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Query/SimpleTerm.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Query/SimpleTerm.cs b/Lucene.Net.QueryParser/Surround/Query/SimpleTerm.cs
new file mode 100644
index 0000000..5e39e03
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Query/SimpleTerm.cs
@@ -0,0 +1,118 @@
+\ufeffusing Lucene.Net.Index;
+using System;
+using System.Text;
+
+namespace Lucene.Net.QueryParser.Surround.Query
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Base class for queries that expand to sets of simple terms.
+    /// </summary>
+    public abstract class SimpleTerm : SrndQuery, IDistanceSubQuery, IComparable<SimpleTerm>
+    {
+        public SimpleTerm(bool q) 
+        { 
+            quoted = q; 
+        }
+
+        private bool quoted;
+        internal bool IsQuoted { get { return quoted; } }
+
+        public virtual string Quote { get { return "\""; }}
+        public virtual string FieldOperator { get { return "/"; } }
+
+        public abstract string ToStringUnquoted();
+
+        [Obsolete("deprecated (March 2011) Not normally used, to be removed from Lucene 4.0. This class implementing Comparable is to be removed at the same time.")]
+        public int CompareTo(SimpleTerm ost)
+        {
+            /* for ordering terms and prefixes before using an index, not used */
+            return this.ToStringUnquoted().CompareTo(ost.ToStringUnquoted());
+        }
+
+        protected virtual void SuffixToString(StringBuilder r) { } /* override for prefix query */
+
+
+        public override string ToString()
+        {
+            StringBuilder r = new StringBuilder();
+            if (IsQuoted)
+            {
+                r.Append(Quote);
+            }
+            r.Append(ToStringUnquoted());
+            if (IsQuoted)
+            {
+                r.Append(Quote);
+            }
+            SuffixToString(r);
+            WeightToString(r);
+            return r.ToString();
+        }
+
+        public abstract void VisitMatchingTerms(
+                            IndexReader reader,
+                            string fieldName,
+                            IMatchingTermVisitor mtv);
+
+        /// <summary>
+        /// Callback to visit each matching term during "rewrite"
+        /// in <see cref="M:VisitMatchingTerm(Term)"/>
+        /// </summary>
+        public interface IMatchingTermVisitor
+        {
+            void VisitMatchingTerm(Term t);
+        }
+
+        public string DistanceSubQueryNotAllowed()
+        {
+            return null;
+        }
+
+        public void AddSpanQueries(SpanNearClauseFactory sncf)
+        {
+            VisitMatchingTerms(
+                sncf.IndexReader,
+                sncf.FieldName,
+                new AddSpanQueriesMatchingTermVisitor(sncf, Weight));
+        }
+
+        internal class AddSpanQueriesMatchingTermVisitor : IMatchingTermVisitor
+        {
+            private readonly SpanNearClauseFactory sncf;
+            private readonly float weight;
+
+            public AddSpanQueriesMatchingTermVisitor(SpanNearClauseFactory sncf, float weight)
+            {
+                this.sncf = sncf;
+                this.weight = weight;
+            }
+
+            public void VisitMatchingTerm(Term term)
+            {
+                sncf.AddTermWeighted(term, weight);
+            }
+        }
+
+        public override Search.Query MakeLuceneQueryFieldNoBoost(string fieldName, BasicQueryFactory qf)
+        {
+            return new SimpleTermRewriteQuery(this, fieldName, qf);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/1e7576a6/Lucene.Net.QueryParser/Surround/Query/SimpleTermRewriteQuery.cs
----------------------------------------------------------------------
diff --git a/Lucene.Net.QueryParser/Surround/Query/SimpleTermRewriteQuery.cs b/Lucene.Net.QueryParser/Surround/Query/SimpleTermRewriteQuery.cs
new file mode 100644
index 0000000..6502d6c
--- /dev/null
+++ b/Lucene.Net.QueryParser/Surround/Query/SimpleTermRewriteQuery.cs
@@ -0,0 +1,64 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Search;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Lucene.Net.QueryParser.Surround.Query
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    internal class SimpleTermRewriteQuery : RewriteQuery<SimpleTerm>
+    {
+        public  SimpleTermRewriteQuery(
+            SimpleTerm srndQuery,
+            string fieldName,
+            BasicQueryFactory qf)
+            : base(srndQuery, fieldName, qf)
+        {
+        }
+
+        public override Search.Query Rewrite(IndexReader reader)
+        {
+            var luceneSubQueries = new List<Search.Query>();
+            srndQuery.VisitMatchingTerms(reader, fieldName, 
+                new SimpleTermRewriteMatchingTermVisitor(luceneSubQueries, qf));
+            return (luceneSubQueries.Count == 0) ? SrndQuery.TheEmptyLcnQuery
+                : (luceneSubQueries.Count == 1) ? luceneSubQueries.First()
+                : SrndBooleanQuery.MakeBooleanQuery(
+                /* luceneSubQueries all have default weight */
+                luceneSubQueries, BooleanClause.Occur.SHOULD); /* OR the subquery terms */
+        }
+
+        internal class SimpleTermRewriteMatchingTermVisitor : SimpleTerm.IMatchingTermVisitor
+        {
+            private readonly IList<Search.Query> luceneSubQueries;
+            private readonly BasicQueryFactory qf;
+
+            public SimpleTermRewriteMatchingTermVisitor(IList<Search.Query> luceneSubQueries, BasicQueryFactory qf)
+            {
+                this.luceneSubQueries = luceneSubQueries;
+                this.qf = qf;
+            }
+
+            public void VisitMatchingTerm(Term term)
+            {
+                luceneSubQueries.Add(qf.NewTermQuery(term));
+            }
+        }
+    }
+}