Beginnings for RPN to CQL transform.
[yaz-moved-to-github.git] / src / rpn2cql.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2008 Index Data
3  * See the file LICENSE for details.
4  */
5
6 /**
7  * \file
8  * \brief Implements RPN to CQL conversion
9  *
10  * Evaluation order of rules:
11  *
12  * always
13  * relation
14  * structure
15  * position
16  * truncation
17  * index
18  * relationModifier
19  */
20
21 #include <assert.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <yaz/rpn2cql.h>
25 #include <yaz/xmalloc.h>
26 #include <yaz/diagbib1.h>
27 #include <yaz/z-core.h>
28 #include <yaz/wrbuf.h>
29
30 static int rpn2cql_simple(cql_transform_t ct,
31                           void (*pr)(const char *buf, void *client_data),
32                           void *client_data,
33                           Z_Operand *q)
34 {
35     int ret = 0;
36     if (q->which != Z_Operand_APT)
37     {
38         ret = -1;
39         cql_transform_set_error(ct, YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM, 0);
40     }
41     else
42     {
43         Z_AttributesPlusTerm *apt = q->u.attributesPlusTerm;
44         Z_Term *term = apt->term;
45         Z_AttributeList *attributes = apt->attributes;
46         WRBUF w = wrbuf_alloc();
47
48         switch(term->which)
49         {
50         case Z_Term_general:
51             wrbuf_write(w, (const char *) term->u.general->buf, term->u.general->len);
52             break;
53         case Z_Term_numeric:
54             wrbuf_printf(w, "%d", *term->u.numeric);
55             break;
56         case Z_Term_characterString:
57             wrbuf_puts(w, term->u.characterString);
58             break;
59         default:
60             ret = -1;
61             cql_transform_set_error(ct, YAZ_BIB1_TERM_TYPE_UNSUPP, 0);
62         }
63         if (ret == 0)
64             pr(wrbuf_cstr(w), client_data);
65         wrbuf_destroy(w);
66     }
67     return ret;
68 }
69
70 static int rpn2cql_structure(cql_transform_t ct,
71                              void (*pr)(const char *buf, void *client_data),
72                              void *client_data,
73                              Z_RPNStructure *q, int nested)
74 {
75     if (q->which == Z_RPNStructure_simple)
76         return rpn2cql_simple(ct, pr, client_data, q->u.simple);
77     else
78     {
79         Z_Operator *op = q->u.complex->roperator;
80         int r;
81
82         if (nested)
83             pr("(", client_data);
84
85         r = rpn2cql_structure(ct, pr, client_data, q->u.complex->s1, 1);
86         if (r)
87             return r;
88         switch(op->which)
89         {
90         case  Z_Operator_and:
91             pr(" and ", client_data);
92             break;
93         case  Z_Operator_or:
94             pr(" or ", client_data);
95             break;
96         case  Z_Operator_and_not:
97             pr(" not ", client_data);
98             break;
99         case  Z_Operator_prox:
100             cql_transform_set_error(ct, YAZ_BIB1_UNSUPP_SEARCH, 0);
101             return -1;
102         }
103         r = rpn2cql_structure(ct, pr, client_data, q->u.complex->s2, 1);
104         if (nested)
105             pr(")", client_data);
106         return r;
107     }
108 }
109
110 int cql_transform_rpn2cql(cql_transform_t ct,
111                           void (*pr)(const char *buf, void *client_data),
112                           void *client_data,
113                           Z_RPNQuery *q)
114 {
115     cql_transform_set_error(ct, 0, 0);
116     return rpn2cql_structure(ct, pr, client_data, q->RPNStructure, 0);
117 }
118
119
120 /*
121  * Local variables:
122  * c-basic-offset: 4
123  * indent-tabs-mode: nil
124  * End:
125  * vim: shiftwidth=4 tabstop=8 expandtab
126  */
127