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