1 %{ 2 #if USE_WINDOWS 3 #pragma warning(push,1) 4 #endif 5 %} 6 7 %lex-param { XQParser_t * pParser } 8 %parse-param { XQParser_t * pParser } 9 %pure-parser 10 %error-verbose 11 12 %union { 13 XQNode_t * pNode; // tree node 14 struct 15 { 16 int iValue; 17 int iStrIndex; 18 float fValue; 19 } tInt; 20 struct // field spec 21 { 22 FieldMask_t dMask; // acceptable fields mask 23 int iMaxPos; // max allowed position within field 24 } tFieldLimit; 25 int iZoneVec; 26 }; 27 28 %token <pNode> TOK_KEYWORD 29 %token <tInt> TOK_NEAR 30 %token <tInt> TOK_INT 31 %token <tInt> TOK_FLOAT 32 %token <tFieldLimit> TOK_FIELDLIMIT 33 %token <iZoneVec> TOK_ZONE 34 %token <iZoneVec> TOK_ZONESPAN 35 %token TOK_BEFORE 36 %token TOK_SENTENCE 37 %token TOK_PARAGRAPH 38 %token TOK_MAYBE 39 %type <pNode> keyword 40 %type <pNode> phrasetoken 41 %type <pNode> phrase 42 %type <pNode> sp_item 43 %type <pNode> sentence 44 %type <pNode> paragraph 45 %type <pNode> atom 46 %type <pNode> orlist 47 %type <pNode> orlistf 48 %type <pNode> beforelist 49 %type <pNode> expr 50 51 %left TOK_BEFORE TOK_NEAR 52 53 %% 54 55 query: 56 expr { pParser->AddQuery ( $1 ); } 57 ; 58 59 expr: 60 beforelist { $$ = $1; } 61 | expr beforelist { $$ = pParser->AddOp ( SPH_QUERY_AND, $1, $2 ); } 62 ; 63 64 tok_limiter: 65 // empty 66 | TOK_FIELDLIMIT { pParser->SetFieldSpec ( $1.dMask, $1.iMaxPos ); } 67 | TOK_ZONE { pParser->SetZoneVec ( $1 ); } 68 | TOK_ZONESPAN { pParser->SetZoneVec ( $1, true ); } 69 ; 70 71 beforelist: 72 orlistf { $$ = $1; } 73 | beforelist TOK_BEFORE orlistf { $$ = pParser->AddOp ( SPH_QUERY_BEFORE, $1, $3 ); } 74 | beforelist TOK_NEAR orlistf { $$ = pParser->AddOp ( SPH_QUERY_NEAR, $1, $3, $2.iValue ); } 75 ; 76 77 orlistf: 78 orlist { $$ = $1; } 79 | tok_limiter '-' orlist { $$ = pParser->AddOp ( SPH_QUERY_NOT, $3, NULL ); } 80 | tok_limiter '!' orlist { $$ = pParser->AddOp ( SPH_QUERY_NOT, $3, NULL ); } 81 ; 82 83 orlist: 84 tok_limiter atom { $$ = $2; } 85 | orlist '|' tok_limiter atom { $$ = pParser->AddOp ( SPH_QUERY_OR, $1, $4 ); } 86 | orlist TOK_MAYBE tok_limiter atom { $$ = pParser->AddOp ( SPH_QUERY_MAYBE, $1, $4 ); } 87 ; 88 89 atom: 90 keyword { $$ = $1; } 91 | sentence { $$ = $1; } 92 | paragraph { $$ = $1; } 93 | '"' '"' { $$ = NULL; } 94 | '"' '"' '~' TOK_INT { $$ = NULL; } 95 | '"' '"' '/' TOK_INT { $$ = NULL; } 96 | '"' '"' '/' TOK_FLOAT { $$ = NULL; } 97 | '"' phrase '"' { $$ = $2; pParser->SetPhrase ( $$, false ); } 98 | '"' phrase '"' '~' TOK_INT { $$ = $2; if ( $$ ) { assert ( $$->m_dWords.GetLength() ); $$->SetOp ( SPH_QUERY_PROXIMITY ); $$->m_iOpArg = $5.iValue; pParser->m_iAtomPos = $$->FixupAtomPos(); } } 99 | '"' phrase '"' '/' TOK_INT { $$ = $2; if ( $$ ) { assert ( $$->m_dWords.GetLength() ); $$->SetOp ( SPH_QUERY_QUORUM ); $$->m_iOpArg = $5.iValue; } } 100 | '"' phrase '"' '/' TOK_FLOAT { $$ = $2; if ( $$ ) { assert ( $$->m_dWords.GetLength() ); $$->SetOp ( SPH_QUERY_QUORUM ); $$->m_iOpArg = $5.fValue * 100; $$->m_bPercentOp = true; } } 101 | '(' expr ')' { $$ = $2; } 102 | '=' '"' phrase '"' { $$ = $3; pParser->SetPhrase ( $$, true ); } 103 ; 104 105 keyword: 106 TOK_KEYWORD { $$ = $1; } 107 | TOK_INT { $$ = pParser->AddKeyword ( ( $1.iStrIndex>=0 ) ? pParser->m_dIntTokens[$1.iStrIndex].cstr() : NULL ); } 108 | TOK_FLOAT { $$ = pParser->AddKeyword ( ( $1.iStrIndex>=0 ) ? pParser->m_dIntTokens[$1.iStrIndex].cstr() : NULL ); } 109 | '=' keyword { $$ = $2; assert ( $$->m_dWords.GetLength()==1 ); if ( !($$->m_dWords[0].m_sWord.IsEmpty()) ) $$->m_dWords[0].m_sWord.SetSprintf ( "=%s", $$->m_dWords[0].m_sWord.cstr() ); } 110 ; 111 112 sentence: 113 sp_item TOK_SENTENCE sp_item { $$ = pParser->AddOp ( SPH_QUERY_SENTENCE, $1, $3 ); } 114 | sentence TOK_SENTENCE sp_item { $$ = pParser->AddOp ( SPH_QUERY_SENTENCE, $1, $3 ); } 115 ; 116 117 paragraph: 118 sp_item TOK_PARAGRAPH sp_item { $$ = pParser->AddOp ( SPH_QUERY_PARAGRAPH, $1, $3 ); } 119 | paragraph TOK_PARAGRAPH sp_item { $$ = pParser->AddOp ( SPH_QUERY_PARAGRAPH, $1, $3 ); } 120 ; 121 122 sp_item: 123 keyword { $$ = $1; } 124 | '"' phrase '"' { $$ = $2; if ( $$ ) { assert ( $$->m_dWords.GetLength() ); $$->SetOp ( SPH_QUERY_PHRASE); } } 125 ; 126 127 phrase: 128 phrasetoken { $$ = $1; } 129 | phrase phrasetoken { $$ = pParser->AddKeyword ( $1, $2 ); } 130 ; 131 132 phrasetoken: 133 keyword { $$ = $1; } 134 | '(' { $$ = NULL; } 135 | ')' { $$ = NULL; } 136 | '-' { $$ = NULL; } 137 | '|' { $$ = NULL; } 138 | '~' { $$ = NULL; } 139 | '/' { $$ = NULL; } 140 ; 141 142 143 %% 144 145 #if USE_WINDOWS 146 #pragma warning(pop) 147 #endif 148