Extend MARC-8 to handle ESC-G0 EACC. Fix conversion order for MARCXML
[yaz-moved-to-github.git] / src / cql.y
1 /* $Id: cql.y,v 1.3 2004-03-15 21:39:06 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 = nmem_malloc(cp->nmem, (lval->size = lval->len * 2 + 20));
191         memcpy (nb, lval->buf, lval->len);
192         lval->buf = nb;
193     }
194     if (c)
195         lval->buf[lval->len++] = c;
196     lval->buf[lval->len] = '\0';
197 }
198
199
200 int yylex(YYSTYPE *lval, void *vp)
201 {
202     CQL_parser cp = (CQL_parser) vp;
203     int c;
204     lval->cql = 0;
205     lval->rel = 0;
206     lval->len = 0;
207     lval->size = 10;
208     lval->buf = nmem_malloc(cp->nmem, lval->size);
209     lval->buf[0] = '\0';
210     do
211     {
212         c = cp->getbyte(cp->client_data);
213         if (c == 0)
214             return 0;
215         if (c == '\n')
216             return 0;
217     } while (isspace(c));
218     if (strchr("()=></", c))
219     {
220         int c1;
221         putb(lval, cp, c);
222         if (c == '>')
223         {
224             c1 = cp->getbyte(cp->client_data);
225             if (c1 == '=')
226             {
227                 putb(lval, cp, c1);
228                 return GE;
229             }
230             else
231                 cp->ungetbyte(c1, cp->client_data);
232         }
233         else if (c == '<')
234         {
235             c1 = cp->getbyte(cp->client_data);
236             if (c1 == '=')
237             {
238                 putb(lval, cp, c1);
239                 return LE;
240             }
241             else if (c1 == '>')
242             {
243                 putb(lval, cp, c1);
244                 return NE;
245             }
246             else
247                 cp->ungetbyte(c1, cp->client_data);
248         }
249         return c;
250     }
251     if (c == '"')
252     {
253         while ((c = cp->getbyte(cp->client_data)) != EOF && c != '"')
254         {
255             if (c == '\\')
256                 c = cp->getbyte(cp->client_data);
257             putb(lval, cp, c);
258         }
259         putb(lval, cp, 0);
260     }
261     else
262     {
263         putb(lval, cp, c);
264         while ((c = cp->getbyte(cp->client_data)) != 0 &&
265                !strchr(" \n()=<>/", c))
266         {
267             if (c == '\\')
268                 c = cp->getbyte(cp->client_data);
269             putb(lval, cp, c);
270         }
271 #if YYDEBUG
272         printf ("got %s\n", lval->buf);
273 #endif
274         if (c != 0)
275             cp->ungetbyte(c, cp->client_data);
276         if (!strcmp(lval->buf, "and"))
277             return AND;
278         if (!strcmp(lval->buf, "or"))
279             return OR;
280         if (!strcmp(lval->buf, "not"))
281             return NOT;
282         if (!strncmp(lval->buf, "prox", 4))
283             return PROX;
284     }
285     return TERM;
286 }
287
288
289 int cql_parser_stream(CQL_parser cp,
290                       int (*getbyte)(void *client_data),
291                       void (*ungetbyte)(int b, void *client_data),
292                       void *client_data)
293 {
294     nmem_reset(cp->nmem);
295     cp->getbyte = getbyte;
296     cp->ungetbyte = ungetbyte;
297     cp->client_data = client_data;
298     if (cp->top)
299         cql_node_destroy(cp->top);
300     cql_parse(cp);
301     if (cp->top)
302         return 0;
303     return -1;
304 }
305
306 CQL_parser cql_parser_create(void)
307 {
308     CQL_parser cp = (CQL_parser) xmalloc (sizeof(*cp));
309
310     cp->top = 0;
311     cp->getbyte = 0;
312     cp->ungetbyte = 0;
313     cp->client_data = 0;
314     cp->last_error = 0;
315     cp->last_pos = 0;
316     cp->nmem = nmem_create();
317     return cp;
318 }
319
320 void cql_parser_destroy(CQL_parser cp)
321 {
322     cql_node_destroy(cp->top);
323     nmem_destroy(cp->nmem);
324     xfree (cp);
325 }
326
327 struct cql_node *cql_parser_result(CQL_parser cp)
328 {
329     return cp->top;
330 }