|
|
@@ -10,12 +10,18 @@
|
|
|
// did not, you can find it at http://www.gnu.org
|
|
|
//
|
|
|
|
|
|
-#include "sphinxquery.h"
|
|
|
-
|
|
|
+#include "xqparser.h"
|
|
|
+#include "parse_helper.h"
|
|
|
#include "sphinxplugin.h"
|
|
|
#include "tokenizer/tokenizer.h"
|
|
|
#include "dict/dict_base.h"
|
|
|
-#include "xqparser.h"
|
|
|
+#include "xqdebug.h"
|
|
|
+
|
|
|
+//////////////////////////////////////////////////////////////////////////
|
|
|
+// EXTENDED PARSER RELOADED
|
|
|
+//////////////////////////////////////////////////////////////////////////
|
|
|
+class XQParser_t;
|
|
|
+#include "bissphinxquery.h"
|
|
|
|
|
|
static bool g_bOnlyNotAllowed = false;
|
|
|
|
|
|
@@ -45,13 +51,102 @@ bool HasMissedField ( const XQLimitSpec_t & tSpec )
|
|
|
{
|
|
|
return (tSpec.m_dFieldMask.TestAll ( false ) && tSpec.m_iFieldMaxPos == 0 && !tSpec.m_bZoneSpan && tSpec.m_dZones.GetLength() == 0);
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
-// EXTENDED PARSER RELOADED
|
|
|
-//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
+class XQParser_t : public XQParseHelper_c
|
|
|
+{
|
|
|
+ friend void yyerror ( XQParser_t * pParser, const char * sMessage );
|
|
|
+
|
|
|
+ friend int yyparse (XQParser_t * pParser);
|
|
|
+
|
|
|
+public:
|
|
|
+ XQParser_t();
|
|
|
+ ~XQParser_t() override;
|
|
|
+
|
|
|
+public:
|
|
|
+ bool Parse ( XQQuery_t & tQuery, const char * sQuery, const CSphQuery * pQuery, const TokenizerRefPtr_c & pTokenizer, const CSphSchema * pSchema, const DictRefPtr_c & pDict, const CSphIndexSettings & tSettings, const CSphBitvec * pMorphFields );
|
|
|
+ int ParseZone ( const char * pZone );
|
|
|
+
|
|
|
+ bool IsSpecial ( char c );
|
|
|
+ bool GetNumber ( const char * p, const char * sRestart );
|
|
|
+ int GetToken ( YYSTYPE * lvalp );
|
|
|
+
|
|
|
+ void HandleModifiers ( XQKeyword_t & tKeyword ) const noexcept;
|
|
|
+
|
|
|
+ void AddQuery ( XQNode_t * pNode );
|
|
|
+ XQNode_t * AddKeyword ( const char * sKeyword, int iSkippedPosBeforeToken=0 );
|
|
|
+ XQNode_t * AddKeyword ( XQNode_t * pLeft, XQNode_t * pRight );
|
|
|
+ XQNode_t * AddOp ( XQOperator_e eOp, XQNode_t * pLeft, XQNode_t * pRight, int iOpArg=0 );
|
|
|
+ void SetPhrase ( XQNode_t * pNode, bool bSetExact );
|
|
|
+ void PhraseShiftQpos ( XQNode_t * pNode );
|
|
|
+
|
|
|
+ void Cleanup () override;
|
|
|
+
|
|
|
+ void SetFieldSpec ( const FieldMask_t& uMask, int iMaxPos )
|
|
|
+ {
|
|
|
+ FixRefSpec();
|
|
|
+ m_dStateSpec.Last()->SetFieldSpec ( uMask, iMaxPos );
|
|
|
+ }
|
|
|
+ void SetZoneVec ( int iZoneVec, bool bZoneSpan = false )
|
|
|
+ {
|
|
|
+ FixRefSpec();
|
|
|
+ m_dStateSpec.Last()->SetZoneSpec ( m_dZoneVecs[iZoneVec], bZoneSpan );
|
|
|
+ }
|
|
|
+
|
|
|
+ void FixRefSpec ()
|
|
|
+ {
|
|
|
+ bool bRef = ( m_dStateSpec.GetLength()>1 && ( m_dStateSpec[m_dStateSpec.GetLength()-1]==m_dStateSpec[m_dStateSpec.GetLength()-2] ) );
|
|
|
+ if ( !bRef )
|
|
|
+ return;
|
|
|
+
|
|
|
+ XQLimitSpec_t * pSpec = m_dStateSpec.Pop();
|
|
|
+ m_dSpecPool.Add ( new XQLimitSpec_t ( *pSpec ) );
|
|
|
+ m_dStateSpec.Add ( m_dSpecPool.Last() );
|
|
|
+ }
|
|
|
+
|
|
|
+public:
|
|
|
+ const CSphVector<int> & GetZoneVec ( int iZoneVec ) const
|
|
|
+ {
|
|
|
+ return m_dZoneVecs[iZoneVec];
|
|
|
+ }
|
|
|
+
|
|
|
+public:
|
|
|
+ BYTE * m_sQuery = nullptr;
|
|
|
+ int m_iQueryLen = 0;
|
|
|
+ const char * m_pErrorAt = nullptr;
|
|
|
+
|
|
|
+ XQNode_t * m_pRoot = nullptr;
|
|
|
+
|
|
|
+ int m_iPendingNulls = 0;
|
|
|
+ int m_iPendingType = 0;
|
|
|
+ YYSTYPE m_tPendingToken;
|
|
|
+ bool m_bWasKeyword = false;
|
|
|
+
|
|
|
+ bool m_bEmpty = false;
|
|
|
+ bool m_bQuoted = false;
|
|
|
+ int m_iOvershortStep = 0;
|
|
|
+
|
|
|
+ int m_iQuorumQuote = -1;
|
|
|
+ int m_iQuorumFSlash = -1;
|
|
|
+ bool m_bCheckNumber = false;
|
|
|
+
|
|
|
+ StrVec_t m_dIntTokens;
|
|
|
+
|
|
|
+ CSphVector < CSphVector<int> > m_dZoneVecs;
|
|
|
+ CSphVector<XQLimitSpec_t *> m_dStateSpec;
|
|
|
+ CSphVector<XQLimitSpec_t *> m_dSpecPool;
|
|
|
+ IntVec_t m_dPhraseStar;
|
|
|
+
|
|
|
+protected:
|
|
|
+ bool HandleFieldBlockStart ( const char * & pPtr ) override;
|
|
|
+
|
|
|
+private:
|
|
|
+ XQNode_t * ParseRegex ( const char * pStart );
|
|
|
+};
|
|
|
+
|
|
|
+//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
static int yylex ( YYSTYPE * lvalp, XQParser_t * pParser )
|
|
|
{
|
|
|
@@ -946,3 +1041,54 @@ bool XQParser_t::HandleFieldBlockStart ( const char * & pPtr )
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
+bool sphParseExtendedQuery ( XQQuery_t & tParsed, const char * sQuery, const CSphQuery * pQuery, const TokenizerRefPtr_c& pTokenizer, const CSphSchema * pSchema, const DictRefPtr_c& pDict, const CSphIndexSettings & tSettings, const CSphBitvec * pMorphFields )
|
|
|
+{
|
|
|
+ XQParser_t qp;
|
|
|
+ bool bRes = qp.Parse ( tParsed, sQuery, pQuery, pTokenizer, pSchema, pDict, tSettings, pMorphFields );
|
|
|
+
|
|
|
+#ifndef NDEBUG
|
|
|
+ if ( bRes && tParsed.m_pRoot )
|
|
|
+ tParsed.m_pRoot->Check ( true );
|
|
|
+#endif
|
|
|
+
|
|
|
+#if XQDEBUG
|
|
|
+ if ( bRes )
|
|
|
+ {
|
|
|
+ printf ( "\n--- query ---\n" );
|
|
|
+ printf ( "%s\n", sQuery );
|
|
|
+ xqDump ( tParsed.m_pRoot, 0 );
|
|
|
+ DotDump ( tParsed.m_pRoot );
|
|
|
+ printf ( "\n--- query reconstructed ---\n" );
|
|
|
+ printf ( "%s\n", sphReconstructNode ( tParsed.m_pRoot ).cstr());
|
|
|
+ printf ( "---\n" );
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ // moved here from ranker creation
|
|
|
+ // as at that point term expansion could produce many terms from expanded term and this condition got failed
|
|
|
+ tParsed.m_bSingleWord = ( tParsed.m_pRoot && tParsed.m_pRoot->dChildren().IsEmpty() && tParsed.m_pRoot->dWords().GetLength()==1 );
|
|
|
+ tParsed.m_bEmpty = qp.m_bEmpty;
|
|
|
+
|
|
|
+ return bRes;
|
|
|
+}
|
|
|
+
|
|
|
+class QueryParserPlain_c : public QueryParser_i
|
|
|
+{
|
|
|
+public:
|
|
|
+ bool IsFullscan ( const XQQuery_t & tQuery ) const override { return false; }
|
|
|
+ bool ParseQuery ( XQQuery_t & tParsed, const char * sQuery, const CSphQuery * pQuery, TokenizerRefPtr_c pQueryTokenizer, TokenizerRefPtr_c pQueryTokenizerJson, const CSphSchema * pSchema, const DictRefPtr_c& pDict, const CSphIndexSettings & tSettings, const CSphBitvec * pMorphFields ) const override;
|
|
|
+ QueryParser_i * Clone() const final { return new QueryParserPlain_c; }
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+bool QueryParserPlain_c::ParseQuery ( XQQuery_t & tParsed, const char * sQuery, const CSphQuery * pQuery, TokenizerRefPtr_c pQueryTokenizer, TokenizerRefPtr_c, const CSphSchema * pSchema, const DictRefPtr_c& pDict, const CSphIndexSettings & tSettings, const CSphBitvec * pMorphFields ) const
|
|
|
+{
|
|
|
+ return sphParseExtendedQuery ( tParsed, sQuery, pQuery, pQueryTokenizer, pSchema, pDict, tSettings, pMorphFields );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+std::unique_ptr<QueryParser_i> sphCreatePlainQueryParser()
|
|
|
+{
|
|
|
+ return std::make_unique<QueryParserPlain_c>();
|
|
|
+}
|