1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
5 /* bison parser for CQL grammar. */
9 * \brief Implements CQL parser.
11 * This is a YACC parser, but since it must be reentrant, Bison is required.
12 * The original source file is cql.y.
19 /* avoid that bison stuff defines malloc/free - already in stdlib.h */
24 #include <yaz/yaz-iconv.h>
25 #include <yaz/xmalloc.h>
29 /** Node in the LALR parse tree. */
31 /** Inhereted attribute: relation */
33 /** Synthesized attribute: CQL node */
35 /** string buffer with token */
37 /** length of token */
39 /** size of buffer (len <= size) */
44 int (*getbyte)(void *client_data);
45 void (*ungetbyte)(int b, void *client_data);
56 int yylex(YYSTYPE *lval, void *vp);
57 int yyerror(void *lval, char *msg);
62 %lex-param {void *parm}
63 %parse-param {void *parm}
65 %token PREFIX_NAME SIMPLE_STRING AND OR NOT PROX GE LE NE EXACT SORTBY
70 $$.rel = cql_node_mk_sc(((CQL_parser) parm)->nmem,
71 "cql.serverChoice", "=", 0);
72 ((CQL_parser) parm)->top = 0;
74 cql_node_destroy($$.rel);
77 $3.cql->u.sort.search = $2.cql;
78 ((CQL_parser) parm)->top = $3.cql;
80 ((CQL_parser) parm)->top = $2.cql;
91 sortSpec: sortSpec singleSpec {
93 $$.cql->u.sort.next = $2.cql;
100 singleSpec: index modifiers {
101 $$.cql = cql_node_mk_sort(((CQL_parser) parm)->nmem, $1.buf, $2.cql);
107 cql_node_destroy($1.cql);
115 '>' searchTerm '=' searchTerm {
118 $$.cql = cql_apply_prefix(((CQL_parser) parm)->nmem,
119 $6.cql, $2.buf, $4.buf);
124 $$.cql = cql_apply_prefix(((CQL_parser) parm)->nmem,
132 scopedClause boolean modifiers {
135 struct cql_node *cn = cql_node_mk_boolean(((CQL_parser) parm)->nmem,
138 cn->u.boolean.modifiers = $3.cql;
139 cn->u.boolean.left = $1.cql;
140 cn->u.boolean.right = $5.cql;
154 searchTerm extraTerms {
155 struct cql_node *st = cql_node_dup(((CQL_parser) parm)->nmem, $0.rel);
156 st->u.st.extra_terms = $2.cql;
157 st->u.st.term = nmem_strdup(((CQL_parser)parm)->nmem, $1.buf);
161 index relation modifiers {
162 $$.rel = cql_node_mk_sc(((CQL_parser) parm)->nmem, $1.buf, $2.buf, 0);
163 $$.rel->u.st.modifiers = $3.cql;
166 cql_node_destroy($4.rel);
171 SIMPLE_STRING extraTerms {
172 struct cql_node *st = cql_node_mk_sc(((CQL_parser) parm)->nmem,
173 /* index */ 0, /* rel */ 0, $1.buf);
174 st->u.st.extra_terms = $2.cql;
182 /* unary NOT search SIMPLE_STRING here .. */
185 AND | OR | NOT | PROX ;
187 modifiers: modifiers '/' searchTerm
189 struct cql_node *mod = cql_node_mk_sc(((CQL_parser)parm)->nmem,
192 mod->u.st.modifiers = $1.cql;
196 modifiers '/' searchTerm relation_symbol searchTerm
198 struct cql_node *mod = cql_node_mk_sc(((CQL_parser)parm)->nmem,
199 $3.buf, $4.buf, $5.buf);
201 mod->u.st.modifiers = $1.cql;
210 relation: PREFIX_NAME | relation_symbol;
237 int yyerror(void *locp, char *s)
243 * putb is a utility that puts one character to the string
244 * in current lexical token. This routine deallocates as
245 * necessary using NMEM.
248 static void putb(YYSTYPE *lval, CQL_parser cp, int c)
250 if (lval->len+1 >= lval->size)
253 nmem_malloc(cp->nmem, (lval->size = lval->len * 2 + 20));
254 memcpy(nb, lval->buf, lval->len);
258 lval->buf[lval->len++] = c;
259 lval->buf[lval->len] = '\0';
264 * yylex returns next token for Bison to be read. In this
265 * case one of the CQL terminals are returned.
267 int yylex(YYSTYPE *lval, void *vp)
269 CQL_parser cp = (CQL_parser) vp;
275 lval->buf = (char *) nmem_malloc(cp->nmem, lval->size);
279 c = cp->getbyte(cp->client_data);
284 } while (yaz_isspace(c));
285 if (strchr("()=></", c))
291 c1 = cp->getbyte(cp->client_data);
298 cp->ungetbyte(c1, cp->client_data);
302 c1 = cp->getbyte(cp->client_data);
309 cp->ungetbyte(c1, cp->client_data);
313 c1 = cp->getbyte(cp->client_data);
325 cp->ungetbyte(c1, cp->client_data);
331 while ((c = cp->getbyte(cp->client_data)) != 0 && c != '"')
336 c = cp->getbyte(cp->client_data);
343 return SIMPLE_STRING;
347 int relation_like = 0;
348 while (c != 0 && !strchr(" \n()=<>/", c))
355 c = cp->getbyte(cp->client_data);
360 c = cp->getbyte(cp->client_data);
364 printf ("got %s\n", lval->buf);
367 cp->ungetbyte(c, cp->client_data);
368 if (!cql_strcmp(lval->buf, "and"))
373 if (!cql_strcmp(lval->buf, "or"))
378 if (!cql_strcmp(lval->buf, "not"))
383 if (!cql_strcmp(lval->buf, "prox"))
388 if (!cql_strcmp(lval->buf, "sortby"))
390 lval->buf = "sortby";
395 if (!cql_strcmp(lval->buf, "all"))
397 if (!cql_strcmp(lval->buf, "any"))
399 if (!cql_strcmp(lval->buf, "adj"))
404 return SIMPLE_STRING;
408 int cql_parser_stream(CQL_parser cp,
409 int (*getbyte)(void *client_data),
410 void (*ungetbyte)(int b, void *client_data),
413 nmem_reset(cp->nmem);
414 cp->getbyte = getbyte;
415 cp->ungetbyte = ungetbyte;
416 cp->client_data = client_data;
417 cql_node_destroy(cp->top);
424 CQL_parser cql_parser_create(void)
426 CQL_parser cp = (CQL_parser) xmalloc(sizeof(*cp));
434 cp->nmem = nmem_create();
439 void cql_parser_destroy(CQL_parser cp)
441 cql_node_destroy(cp->top);
442 nmem_destroy(cp->nmem);
446 struct cql_node *cql_parser_result(CQL_parser cp)
451 void cql_parser_strict(CQL_parser cp, int mode)
459 * c-file-style: "Stroustrup"
460 * indent-tabs-mode: nil
462 * vim: shiftwidth=4 tabstop=8 expandtab