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:56 UTC
[25/50] [abbrv] lucenenet git commit: Moved Lucene.Net.QueryParser
and Lucene.Net.Tests.QueryParser projects into src\ directory.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/679ad24c/src/Lucene.Net.QueryParser/Classic/QueryParserTokenManager.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Classic/QueryParserTokenManager.cs b/src/Lucene.Net.QueryParser/Classic/QueryParserTokenManager.cs
new file mode 100644
index 0000000..aac1505
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Classic/QueryParserTokenManager.cs
@@ -0,0 +1,1356 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+
+namespace Lucene.Net.QueryParser.Classic
+{
+ /*
+ * 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_2(int pos, long active0)
+ {
+ switch (pos)
+ {
+
+ default:
+ return - 1;
+
+ }
+ }
+ private int JjStartNfa_2(int pos, long active0)
+ {
+ return JjMoveNfa_2(JjStopStringLiteralDfa_2(pos, active0), pos + 1);
+ }
+ private int JjStopAtPos(int pos, int kind)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ return pos + 1;
+ }
+ private int JjMoveStringLiteralDfa0_2()
+ {
+ switch (curChar)
+ {
+
+ case (char) (40):
+ return JjStopAtPos(0, 14);
+
+ case (char) (41):
+ return JjStopAtPos(0, 15);
+
+ case (char) (42):
+ return JjStartNfaWithStates_2(0, 17, 49);
+
+ case (char) (43):
+ return JjStartNfaWithStates_2(0, 11, 15);
+
+ case (char) (45):
+ return JjStartNfaWithStates_2(0, 12, 15);
+
+ case (char) (58):
+ return JjStopAtPos(0, 16);
+
+ case (char) (91):
+ return JjStopAtPos(0, 25);
+
+ case (char) (94):
+ return JjStopAtPos(0, 18);
+
+ case (char) (123):
+ return JjStopAtPos(0, 26);
+
+ default:
+ return JjMoveNfa_2(0, 0);
+
+ }
+ }
+ private int JjStartNfaWithStates_2(int pos, int kind, int state)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ try
+ {
+ curChar = input_stream.ReadChar();
+ }
+ catch (IOException)
+ {
+ return pos + 1;
+ }
+ return JjMoveNfa_2(state, pos + 1);
+ }
+ internal static readonly ulong[] jjbitVec0 = new ulong[]{0x1L, 0x0L, 0x0L, 0x0L};
+ internal static readonly ulong[] jjbitVec1 = new ulong[]{0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL};
+ internal static readonly ulong[] jjbitVec3 = new ulong[]{0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL};
+ internal static readonly ulong[] jjbitVec4 = new ulong[]{0xfffefffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL};
+ private int JjMoveNfa_2(int startState, int curPos)
+ {
+ int startsAt = 0;
+ jjnewStateCnt = 49;
+ 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 49:
+ case 33:
+ if ((0xfbff7cf8ffffd9ffL & l) == (ulong)0L)
+ break;
+ if (kind > 23)
+ kind = 23;
+ JjCheckNAddTwoStates(33, 34);
+ break;
+
+ case 0:
+ if ((0xfbff54f8ffffd9ffL & l) != (ulong)0L)
+ {
+ if (kind > 23)
+ kind = 23;
+ JjCheckNAddTwoStates(33, 34);
+ }
+ else if ((0x100002600L & l) != 0L)
+ {
+ if (kind > 7)
+ kind = 7;
+ }
+ else if ((0x280200000000L & l) != 0L)
+ jjstateSet[jjnewStateCnt++] = 15;
+ else if (curChar == 47)
+ JjCheckNAddStates(0, 2);
+ else if (curChar == 34)
+ JjCheckNAddStates(3, 5);
+ if ((0x7bff50f8ffffd9ffL & l) != 0L)
+ {
+ if (kind > 20)
+ kind = 20;
+ JjCheckNAddStates(6, 10);
+ }
+ else if (curChar == 42)
+ {
+ if (kind > 22)
+ kind = 22;
+ }
+ else if (curChar == 33)
+ {
+ if (kind > 10)
+ kind = 10;
+ }
+ if (curChar == 38)
+ jjstateSet[jjnewStateCnt++] = 4;
+ break;
+
+ case 4:
+ if (curChar == 38 && kind > 8)
+ kind = 8;
+ break;
+
+ case 5:
+ if (curChar == 38)
+ jjstateSet[jjnewStateCnt++] = 4;
+ break;
+
+ case 13:
+ if (curChar == 33 && kind > 10)
+ kind = 10;
+ break;
+
+ case 14:
+ if ((0x280200000000L & l) != 0L)
+ jjstateSet[jjnewStateCnt++] = 15;
+ break;
+ case 15:
+ if ((0x100002600L & l) != 0L && kind > 13)
+ kind = 13;
+ break;
+ case 16:
+ if (curChar == 34)
+ JjCheckNAddStates(3, 5);
+ break;
+ case 17:
+ if ((0xfffffffbffffffffL & l) != (ulong) 0L)
+ JjCheckNAddStates(3, 5);
+ break;
+
+ case 19:
+ JjCheckNAddStates(3, 5);
+ break;
+
+ case 20:
+ if (curChar == 34 && kind > 19)
+ kind = 19;
+ break;
+
+ case 22:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddStates(11, 14);
+ break;
+
+ case 23:
+ if (curChar == 46)
+ JjCheckNAdd(24);
+ break;
+
+ case 24:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddStates(15, 17);
+ break;
+
+ case 25:
+ if ((0x7bff78f8ffffd9ffL & l) == (ulong)0L)
+ break;
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddTwoStates(25, 26);
+ break;
+
+ case 27:
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddTwoStates(25, 26);
+ break;
+
+ case 28:
+ if ((0x7bff78f8ffffd9ffL & l) == 0L)
+ break;
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddTwoStates(28, 29);
+ break;
+
+ case 30:
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddTwoStates(28, 29);
+ break;
+
+ case 31:
+ if (curChar == 42 && kind > 22)
+ kind = 22;
+ break;
+
+ case 32:
+ if ((0xfbff54f8ffffd9ffL & l) == (ulong)0L)
+ break;
+ if (kind > 23)
+ kind = 23;
+ JjCheckNAddTwoStates(33, 34);
+ break;
+ case 35:
+ if (kind > 23)
+ kind = 23;
+ JjCheckNAddTwoStates(33, 34);
+ break;
+ case 36:
+ case 38:
+ if (curChar == 47)
+ JjCheckNAddStates(0, 2);
+ break;
+ case 37:
+ if ((0xffff7fffffffffffL & l) != (ulong)0L)
+ JjCheckNAddStates(0, 2);
+ break;
+ case 40:
+ if (curChar == 47 && kind > 24)
+ kind = 24;
+ break;
+ case 41:
+ if ((0x7bff50f8ffffd9ffL & l) == 0L)
+ break;
+ if (kind > 20)
+ kind = 20;
+ JjCheckNAddStates(6, 10);
+ break;
+ case 42:
+ if ((0x7bff78f8ffffd9ffL & l) == 0L)
+ break;
+ if (kind > 20)
+ kind = 20;
+ JjCheckNAddTwoStates(42, 43);
+ break;
+ case 44:
+ if (kind > 20)
+ kind = 20;
+ JjCheckNAddTwoStates(42, 43);
+ break;
+ case 45:
+ if ((0x7bff78f8ffffd9ffL & l) != 0L)
+ JjCheckNAddStates(18, 20);
+ break;
+ case 47:
+ JjCheckNAddStates(18, 20);
+ break;
+
+ default: break;
+
+ }
+ }
+ while (i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ // NOTE: This didn't change in Java from 3.0.1 to 4.8.0, but it is different in .NET.
+ // But changing it back made more tests pass, so I am working under the assumption 63
+ // is the correct value.
+ //ulong l = (ulong)(1L << (curChar & 077));
+ ulong l = (ulong) (1L << (curChar & 63));
+ do
+ {
+ switch (jjstateSet[--i])
+ {
+
+ case 49:
+ if ((0x97ffffff87ffffffL & l) != (ulong) 0L)
+ {
+ if (kind > 23)
+ kind = 23;
+ JjCheckNAddTwoStates(33, 34);
+ }
+ else if (curChar == 92)
+ JjCheckNAddTwoStates(35, 35);
+ break;
+
+ case 0:
+ if ((0x97ffffff87ffffffL & l) != (ulong) 0L)
+ {
+ if (kind > 20)
+ kind = 20;
+ JjCheckNAddStates(6, 10);
+ }
+ else if (curChar == 92)
+ JjCheckNAddStates(21, 23);
+ else if (curChar == 126)
+ {
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddStates(24, 26);
+ }
+ if ((0x97ffffff87ffffffL & l) != (ulong) 0L)
+ {
+ if (kind > 23)
+ kind = 23;
+ JjCheckNAddTwoStates(33, 34);
+ }
+ if (curChar == 78)
+ jjstateSet[jjnewStateCnt++] = 11;
+ else if (curChar == 124)
+ jjstateSet[jjnewStateCnt++] = 8;
+ else if (curChar == 79)
+ jjstateSet[jjnewStateCnt++] = 6;
+ else if (curChar == 65)
+ jjstateSet[jjnewStateCnt++] = 2;
+ break;
+
+ case 1:
+ if (curChar == 68 && kind > 8)
+ kind = 8;
+ break;
+
+ case 2:
+ if (curChar == 78)
+ jjstateSet[jjnewStateCnt++] = 1;
+ break;
+
+ case 3:
+ if (curChar == 65)
+ jjstateSet[jjnewStateCnt++] = 2;
+ break;
+
+ case 6:
+ if (curChar == 82 && kind > 9)
+ kind = 9;
+ break;
+
+ case 7:
+ if (curChar == 79)
+ jjstateSet[jjnewStateCnt++] = 6;
+ break;
+
+ case 8:
+ if (curChar == 124 && kind > 9)
+ kind = 9;
+ break;
+
+ case 9:
+ if (curChar == 124)
+ jjstateSet[jjnewStateCnt++] = 8;
+ break;
+
+ case 10:
+ if (curChar == 84 && kind > 10)
+ kind = 10;
+ break;
+
+ case 11:
+ if (curChar == 79)
+ jjstateSet[jjnewStateCnt++] = 10;
+ break;
+
+ case 12:
+ if (curChar == 78)
+ jjstateSet[jjnewStateCnt++] = 11;
+ break;
+
+ case 17:
+ if ((0xffffffffefffffffL & l) != (ulong) 0L)
+ JjCheckNAddStates(3, 5);
+ break;
+
+ case 18:
+ if (curChar == 92)
+ jjstateSet[jjnewStateCnt++] = 19;
+ break;
+
+ case 19:
+ JjCheckNAddStates(3, 5);
+ break;
+
+ case 21:
+ if (curChar != 126)
+ break;
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddStates(24, 26);
+ break;
+
+ case 25:
+ if ((0x97ffffff87ffffffL & l) == (ulong) 0L)
+ break;
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddTwoStates(25, 26);
+ break;
+
+ case 26:
+ if (curChar == 92)
+ JjAddStates(27, 28);
+ break;
+
+ case 27:
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddTwoStates(25, 26);
+ break;
+
+ case 28:
+ if ((0x97ffffff87ffffffL & l) == (ulong) 0L)
+ break;
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddTwoStates(28, 29);
+ break;
+
+ case 29:
+ if (curChar == 92)
+ JjAddStates(29, 30);
+ break;
+ case 30:
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddTwoStates(28, 29);
+ break;
+ case 32:
+ if ((0x97ffffff87ffffffL & l) == (ulong)0L)
+ break;
+ if (kind > 23)
+ kind = 23;
+ JjCheckNAddTwoStates(33, 34);
+ break;
+ case 33:
+ if ((0x97ffffff87ffffffL & l) == (ulong)0L)
+ break;
+ if (kind > 23)
+ kind = 23;
+ JjCheckNAddTwoStates(33, 34);
+ break;
+ case 34:
+ if (curChar == 92)
+ JjCheckNAddTwoStates(35, 35);
+ break;
+ case 35:
+ if (kind > 23)
+ kind = 23;
+ JjCheckNAddTwoStates(33, 34);
+ break;
+ case 37:
+ JjAddStates(0, 2);
+ break;
+ case 39:
+ if (curChar == 92)
+ jjstateSet[jjnewStateCnt++] = 38;
+ break;
+ case 41:
+ if ((0x97ffffff87ffffffL & l) == (ulong)0L)
+ break;
+ if (kind > 20)
+ kind = 20;
+ JjCheckNAddStates(6, 10);
+ break;
+ case 42:
+ if ((0x97ffffff87ffffffL & l) == (ulong)0L)
+ break;
+ if (kind > 20)
+ kind = 20;
+ JjCheckNAddTwoStates(42, 43);
+ break;
+ case 43:
+ if (curChar == 92)
+ JjCheckNAddTwoStates(44, 44);
+ break;
+ case 44:
+ if (kind > 20)
+ kind = 20;
+ JjCheckNAddTwoStates(42, 43);
+ break;
+ case 45:
+ if ((0x97ffffff87ffffffL & l) != (ulong)0L)
+ JjCheckNAddStates(18, 20);
+ break;
+ case 46:
+ if (curChar == 92)
+ JjCheckNAddTwoStates(47, 47);
+ break;
+ case 47:
+ JjCheckNAddStates(18, 20);
+ break;
+ case 48:
+ if (curChar == 92)
+ JjCheckNAddStates(21, 23);
+ break;
+
+ default: break;
+
+ }
+ }
+ while (i != startsAt);
+ }
+ else
+ {
+ int hiByte = (int) (curChar >> 8);
+ int i1 = hiByte >> 6;
+ ulong l1 = (ulong) (1L << (hiByte & 63));
+ int i2 = (curChar & 0xff) >> 6;
+ ulong l2 = (ulong) (1L << (curChar & 63));
+ do
+ {
+ switch (jjstateSet[--i])
+ {
+
+ case 49:
+ case 33:
+ if (!JjCanMove_2(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 23)
+ kind = 23;
+ JjCheckNAddTwoStates(33, 34);
+ break;
+
+ case 0:
+ if (JjCanMove_0(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 7)
+ kind = 7;
+ }
+ if (JjCanMove_2(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 23)
+ kind = 23;
+ JjCheckNAddTwoStates(33, 34);
+ }
+ if (JjCanMove_2(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 20)
+ kind = 20;
+ JjCheckNAddStates(6, 10);
+ }
+ break;
+
+ case 15:
+ if (JjCanMove_0(hiByte, i1, i2, l1, l2) && kind > 13)
+ kind = 13;
+ break;
+ case 17:
+ case 19:
+ if (JjCanMove_1(hiByte, i1, i2, l1, l2))
+ JjCheckNAddStates(3, 5);
+ break;
+
+ case 25:
+ if (!JjCanMove_2(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddTwoStates(25, 26);
+ break;
+
+ case 27:
+ if (!JjCanMove_1(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddTwoStates(25, 26);
+ break;
+
+ case 28:
+ if (!JjCanMove_2(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddTwoStates(28, 29);
+ break;
+ case 30:
+ if (!JjCanMove_1(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 21)
+ kind = 21;
+ JjCheckNAddTwoStates(28, 29);
+ break;
+ case 32:
+ if (!JjCanMove_2(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 23)
+ kind = 23;
+ JjCheckNAddTwoStates(33, 34);
+ break;
+
+ case 35:
+ if (!JjCanMove_1(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 23)
+ kind = 23;
+ JjCheckNAddTwoStates(33, 34);
+ break;
+
+ case 37:
+ if (JjCanMove_1(hiByte, i1, i2, l1, l2))
+ JjAddStates(0, 2);
+ break;
+ case 41:
+ if (!JjCanMove_2(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 20)
+ kind = 20;
+ JjCheckNAddStates(6, 10);
+ break;
+ case 42:
+ if (!JjCanMove_2(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 20)
+ kind = 20;
+ JjCheckNAddTwoStates(42, 43);
+ break;
+ case 44:
+ if (!JjCanMove_1(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 20)
+ kind = 20;
+ JjCheckNAddTwoStates(42, 43);
+ break;
+ case 45:
+ if (JjCanMove_2(hiByte, i1, i2, l1, l2))
+ JjCheckNAddStates(18, 20);
+ break;
+
+ case 47:
+ if (JjCanMove_1(hiByte, i1, i2, l1, l2))
+ JjCheckNAddStates(18, 20);
+ break;
+
+ default: break;
+
+ }
+ }
+ while (i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 49 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try
+ {
+ curChar = input_stream.ReadChar();
+ }
+ catch (System.IO.IOException)
+ {
+ 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)
+ {
+ ulong l = (ulong) (1L << (int) curChar);
+ do
+ {
+ switch (jjstateSet[--i])
+ {
+
+ case 0:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 27)
+ kind = 27;
+ JjAddStates(31, 32);
+ break;
+
+ case 1:
+ if (curChar == 46)
+ JjCheckNAdd(2);
+ break;
+
+ case 2:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 27)
+ kind = 27;
+ JjCheckNAdd(2);
+ break;
+
+ default: break;
+
+ }
+ }
+ while (i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ 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 & 63);
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 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)
+ {
+ return curPos;
+ }
+ }
+ }
+ private int JjStopStringLiteralDfa_1(int pos, long active0)
+ {
+ switch (pos)
+ {
+
+ case 0:
+ if ((active0 & 0x10000000L) != 0L)
+ {
+ jjmatchedKind = 32;
+ return 6;
+ }
+ return - 1;
+
+ default:
+ return - 1;
+
+ }
+ }
+ private int JjStartNfa_1(int pos, long active0)
+ {
+ return JjMoveNfa_1(JjStopStringLiteralDfa_1(pos, active0), pos + 1);
+ }
+ private int JjMoveStringLiteralDfa0_1()
+ {
+ switch (curChar)
+ {
+
+ case (char)84:
+ return JjMoveStringLiteralDfa1_1(0x10000000L);
+
+ case (char)93:
+ return JjStopAtPos(0, 29);
+
+ case (char)125:
+ return JjStopAtPos(0, 30);
+
+ default:
+ return JjMoveNfa_1(0, 0);
+
+ }
+ }
+ private int JjMoveStringLiteralDfa1_1(long active0)
+ {
+ try
+ {
+ curChar = input_stream.ReadChar();
+ }
+ catch (System.IO.IOException)
+ {
+ JjStopStringLiteralDfa_1(0, active0);
+ return 1;
+ }
+ switch (curChar)
+ {
+
+ case (char) (79):
+ if ((active0 & 0x10000000L) != 0L)
+ return JjStartNfaWithStates_1(1, 28, 6);
+ break;
+
+ default:
+ break;
+
+ }
+ return JjStartNfa_1(0, active0);
+ }
+ private int JjStartNfaWithStates_1(int pos, int kind, int state)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ try
+ {
+ curChar = input_stream.ReadChar();
+ }
+ catch (System.IO.IOException)
+ {
+ return pos + 1;
+ }
+ return JjMoveNfa_1(state, pos + 1);
+ }
+ private int JjMoveNfa_1(int startState, int curPos)
+ {
+ int startsAt = 0;
+ jjnewStateCnt = 7;
+ 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 ((0xfffffffeffffffffL & l) != (ulong)0L)
+ {
+ if (kind > 32)
+ kind = 32;
+ JjCheckNAdd(6);
+ }
+ if ((0x100002600L & l) != 0L)
+ {
+ if (kind > 7)
+ kind = 7;
+ }
+ else if (curChar == 34)
+ JjCheckNAddTwoStates(2, 4);
+ break;
+
+ case 1:
+ if (curChar == 34)
+ JjCheckNAddTwoStates(2, 4);
+ break;
+
+ case 2:
+ if ((0xfffffffbffffffffL & l) != (ulong)0L)
+ JjCheckNAddStates(33, 35);
+ break;
+
+ case 3:
+ if (curChar == 34)
+ JjCheckNAddStates(33, 35);
+ break;
+
+ case 5:
+ if (curChar == 34 && kind > 31)
+ kind = 31;
+ break;
+
+ case 6:
+ if ((0xfffffffeffffffffL & l) == (ulong)0L)
+ break;
+ if (kind > 32)
+ kind = 32;
+ JjCheckNAdd(6);
+ break;
+
+ default: break;
+
+ }
+ }
+ while (i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ ulong l = (ulong) (1L << (curChar & 63));
+ do
+ {
+ switch (jjstateSet[--i])
+ {
+
+ case 0:
+ case 6:
+ if ((0xdfffffffdfffffffL & l) == (ulong)0L)
+ break;
+ if (kind > 32)
+ kind = 32;
+ JjCheckNAdd(6);
+ break;
+
+ case 2:
+ JjAddStates(33, 35);
+ break;
+
+ case 4:
+ if (curChar == 92)
+ jjstateSet[jjnewStateCnt++] = 3;
+ break;
+
+ default: break;
+
+ }
+ }
+ while (i != startsAt);
+ }
+ else
+ {
+ int hiByte = (int) (curChar >> 8);
+ int i1 = hiByte >> 6;
+ ulong l1 = (ulong) (1L << (hiByte & 63));
+ int i2 = (curChar & 0xff) >> 6;
+ ulong l2 = (ulong) (1L << (curChar & 63));
+ do
+ {
+ switch (jjstateSet[--i])
+ {
+
+ case 0:
+ if (JjCanMove_0(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 7)
+ kind = 7;
+ }
+ if (JjCanMove_1(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 32)
+ kind = 32;
+ JjCheckNAdd(6);
+ }
+ break;
+
+ case 2:
+ if (JjCanMove_1(hiByte, i1, i2, l1, l2))
+ JjAddStates(33, 35);
+ break;
+
+ case 6:
+ if (!JjCanMove_1(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 32)
+ kind = 32;
+ JjCheckNAdd(6);
+ break;
+
+ default: break;
+
+ }
+ }
+ while (i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 7 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try
+ {
+ curChar = input_stream.ReadChar();
+ }
+ catch (System.IO.IOException)
+ {
+ return curPos;
+ }
+ }
+ }
+ internal static readonly int[] jjnextStates = new int[]{
+ 37, 39, 40, 17, 18, 20, 42, 45, 31, 46, 43, 22, 23, 25, 26, 24,
+ 25, 26, 45, 31, 46, 44, 47, 35, 22, 28, 29, 27, 27, 30, 30, 0,
+ 1, 2, 4, 5
+ };
+ private static bool JjCanMove_0(int hiByte, int i1, int i2, ulong l1, ulong l2)
+ {
+ switch (hiByte)
+ {
+
+ case 48:
+ return ((jjbitVec0[i2] & l2) != (ulong) 0L);
+
+ default:
+ return false;
+
+ }
+ }
+ private static bool JjCanMove_1(int hiByte, int i1, int i2, ulong l1, ulong l2)
+ {
+ switch (hiByte)
+ {
+
+ case 0:
+ return ((jjbitVec3[i2] & l2) != (ulong) 0L);
+
+ default:
+ if ((jjbitVec1[i1] & l1) != (ulong) 0L)
+ return true;
+ return false;
+
+ }
+ }
+ private static bool JjCanMove_2(int hiByte, int i1, int i2, ulong l1, ulong l2)
+ {
+ switch (hiByte)
+ {
+
+ case 0:
+ return ((jjbitVec3[i2] & l2) != (ulong) 0L);
+
+ case 48:
+ return ((jjbitVec1[i2] & l2) != (ulong) 0L);
+
+ default:
+ if ((jjbitVec4[i1] & l1) != (ulong) 0L)
+ return true;
+ return false;
+
+ }
+ }
+
+ ///// <summary>Token literal values. </summary>
+ //public static readonly string[] jjstrLiteralImages = new string[] {
+ // "", null, null, null, null, null, null, null, null, null, null, "\x002B", "\x002D",
+ // "\x0028", "\x0029", "\x003A", "\x002A", "\x005E", null, null, null, null, null, "\x005B", "\x007B",
+ // null, "\x0054\x004F", "\x005D", null, null, "\x0054\x004F", "\x007D", null, null };
+
+
+ /// <summary>Token literal values. </summary>
+ public static readonly string[] jjstrLiteralImages = new string[]{
+ "", null, null, null, null, null, null, null, null, null, null, "\x002B", "\x002D",
+ null, "\x0028", "\x0029", "\x003A", "\x002A", "\x005E", null, null, null, null, null, null,
+ "\x005B", "\x007B", null, "\x0054\x004F", "\x005D", "\x007D", null, null };
+
+ /// <summary>Lexer state names. </summary>
+ public static readonly string[] lexStateNames = new string[] {
+ "Boost",
+ "Range",
+ "DEFAULT"
+ };
+
+ /// <summary>Lex State array. </summary>
+ public static readonly int[] jjnewLexState = new int[] {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1,
+ 1, 1, 2, -1, 2, 2, -1, -1
+ };
+ internal static readonly ulong[] jjtoToken = new ulong[] { 0x1ffffff01L };
+ internal static readonly long[] jjtoSkip = new long[] { 0x80L };
+ protected internal ICharStream input_stream;
+ private uint[] jjrounds = new uint[49];
+ private int[] jjstateSet = new int[98];
+ protected internal char curChar;
+ /// <summary>Constructor. </summary>
+ public QueryParserTokenManager(ICharStream stream)
+ {
+ InitBlock();
+ input_stream = stream;
+ }
+
+ /// <summary>Constructor. </summary>
+ public QueryParserTokenManager(ICharStream stream, int lexState):this(stream)
+ {
+ SwitchTo(lexState);
+ }
+
+ /// <summary>Reinitialise parser. </summary>
+ public virtual void ReInit(ICharStream stream)
+ {
+ jjmatchedPos = jjnewStateCnt = 0;
+ curLexState = defaultLexState;
+ input_stream = stream;
+ ReInitRounds();
+ }
+ private void ReInitRounds()
+ {
+ int i;
+ jjround = 0x80000001;
+ for (i = 49; i-- > 0; )
+ jjrounds[i] = 0x80000000;
+ }
+
+ /// <summary>Reinitialise parser. </summary>
+ public virtual void ReInit(ICharStream stream, int lexState)
+ {
+ ReInit(stream);
+ SwitchTo(lexState);
+ }
+
+ /// <summary>Switch to specified lex state. </summary>
+ public virtual void SwitchTo(int lexState)
+ {
+ if (lexState >= 3 || lexState < 0)
+ throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+ else
+ curLexState = lexState;
+ }
+
+ protected internal virtual Token JjFillToken()
+ {
+ Token t;
+ System.String curTokenImage;
+ int beginLine;
+ int endLine;
+ int beginColumn;
+ int endColumn;
+ System.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 = 2;
+ internal int defaultLexState = 2;
+ internal int jjnewStateCnt;
+ internal uint jjround;
+ internal int jjmatchedPos;
+ internal int jjmatchedKind;
+
+ /// <summary>Get the next Token. </summary>
+ [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
+ public virtual Token GetNextToken()
+ {
+ Token matchedToken;
+ int curPos = 0;
+
+ for (; ; )
+ {
+ try
+ {
+ curChar = input_stream.BeginToken();
+ }
+ catch (IOException)
+ {
+ 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;
+
+ case 2:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = JjMoveStringLiteralDfa0_2();
+ break;
+ }
+ if (jjmatchedKind != 0x7fffffff)
+ {
+ if (jjmatchedPos + 1 < curPos)
+ input_stream.Backup(curPos - jjmatchedPos - 1);
+ if ((jjtoToken[jjmatchedKind >> 6] & ((ulong) 1L << (jjmatchedKind & 63))) != (ulong) 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;
+ System.String error_after = null;
+ bool EOFSeen = false;
+ try
+ {
+ input_stream.ReadChar(); input_stream.Backup(1);
+ }
+ catch (IOException)
+ {
+ 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);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/679ad24c/src/Lucene.Net.QueryParser/Classic/Token.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Classic/Token.cs b/src/Lucene.Net.QueryParser/Classic/Token.cs
new file mode 100644
index 0000000..389e7b3
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Classic/Token.cs
@@ -0,0 +1,142 @@
+using System;
+
+namespace Lucene.Net.QueryParser.Classic
+{
+ /*
+ * 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/679ad24c/src/Lucene.Net.QueryParser/Classic/TokenMgrError.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Classic/TokenMgrError.cs b/src/Lucene.Net.QueryParser/Classic/TokenMgrError.cs
new file mode 100644
index 0000000..2f69e13
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Classic/TokenMgrError.cs
@@ -0,0 +1,170 @@
+using System;
+using System.Text;
+
+namespace Lucene.Net.QueryParser.Classic
+{
+ /*
+ * 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/679ad24c/src/Lucene.Net.QueryParser/ComplexPhrase/ComplexPhraseQueryParser.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/ComplexPhrase/ComplexPhraseQueryParser.cs b/src/Lucene.Net.QueryParser/ComplexPhrase/ComplexPhraseQueryParser.cs
new file mode 100644
index 0000000..0ac7c5b
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/ComplexPhrase/ComplexPhraseQueryParser.cs
@@ -0,0 +1,468 @@
+\ufeffusing Lucene.Net.Analysis;
+using Lucene.Net.Index;
+using Lucene.Net.QueryParser.Classic;
+using Lucene.Net.Search;
+using Lucene.Net.Search.Spans;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Lucene.Net.QueryParser.ComplexPhrase
+{
+ /*
+ * 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>
+ /// QueryParser which permits complex phrase query syntax eg "(john jon
+ /// jonathan~) peters*".
+ /// <p>
+ /// Performs potentially multiple passes over Query text to parse any nested
+ /// logic in PhraseQueries. - First pass takes any PhraseQuery content between
+ /// quotes and stores for subsequent pass. All other query content is parsed as
+ /// normal - Second pass parses any stored PhraseQuery content, checking all
+ /// embedded clauses are referring to the same field and therefore can be
+ /// rewritten as Span queries. All PhraseQuery clauses are expressed as
+ /// ComplexPhraseQuery objects
+ /// </p>
+ /// <p>
+ /// This could arguably be done in one pass using a new QueryParser but here I am
+ /// working within the constraints of the existing parser as a base class. This
+ /// currently simply feeds all phrase content through an analyzer to select
+ /// phrase terms - any "special" syntax such as * ~ * etc are not given special
+ /// status
+ /// </p>
+ /// </summary>
+ public class ComplexPhraseQueryParser : Classic.QueryParser
+ {
+ private List<ComplexPhraseQuery> complexPhrases = null;
+
+ private bool isPass2ResolvingPhrases;
+
+ /// <summary>
+ /// When <code>inOrder</code> is true, the search terms must
+ /// exists in the documents as the same order as in query.
+ /// Choose between ordered (true) or un-ordered (false) proximity search.
+ /// </summary>
+ public bool InOrder { get; set; }
+
+ private ComplexPhraseQuery currentPhraseQuery = null;
+
+ public ComplexPhraseQueryParser(LuceneVersion matchVersion, string f, Analyzer a)
+ : base(matchVersion, f, a)
+ {
+ // set property defaults
+ this.InOrder = true;
+ }
+
+ protected internal override Query GetFieldQuery(string field, string queryText, int slop)
+ {
+ ComplexPhraseQuery cpq = new ComplexPhraseQuery(field, queryText, slop, InOrder);
+ complexPhrases.Add(cpq); // add to list of phrases to be parsed once
+ // we
+ // are through with this pass
+ return cpq;
+ }
+
+ public override Query Parse(string query)
+ {
+ if (isPass2ResolvingPhrases)
+ {
+ MultiTermQuery.RewriteMethod oldMethod = MultiTermRewriteMethod;
+ try
+ {
+ // Temporarily force BooleanQuery rewrite so that Parser will
+ // generate visible
+ // collection of terms which we can convert into SpanQueries.
+ // ConstantScoreRewrite mode produces an
+ // opaque ConstantScoreQuery object which cannot be interrogated for
+ // terms in the same way a BooleanQuery can.
+ // QueryParser is not guaranteed threadsafe anyway so this temporary
+ // state change should not
+ // present an issue
+ MultiTermRewriteMethod = MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE;
+ return base.Parse(query);
+ }
+ finally
+ {
+ MultiTermRewriteMethod = oldMethod;
+ }
+ }
+
+ // First pass - parse the top-level query recording any PhraseQuerys
+ // which will need to be resolved
+ complexPhrases = new List<ComplexPhraseQuery>();
+ Query q = base.Parse(query);
+
+ // Perform second pass, using this QueryParser to parse any nested
+ // PhraseQueries with different
+ // set of syntax restrictions (i.e. all fields must be same)
+ isPass2ResolvingPhrases = true;
+ try
+ {
+ foreach (var currentPhraseQuery in complexPhrases)
+ {
+ this.currentPhraseQuery = currentPhraseQuery;
+ // in each phrase, now parse the contents between quotes as a
+ // separate parse operation
+ currentPhraseQuery.ParsePhraseElements(this);
+ }
+ }
+ finally
+ {
+ isPass2ResolvingPhrases = false;
+ }
+ return q;
+ }
+
+ // There is No "getTermQuery throws ParseException" method to override so
+ // unfortunately need
+ // to throw a runtime exception here if a term for another field is embedded
+ // in phrase query
+ protected override Query NewTermQuery(Term term)
+ {
+ if (isPass2ResolvingPhrases)
+ {
+ try
+ {
+ CheckPhraseClauseIsForSameField(term.Field);
+ }
+ catch (ParseException pe)
+ {
+ throw new Exception("Error parsing complex phrase", pe);
+ }
+ }
+ return base.NewTermQuery(term);
+ }
+
+ // Helper method used to report on any clauses that appear in query syntax
+ private void CheckPhraseClauseIsForSameField(string field)
+ {
+ if (!field.Equals(currentPhraseQuery.Field))
+ {
+ throw new ParseException("Cannot have clause for field \"" + field
+ + "\" nested in phrase " + " for field \"" + currentPhraseQuery.Field
+ + "\"");
+ }
+ }
+
+ protected internal override Query GetWildcardQuery(string field, string termStr)
+ {
+ if (isPass2ResolvingPhrases)
+ {
+ CheckPhraseClauseIsForSameField(field);
+ }
+ return base.GetWildcardQuery(field, termStr);
+ }
+
+ protected internal override Query GetRangeQuery(string field, string part1, string part2, bool startInclusive, bool endInclusive)
+ {
+ if (isPass2ResolvingPhrases)
+ {
+ CheckPhraseClauseIsForSameField(field);
+ }
+ return base.GetRangeQuery(field, part1, part2, startInclusive, endInclusive);
+ }
+
+ protected internal override Query NewRangeQuery(string field, string part1, string part2, bool startInclusive, bool endInclusive)
+ {
+ if (isPass2ResolvingPhrases)
+ {
+ // Must use old-style RangeQuery in order to produce a BooleanQuery
+ // that can be turned into SpanOr clause
+ TermRangeQuery rangeQuery = TermRangeQuery.NewStringRange(field, part1, part2, startInclusive, endInclusive);
+ rangeQuery.SetRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);
+ return rangeQuery;
+ }
+ return base.NewRangeQuery(field, part1, part2, startInclusive, endInclusive);
+ }
+
+ protected internal override Query GetFuzzyQuery(string field, string termStr, float minSimilarity)
+ {
+ if (isPass2ResolvingPhrases)
+ {
+ CheckPhraseClauseIsForSameField(field);
+ }
+ return base.GetFuzzyQuery(field, termStr, minSimilarity);
+ }
+
+ /// <summary>
+ /// Used to handle the query content in between quotes and produced Span-based
+ /// interpretations of the clauses.
+ /// </summary>
+ public class ComplexPhraseQuery : Query
+ {
+ private readonly string field;
+ private readonly string phrasedQueryStringContents;
+ private readonly int slopFactor;
+ private readonly bool inOrder;
+ private Query contents;
+
+ public ComplexPhraseQuery(string field, string phrasedQueryStringContents,
+ int slopFactor, bool inOrder)
+ {
+ this.field = field;
+ this.phrasedQueryStringContents = phrasedQueryStringContents;
+ this.slopFactor = slopFactor;
+ this.inOrder = inOrder;
+ }
+
+ public string Field
+ {
+ get { return field; }
+ }
+
+ // Called by ComplexPhraseQueryParser for each phrase after the main
+ // parse
+ // thread is through
+ protected internal void ParsePhraseElements(ComplexPhraseQueryParser qp)
+ {
+ // TODO ensure that field-sensitivity is preserved ie the query
+ // string below is parsed as
+ // field+":("+phrasedQueryStringContents+")"
+ // but this will need code in rewrite to unwrap the first layer of
+ // boolean query
+
+ string oldDefaultParserField = qp.Field;
+ try
+ {
+ //temporarily set the QueryParser to be parsing the default field for this phrase e.g author:"fred* smith"
+ qp.field = this.field;
+ contents = qp.Parse(phrasedQueryStringContents);
+ }
+ finally
+ {
+ qp.field = oldDefaultParserField;
+ }
+ }
+
+ public override Query Rewrite(IndexReader reader)
+ {
+ // ArrayList spanClauses = new ArrayList();
+ if (contents is TermQuery)
+ {
+ return contents;
+ }
+ // Build a sequence of Span clauses arranged in a SpanNear - child
+ // clauses can be complex
+ // Booleans e.g. nots and ors etc
+ int numNegatives = 0;
+ if (!(contents is BooleanQuery))
+ {
+ throw new ArgumentException("Unknown query type \""
+ + contents.GetType().Name
+ + "\" found in phrase query string \"" + phrasedQueryStringContents
+ + "\"");
+ }
+ BooleanQuery bq = (BooleanQuery)contents;
+ BooleanClause[] bclauses = bq.Clauses;
+ SpanQuery[] allSpanClauses = new SpanQuery[bclauses.Length];
+ // For all clauses e.g. one* two~
+ for (int i = 0; i < bclauses.Length; i++)
+ {
+ // HashSet bclauseterms=new HashSet();
+ Query qc = bclauses[i].Query;
+ // Rewrite this clause e.g one* becomes (one OR onerous)
+ qc = qc.Rewrite(reader);
+ if (bclauses[i].Occur_.Equals(BooleanClause.Occur.MUST_NOT))
+ {
+ numNegatives++;
+ }
+
+ if (qc is BooleanQuery)
+ {
+ List<SpanQuery> sc = new List<SpanQuery>();
+ AddComplexPhraseClause(sc, (BooleanQuery)qc);
+ if (sc.Count > 0)
+ {
+ allSpanClauses[i] = sc.ElementAt(0);
+ }
+ else
+ {
+ // Insert fake term e.g. phrase query was for "Fred Smithe*" and
+ // there were no "Smithe*" terms - need to
+ // prevent match on just "Fred".
+ allSpanClauses[i] = new SpanTermQuery(new Term(field,
+ "Dummy clause because no terms found - must match nothing"));
+ }
+ }
+ else
+ {
+ if (qc is TermQuery)
+ {
+ TermQuery tq = (TermQuery)qc;
+ allSpanClauses[i] = new SpanTermQuery(tq.Term);
+ }
+ else
+ {
+ throw new ArgumentException("Unknown query type \""
+ + qc.GetType().Name
+ + "\" found in phrase query string \""
+ + phrasedQueryStringContents + "\"");
+ }
+
+ }
+ }
+ if (numNegatives == 0)
+ {
+ // The simple case - no negative elements in phrase
+ return new SpanNearQuery(allSpanClauses, slopFactor, inOrder);
+ }
+ // Complex case - we have mixed positives and negatives in the
+ // sequence.
+ // Need to return a SpanNotQuery
+ List<SpanQuery> positiveClauses = new List<SpanQuery>();
+ for (int j = 0; j < allSpanClauses.Length; j++)
+ {
+ if (!bclauses[j].Occur_.Equals(BooleanClause.Occur.MUST_NOT))
+ {
+ positiveClauses.Add(allSpanClauses[j]);
+ }
+ }
+
+ SpanQuery[] includeClauses = positiveClauses
+ .ToArray();
+
+ SpanQuery include = null;
+ if (includeClauses.Length == 1)
+ {
+ include = includeClauses[0]; // only one positive clause
+ }
+ else
+ {
+ // need to increase slop factor based on gaps introduced by
+ // negatives
+ include = new SpanNearQuery(includeClauses, slopFactor + numNegatives,
+ inOrder);
+ }
+ // Use sequence of positive and negative values as the exclude.
+ SpanNearQuery exclude = new SpanNearQuery(allSpanClauses, slopFactor,
+ inOrder);
+ SpanNotQuery snot = new SpanNotQuery(include, exclude);
+ return snot;
+ }
+
+ private void AddComplexPhraseClause(List<SpanQuery> spanClauses, BooleanQuery qc)
+ {
+ List<SpanQuery> ors = new List<SpanQuery>();
+ List<SpanQuery> nots = new List<SpanQuery>();
+ BooleanClause[] bclauses = qc.Clauses;
+
+ // For all clauses e.g. one* two~
+ for (int i = 0; i < bclauses.Length; i++)
+ {
+ Query childQuery = bclauses[i].Query;
+
+ // select the list to which we will add these options
+ List<SpanQuery> chosenList = ors;
+ if (bclauses[i].Occur_ == BooleanClause.Occur.MUST_NOT)
+ {
+ chosenList = nots;
+ }
+
+ if (childQuery is TermQuery)
+ {
+ TermQuery tq = (TermQuery)childQuery;
+ SpanTermQuery stq = new SpanTermQuery(tq.Term);
+ stq.Boost = tq.Boost;
+ chosenList.Add(stq);
+ }
+ else if (childQuery is BooleanQuery)
+ {
+ BooleanQuery cbq = (BooleanQuery)childQuery;
+ AddComplexPhraseClause(chosenList, cbq);
+ }
+ else
+ {
+ // LUCENETODO alternatively could call extract terms here?
+ throw new ArgumentException("Unknown query type:"
+ + childQuery.GetType().Name);
+ }
+ }
+ if (ors.Count == 0)
+ {
+ return;
+ }
+ SpanOrQuery soq = new SpanOrQuery(ors
+ .ToArray());
+ if (nots.Count == 0)
+ {
+ spanClauses.Add(soq);
+ }
+ else
+ {
+ SpanOrQuery snqs = new SpanOrQuery(nots
+ .ToArray());
+ SpanNotQuery snq = new SpanNotQuery(soq, snqs);
+ spanClauses.Add(snq);
+ }
+ }
+
+ public override string ToString(string field)
+ {
+ return "\"" + phrasedQueryStringContents + "\"";
+ }
+
+ public override int GetHashCode()
+ {
+ int prime = 31;
+ int result = base.GetHashCode();
+ result = prime * result + ((field == null) ? 0 : field.GetHashCode());
+ result = prime
+ * result
+ + ((phrasedQueryStringContents == null) ? 0
+ : phrasedQueryStringContents.GetHashCode());
+ result = prime * result + slopFactor;
+ result = prime * result + (inOrder ? 1 : 0);
+ return result;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (GetType() != obj.GetType())
+ return false;
+ if (!base.Equals(obj))
+ {
+ return false;
+ }
+ ComplexPhraseQuery other = (ComplexPhraseQuery)obj;
+ if (field == null)
+ {
+ if (other.field != null)
+ return false;
+ }
+ else if (!field.Equals(other.field))
+ return false;
+ if (phrasedQueryStringContents == null)
+ {
+ if (other.phrasedQueryStringContents != null)
+ return false;
+ }
+ else if (!phrasedQueryStringContents
+ .Equals(other.phrasedQueryStringContents))
+ return false;
+ if (slopFactor != other.slopFactor)
+ return false;
+ return inOrder == other.inOrder;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/679ad24c/src/Lucene.Net.QueryParser/Ext/ExtendableQueryParser.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Ext/ExtendableQueryParser.cs b/src/Lucene.Net.QueryParser/Ext/ExtendableQueryParser.cs
new file mode 100644
index 0000000..6418f87
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Ext/ExtendableQueryParser.cs
@@ -0,0 +1,131 @@
+\ufeffusing Lucene.Net.Analysis;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using System;
+
+namespace Lucene.Net.QueryParser.Ext
+{
+ /*
+ * 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>
+ /// The <see cref="ExtendableQueryParser"/> enables arbitrary query parser extension
+ /// based on a customizable field naming scheme. The lucene query syntax allows
+ /// implicit and explicit field definitions as query prefix followed by a colon
+ /// (':') character. The <see cref="ExtendableQueryParser"/> allows to encode extension
+ /// keys into the field symbol associated with a registered instance of
+ /// <see cref="ParserExtension"/>. A customizable separation character separates the
+ /// extension key from the actual field symbol. The <see cref="ExtendableQueryParser"/>
+ /// splits (<see cref="Extensions.SplitExtensionField(String, String)"/>) the
+ /// extension key from the field symbol and tries to resolve the associated
+ /// <see cref="ParserExtension"/>. If the parser can't resolve the key or the field
+ /// token does not contain a separation character, <see cref="ExtendableQueryParser"/>
+ /// yields the same behavior as its super class <see cref="QueryParser"/>. Otherwise,
+ /// if the key is associated with a <see cref="ParserExtension"/> instance, the parser
+ /// builds an instance of <see cref="ExtensionQuery"/> to be processed by
+ /// <see cref="ParserExtension.Parse(ExtensionQuery)"/>.If a extension field does not
+ /// contain a field part the default field for the query will be used.
+ /// <p>
+ /// To guarantee that an extension field is processed with its associated
+ /// extension, the extension query part must escape any special characters like
+ /// '*' or '['. If the extension query contains any whitespace characters, the
+ /// extension query part must be enclosed in quotes.
+ /// Example ('_' used as separation character):
+ /// <pre>
+ /// title_customExt:"Apache Lucene\?" OR content_customExt:prefix\*
+ /// </pre>
+ ///
+ /// Search on the default field:
+ /// <pre>
+ /// _customExt:"Apache Lucene\?" OR _customExt:prefix\*
+ /// </pre>
+ /// </p>
+ /// <p>
+ /// The <see cref="ExtendableQueryParser"/> itself does not implement the logic how
+ /// field and extension key are separated or ordered. All logic regarding the
+ /// extension key and field symbol parsing is located in <see cref="Extensions"/>.
+ /// Customized extension schemes should be implemented by sub-classing
+ /// <see cref="Extensions"/>.
+ /// </p>
+ /// <p>
+ /// For details about the default encoding scheme see <see cref="Extensions"/>.
+ /// </p>
+ ///
+ /// <see cref="Extensions"/>
+ /// <see cref="ParserExtension"/>
+ /// <see cref="ExtensionQuery"/>
+ /// </summary>
+ public class ExtendableQueryParser : Classic.QueryParser
+ {
+ private readonly string defaultField;
+ private readonly Extensions extensions;
+
+
+ /// <summary>
+ /// Default empty extensions instance
+ /// </summary>
+ private static readonly Extensions DEFAULT_EXTENSION = new Extensions();
+
+ /// <summary>
+ /// Creates a new <see cref="ExtendableQueryParser"/> instance
+ /// </summary>
+ /// <param name="matchVersion">the lucene version to use.</param>
+ /// <param name="f">the default query field</param>
+ /// <param name="a">the analyzer used to find terms in a query string</param>
+ public ExtendableQueryParser(LuceneVersion matchVersion, string f, Analyzer a)
+ : base(matchVersion, f, a)
+ {
+ }
+
+ /// <summary>
+ /// Creates a new <see cref="ExtendableQueryParser"/> instance
+ /// </summary>
+ /// <param name="matchVersion">the lucene version to use.</param>
+ /// <param name="f">the default query field</param>
+ /// <param name="a">the analyzer used to find terms in a query string</param>
+ /// <param name="ext">the query parser extensions</param>
+ public ExtendableQueryParser(LuceneVersion matchVersion, string f, Analyzer a, Extensions ext)
+ : base(matchVersion, f, a)
+ {
+ this.defaultField = f;
+ this.extensions = ext;
+ }
+
+ /// <summary>
+ /// Returns the extension field delimiter character.
+ /// </summary>
+ /// <returns>the extension field delimiter character.</returns>
+ public char ExtensionFieldDelimiter
+ {
+ get { return extensions.ExtensionFieldDelimiter; }
+ }
+
+ protected internal override Query GetFieldQuery(string field, string queryText, bool quoted)
+ {
+ Tuple<string, string> splitExtensionField = this.extensions
+ .SplitExtensionField(defaultField, field);
+ ParserExtension extension = this.extensions
+ .GetExtension(splitExtensionField.Item2);
+ if (extension != null)
+ {
+ return extension.Parse(new ExtensionQuery(this, splitExtensionField.Item1,
+ queryText));
+ }
+ return base.GetFieldQuery(field, queryText, quoted);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/679ad24c/src/Lucene.Net.QueryParser/Ext/ExtensionQuery.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Ext/ExtensionQuery.cs b/src/Lucene.Net.QueryParser/Ext/ExtensionQuery.cs
new file mode 100644
index 0000000..610e4ad
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Ext/ExtensionQuery.cs
@@ -0,0 +1,54 @@
+\ufeffnamespace Lucene.Net.QueryParser.Ext
+{
+ /*
+ * 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>
+ /// <see cref="ExtensionQuery"/> holds all query components extracted from the original
+ /// query string like the query field and the extension query string.
+ /// </summary>
+ public class ExtensionQuery
+ {
+ /// <summary>
+ /// Creates a new <see cref="ExtensionQuery"/>
+ /// </summary>
+ /// <param name="topLevelParser"></param>
+ /// <param name="field">the query field</param>
+ /// <param name="rawQueryString">the raw extension query string</param>
+ public ExtensionQuery(Classic.QueryParser topLevelParser, string field, string rawQueryString)
+ {
+ this.Field = field;
+ this.RawQueryString = rawQueryString;
+ this.TopLevelParser = topLevelParser;
+ }
+
+ /// <summary>
+ /// Returns the query field
+ /// </summary>
+ public string Field { get; protected set; }
+
+ /// <summary>
+ /// Returns the raw extension query string
+ /// </summary>
+ public string RawQueryString { get; protected set; }
+
+ /// <summary>
+ /// Returns the top level parser which created this <see cref="ExtensionQuery"/>
+ /// </summary>
+ public Classic.QueryParser TopLevelParser { get; protected set; }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/679ad24c/src/Lucene.Net.QueryParser/Ext/Extensions.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Ext/Extensions.cs b/src/Lucene.Net.QueryParser/Ext/Extensions.cs
new file mode 100644
index 0000000..6895268
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Ext/Extensions.cs
@@ -0,0 +1,167 @@
+\ufeffusing Lucene.Net.QueryParser.Classic;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Lucene.Net.QueryParser.Ext
+{
+ /*
+ * 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 class Extensions
+ {
+ private readonly IDictionary<string, ParserExtension> extensions = new Dictionary<string, ParserExtension>();
+ private readonly char extensionFieldDelimiter;
+
+ /// <summary>
+ /// The default extension field delimiter character. This constant is set to ':'
+ /// </summary>
+ public static readonly char DEFAULT_EXTENSION_FIELD_DELIMITER = ':';
+
+ /// <summary>
+ /// Creates a new <see cref="Extensions"/> instance with the
+ /// <see cref="#DEFAULT_EXTENSION_FIELD_DELIMITER"/> as a delimiter character.
+ /// </summary>
+ public Extensions()
+ : this(DEFAULT_EXTENSION_FIELD_DELIMITER)
+ {
+ }
+
+ /// <summary>
+ /// Creates a new <see cref="Extensions"/> instance
+ /// </summary>
+ /// <param name="extensionFieldDelimiter">the extensions field delimiter character</param>
+ public Extensions(char extensionFieldDelimiter)
+ {
+ this.extensionFieldDelimiter = extensionFieldDelimiter;
+ }
+
+ /// <summary>
+ /// Adds a new <see cref="ParserExtension"/> instance associated with the given key.
+ /// </summary>
+ /// <param name="key">the parser extension key</param>
+ /// <param name="extension">the parser extension</param>
+ public virtual void Add(string key, ParserExtension extension)
+ {
+ this.extensions[key] = extension;
+ }
+
+ /// <summary>
+ /// Returns the <see cref="ParserExtension"/> instance for the given key or
+ /// <code>null</code> if no extension can be found for the key.
+ /// </summary>
+ /// <param name="key">the extension key</param>
+ /// <returns>the <see cref="ParserExtension"/> instance for the given key or
+ /// <code>null</code> if no extension can be found for the key.</returns>
+ public ParserExtension GetExtension(string key)
+ {
+ if (key == null || !this.extensions.ContainsKey(key)) return null;
+ return this.extensions[key];
+ }
+
+ /// <summary>
+ /// Returns the extension field delimiter
+ /// </summary>
+ public virtual char ExtensionFieldDelimiter
+ {
+ get { return extensionFieldDelimiter; }
+ }
+
+ /// <summary>
+ /// Splits a extension field and returns the field / extension part as a
+ /// <see cref="Tuple{String,String}"/>. This method tries to split on the first occurrence of the
+ /// extension field delimiter, if the delimiter is not present in the string
+ /// the result will contain a <code>null</code> value for the extension key and
+ /// the given field string as the field value. If the given extension field
+ /// string contains no field identifier the result pair will carry the given
+ /// default field as the field value.
+ /// </summary>
+ /// <param name="defaultField">the default query field</param>
+ /// <param name="field">the extension field string</param>
+ /// <returns>a {<see cref="Tuple{String,String}"/> with the field name as the <see cref="Tuple{String,String}.Item1"/> and the
+ /// extension key as the <see cref="Tuple{String,String}.Item2"/></returns>
+ public Tuple<string, string> SplitExtensionField(string defaultField, string field)
+ {
+ int indexOf = field.IndexOf(this.extensionFieldDelimiter);
+ if (indexOf < 0)
+ return new Tuple<string, string>(field, null);
+ string indexField = indexOf == 0 ? defaultField : field.Substring(0, indexOf);
+ string extensionKey = field.Substring(indexOf + 1);
+ return new Tuple<string, string>(indexField, extensionKey);
+ }
+
+ /// <summary>
+ /// Escapes an extension field. The default implementation is equivalent to
+ /// <see cref="QueryParser.Escape(String)"/>.
+ /// </summary>
+ /// <param name="extfield">the extension field identifier</param>
+ /// <returns>the extension field identifier with all special chars escaped with
+ /// a backslash character.</returns>
+ public string EscapeExtensionField(string extfield)
+ {
+ return QueryParserBase.Escape(extfield);
+ }
+
+ /// <summary>
+ /// Builds an extension field string from a given extension key and the default
+ /// query field. The default field and the key are delimited with the extension
+ /// field delimiter character. This method makes no assumption about the order
+ /// of the extension key and the field. By default the extension key is
+ /// appended to the end of the returned string while the field is added to the
+ /// beginning. Special Query characters are escaped in the result.
+ /// <p>
+ /// Note: <see cref="Extensions"/> subclasses must maintain the contract between
+ /// <see cref="M:BuildExtensionField(String)"/> and
+ /// <see cref="M:BuildExtensionField(String, String)"/> where the latter inverts the
+ /// former.
+ /// </p>
+ /// </summary>
+ /// <param name="extensionKey">the extension key</param>
+ /// <returns>escaped extension field identifier</returns>
+ public string BuildExtensionField(string extensionKey)
+ {
+ return BuildExtensionField(extensionKey, "");
+ }
+
+ /// <summary>
+ /// Builds an extension field string from a given extension key and the default
+ /// query field. The default field and the key are delimited with the extension
+ /// field delimiter character. This method makes no assumption about the order
+ /// of the extension key and the field. By default the extension key is
+ /// appended to the end of the returned string while the field is added to the
+ /// beginning. Special Query characters are escaped in the result.
+ /// <p>
+ /// Note: <see cref="Extensions"/> subclasses must maintain the contract between
+ /// <see cref="M:BuildExtensionField(String)"/> and
+ /// <see cref="M:BuildExtensionField(String, String)"/> where the latter inverts the
+ /// former.
+ /// </summary>
+ /// <param name="extensionKey">the extension key</param>
+ /// <param name="field">the field to apply the extension on.</param>
+ /// <returns>escaped extension field identifier</returns>
+ /// <remarks>See <see cref="M:BuildExtensionField(String)"/> to use the default query field</remarks>
+ public string BuildExtensionField(string extensionKey, string field)
+ {
+ StringBuilder builder = new StringBuilder(field);
+ builder.Append(this.extensionFieldDelimiter);
+ builder.Append(extensionKey);
+ return EscapeExtensionField(builder.ToString());
+ }
+
+ // NOTE: Pair<T, T> was eliminated in favor of the built in Tuple<T, T> type.
+ }
+}