91dbf7c1ffe672413f3eaacaaa483e80426e17b6
[yaz-moved-to-github.git] / src / cql.y
1 /* $Id: cql.y,v 1.5 2004-10-02 13:28:26 adam Exp $
2    Copyright (C) 2002-2004
3    Index Data Aps
4
5 This file is part of the YAZ toolkit.
6
7 See the file LICENSE.
8
9  bison parser for CQL grammar.
10 */
11 %{
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <yaz/xmalloc.h>
17 #include <yaz/nmem.h>
18 #include <yaz/cql.h>
19     
20     typedef struct {
21         struct cql_node *rel;
22         struct cql_node *cql;
23         char *buf;
24         size_t len;
25         size_t size;
26     } token;        
27
28     struct cql_parser {
29         int (*getbyte)(void *client_data);
30         void (*ungetbyte)(int b, void *client_data);
31         void *client_data;
32         int last_error;
33         int last_pos;
34         struct cql_node *top;
35         NMEM nmem;
36     };
37
38 #define YYSTYPE token
39     
40 #define YYPARSE_PARAM parm
41 #define YYLEX_PARAM parm
42     
43     int yylex(YYSTYPE *lval, void *vp);
44     int yyerror(char *s);
45 %}
46
47 %pure_parser
48 %token TERM AND OR NOT PROX GE LE NE
49 %expect 9
50
51 %%
52
53 top: { 
54     $$.rel = cql_node_mk_sc("cql.serverChoice", "scr", 0);
55     ((CQL_parser) parm)->top = 0;
56 } cqlQuery1 {
57     cql_node_destroy($$.rel);
58     ((CQL_parser) parm)->top = $2.cql; 
59 }
60 ;
61
62 cqlQuery1: cqlQuery
63 | cqlQuery error {
64     cql_node_destroy($1.cql);
65     $$.cql = 0;
66 }
67 ;
68
69 cqlQuery: 
70   searchClause
71 |
72   cqlQuery boolean modifiers { 
73       $$.rel = $0.rel;
74   } searchClause {
75       struct cql_node *cn = cql_node_mk_boolean($2.buf);
76       
77       cn->u.boolean.modifiers = $3.cql;
78       cn->u.boolean.left = $1.cql;
79       cn->u.boolean.right = $5.cql;
80
81       $$.cql = cn;
82   }
83 ;
84
85 searchClause: 
86   '(' { 
87       $$.rel = $0.rel;
88       
89   } cqlQuery ')' {
90       $$.cql = $3.cql;
91   }
92 |
93   searchTerm {
94       struct cql_node *st = cql_node_dup ($0.rel);
95       st->u.st.term = xstrdup($1.buf);
96       $$.cql = st;
97   }
98
99   index relation modifiers {
100       $$.rel = cql_node_mk_sc($1.buf, $2.buf, 0);
101       $$.rel->u.st.modifiers = $3.cql;
102   } searchClause {
103       $$.cql = $5.cql;
104       cql_node_destroy($4.rel);
105   }
106 | '>' searchTerm '=' searchTerm {
107       $$.rel = $0.rel;
108   } cqlQuery {
109     $$.cql = cql_apply_prefix($6.cql, $2.buf, $4.buf);
110   }
111 | '>' searchTerm {
112       $$.rel = $0.rel;
113   } cqlQuery {
114     $$.cql = cql_apply_prefix($4.cql, 0, $2.buf);
115    }
116 ;
117
118 /* unary NOT search TERM here .. */
119
120 boolean: 
121   AND | OR | NOT | PROX 
122   ;
123
124 modifiers: modifiers '/' searchTerm
125
126     struct cql_node *mod = cql_node_mk_sc($3.buf, "=", 0);
127
128     mod->u.st.modifiers = $1.cql;
129     $$.cql = mod;
130 }
131 |
132 modifiers '/' searchTerm mrelation searchTerm
133 {
134     struct cql_node *mod = cql_node_mk_sc($3.buf, $4.buf, $5.buf);
135
136     mod->u.st.modifiers = $1.cql;
137     $$.cql = mod;
138 }
139 |
140
141     $$.cql = 0;
142 }
143 ;
144
145 mrelation:
146   '=' 
147 | '>' 
148 | '<'
149 | GE
150 | LE
151 | NE
152 ;
153
154 relation: 
155   '=' 
156 | '>' 
157 | '<'
158 | GE
159 | LE
160 | NE
161 | TERM
162 ;
163
164 index: 
165   searchTerm;
166
167 searchTerm:
168   TERM
169 | AND
170 | OR
171 | NOT
172 | PROX
173 ;
174
175 %%
176
177 int yyerror(char *s)
178 {
179     return 0;
180 }
181
182 /*
183  * bison lexer for CQL.
184  */
185
186 static void putb(YYSTYPE *lval, CQL_parser cp, int c)
187 {
188     if (lval->len+1 >= lval->size)
189     {
190         char *nb = (char *)
191             nmem_malloc(cp->nmem, (lval->size = lval->len * 2 + 20));
192         memcpy (nb, lval->buf, lval->len);
193         lval->buf = nb;
194     }
195     if (c)
196         lval->buf[lval->len++] = c;
197     lval->buf[lval->len] = '\0';
198 }
199
200
201 int yylex(YYSTYPE *lval, void *vp)
202 {
203     CQL_parser cp = (CQL_parser) vp;
204     int c;
205     lval->cql = 0;
206     lval->rel = 0;
207     lval->len = 0;
208     lval->size = 10;
209     lval->buf = (char *) nmem_malloc(cp->nmem, lval->size);
210     lval->buf[0] = '\0';
211     do
212     {
213         c = cp->getbyte(cp->client_data);
214         if (c == 0)
215             return 0;
216         if (c == '\n')
217             return 0;
218     } while (isspace(c));
219     if (strchr("()=></", c))
220     {
221         int c1;
222         putb(lval, cp, c);
223         if (c == '>')
224         {
225             c1 = cp->getbyte(cp->client_data);
226             if (c1 == '=')
227             {
228                 putb(lval, cp, c1);
229                 return GE;
230             }
231             else
232                 cp->ungetbyte(c1, cp->client_data);
233         }
234         else if (c == '<')
235         {
236             c1 = cp->getbyte(cp->client_data);
237             if (c1 == '=')
238             {
239                 putb(lval, cp, c1);
240                 return LE;
241             }
242             else if (c1 == '>')
243             {
244                 putb(lval, cp, c1);
245                 return NE;
246             }
247             else
248                 cp->ungetbyte(c1, cp->client_data);
249         }
250         return c;
251     }
252     if (c == '"')
253     {
254         while ((c = cp->getbyte(cp->client_data)) != 0 && c != '"')
255         {
256             if (c == '\\')
257                 c = cp->getbyte(cp->client_data);
258             putb(lval, cp, c);
259         }
260         putb(lval, cp, 0);
261     }
262     else
263     {
264         putb(lval, cp, c);
265         while ((c = cp->getbyte(cp->client_data)) != 0 &&
266                !strchr(" \n()=<>/", c))
267         {
268             if (c == '\\')
269                 c = cp->getbyte(cp->client_data);
270             putb(lval, cp, c);
271         }
272 #if YYDEBUG
273         printf ("got %s\n", lval->buf);
274 #endif
275         if (c != 0)
276             cp->ungetbyte(c, cp->client_data);
277         if (!strcmp(lval->buf, "and"))
278             return AND;
279         if (!strcmp(lval->buf, "or"))
280             return OR;
281         if (!strcmp(lval->buf, "not"))
282             return NOT;
283         if (!strncmp(lval->buf, "prox", 4))
284             return PROX;
285     }
286     return TERM;
287 }
288
289
290 int cql_parser_stream(CQL_parser cp,
291                       int (*getbyte)(void *client_data),
292                       void (*ungetbyte)(int b, void *client_data),
293                       void *client_data)
294 {
295     nmem_reset(cp->nmem);
296     cp->getbyte = getbyte;
297     cp->ungetbyte = ungetbyte;
298     cp->client_data = client_data;
299     if (cp->top)
300         cql_node_destroy(cp->top);
301     cql_parse(cp);
302     if (cp->top)
303         return 0;
304     return -1;
305 }
306
307 CQL_parser cql_parser_create(void)
308 {
309     CQL_parser cp = (CQL_parser) xmalloc (sizeof(*cp));
310
311     cp->top = 0;
312     cp->getbyte = 0;
313     cp->ungetbyte = 0;
314     cp->client_data = 0;
315     cp->last_error = 0;
316     cp->last_pos = 0;
317     cp->nmem = nmem_create();
318     return cp;
319 }
320
321 void cql_parser_destroy(CQL_parser cp)
322 {
323     cql_node_destroy(cp->top);
324     nmem_destroy(cp->nmem);
325     xfree (cp);
326 }
327
328 struct cql_node *cql_parser_result(CQL_parser cp)
329 {
330     return cp->top;
331 }