1 /*
2 ** 2014 May 31
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 ******************************************************************************
12 **
13 */
14 
15 
16 // All token codes are small integers with #defines that begin with "TK_"
17 %token_prefix FTS5_
18 
19 // The type of the data attached to each token is Token.  This is also the
20 // default type for non-terminals.
21 //
22 %token_type {Fts5Token}
23 %default_type {Fts5Token}
24 
25 // The generated parser function takes a 4th argument as follows:
26 %extra_argument {Fts5Parse *pParse}
27 
28 // This code runs whenever there is a syntax error
29 //
30 %syntax_error {
31   UNUSED_PARAM(yymajor); /* Silence a compiler warning */
32   sqlite3Fts5ParseError(
33     pParse, "fts5: syntax error near \"%.*s\"",TOKEN.n,TOKEN.p
34   );
35 }
36 %stack_overflow {
37   sqlite3Fts5ParseError(pParse, "fts5: parser stack overflow");
38 }
39 
40 // The name of the generated procedure that implements the parser
41 // is as follows:
42 %name sqlite3Fts5Parser
43 
44 // The following text is included near the beginning of the C source
45 // code file that implements the parser.
46 //
47 %include {
48 #include "fts5Int.h"
49 #include "fts5parse.h"
50 
51 /*
52 ** Disable all error recovery processing in the parser push-down
53 ** automaton.
54 */
55 #define YYNOERRORRECOVERY 1
56 
57 /*
58 ** Make yytestcase() the same as testcase()
59 */
60 #define yytestcase(X) testcase(X)
61 
62 /*
63 ** Indicate that sqlite3ParserFree() will never be called with a null
64 ** pointer.
65 */
66 #define YYPARSEFREENOTNULL 1
67 
68 /*
69 ** Alternative datatype for the argument to the malloc() routine passed
70 ** into sqlite3ParserAlloc().  The default is size_t.
71 */
72 #define YYMALLOCARGTYPE  u64
73 
74 } // end %include
75 
76 %left OR.
77 %left AND.
78 %left NOT.
79 %left TERM.
80 %left COLON.
81 
82 input ::= expr(X). { sqlite3Fts5ParseFinished(pParse, X); }
83 %destructor input { (void)pParse; }
84 
85 %type cnearset    {Fts5ExprNode*}
86 %type expr        {Fts5ExprNode*}
87 %type exprlist    {Fts5ExprNode*}
88 %destructor cnearset { sqlite3Fts5ParseNodeFree($$); }
89 %destructor expr     { sqlite3Fts5ParseNodeFree($$); }
90 %destructor exprlist { sqlite3Fts5ParseNodeFree($$); }
91 
92 %type colset {Fts5Colset*}
93 %destructor colset { sqlite3_free($$); }
94 %type colsetlist {Fts5Colset*}
95 %destructor colsetlist { sqlite3_free($$); }
96 
colset(A)97 colset(A) ::= MINUS LCP colsetlist(X) RCP. {
98     A = sqlite3Fts5ParseColsetInvert(pParse, X);
99 }
colset(A)100 colset(A) ::= LCP colsetlist(X) RCP. { A = X; }
colset(A)101 colset(A) ::= STRING(X). {
102   A = sqlite3Fts5ParseColset(pParse, 0, &X);
103 }
colset(A)104 colset(A) ::= MINUS STRING(X). {
105   A = sqlite3Fts5ParseColset(pParse, 0, &X);
106   A = sqlite3Fts5ParseColsetInvert(pParse, A);
107 }
108 
colsetlist(A)109 colsetlist(A) ::= colsetlist(Y) STRING(X). {
110   A = sqlite3Fts5ParseColset(pParse, Y, &X); }
colsetlist(A)111 colsetlist(A) ::= STRING(X). {
112   A = sqlite3Fts5ParseColset(pParse, 0, &X);
113 }
114 
expr(A)115 expr(A) ::= expr(X) AND expr(Y). {
116   A = sqlite3Fts5ParseNode(pParse, FTS5_AND, X, Y, 0);
117 }
expr(A)118 expr(A) ::= expr(X) OR expr(Y). {
119   A = sqlite3Fts5ParseNode(pParse, FTS5_OR, X, Y, 0);
120 }
expr(A)121 expr(A) ::= expr(X) NOT expr(Y). {
122   A = sqlite3Fts5ParseNode(pParse, FTS5_NOT, X, Y, 0);
123 }
124 
expr(A)125 expr(A) ::= colset(X) COLON LP expr(Y) RP. {
126   sqlite3Fts5ParseSetColset(pParse, Y, X);
127   A = Y;
128 }
expr(A)129 expr(A) ::= LP expr(X) RP. {A = X;}
expr(A)130 expr(A) ::= exprlist(X).   {A = X;}
131 
exprlist(A)132 exprlist(A) ::= cnearset(X). {A = X;}
exprlist(A)133 exprlist(A) ::= exprlist(X) cnearset(Y). {
134   A = sqlite3Fts5ParseImplicitAnd(pParse, X, Y);
135 }
136 
cnearset(A)137 cnearset(A) ::= nearset(X). {
138   A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, X);
139 }
cnearset(A)140 cnearset(A) ::= colset(X) COLON nearset(Y). {
141   A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, Y);
142   sqlite3Fts5ParseSetColset(pParse, A, X);
143 }
144 
145 
146 %type nearset     {Fts5ExprNearset*}
147 %type nearphrases {Fts5ExprNearset*}
148 %destructor nearset { sqlite3Fts5ParseNearsetFree($$); }
149 %destructor nearphrases { sqlite3Fts5ParseNearsetFree($$); }
150 
nearset(A)151 nearset(A) ::= phrase(Y). { A = sqlite3Fts5ParseNearset(pParse, 0, Y); }
nearset(A)152 nearset(A) ::= CARET phrase(Y). {
153   sqlite3Fts5ParseSetCaret(Y);
154   A = sqlite3Fts5ParseNearset(pParse, 0, Y);
155 }
nearset(A)156 nearset(A) ::= STRING(X) LP nearphrases(Y) neardist_opt(Z) RP. {
157   sqlite3Fts5ParseNear(pParse, &X);
158   sqlite3Fts5ParseSetDistance(pParse, Y, &Z);
159   A = Y;
160 }
161 
nearphrases(A)162 nearphrases(A) ::= phrase(X). {
163   A = sqlite3Fts5ParseNearset(pParse, 0, X);
164 }
nearphrases(A)165 nearphrases(A) ::= nearphrases(X) phrase(Y). {
166   A = sqlite3Fts5ParseNearset(pParse, X, Y);
167 }
168 
169 /*
170 ** The optional ", <integer>" at the end of the NEAR() arguments.
171 */
neardist_opt(A)172 neardist_opt(A) ::= . { A.p = 0; A.n = 0; }
neardist_opt(A)173 neardist_opt(A) ::= COMMA STRING(X). { A = X; }
174 
175 /*
176 ** A phrase. A set of primitives connected by "+" operators. Examples:
177 **
178 **     "the" + "quick brown" + fo *
179 **     "the quick brown fo" *
180 **     the+quick+brown+fo*
181 */
182 %type phrase {Fts5ExprPhrase*}
183 %destructor phrase { sqlite3Fts5ParsePhraseFree($$); }
184 
phrase(A)185 phrase(A) ::= phrase(X) PLUS STRING(Y) star_opt(Z). {
186   A = sqlite3Fts5ParseTerm(pParse, X, &Y, Z);
187 }
phrase(A)188 phrase(A) ::= STRING(Y) star_opt(Z). {
189   A = sqlite3Fts5ParseTerm(pParse, 0, &Y, Z);
190 }
191 
192 /*
193 ** Optional "*" character.
194 */
195 %type star_opt {int}
star_opt(A)196 star_opt(A) ::= STAR. { A = 1; }
star_opt(A)197 star_opt(A) ::= . { A = 0; }
198