1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2011 Index Data
3 * See the file LICENSE for details.
7 * \brief Implements CCL lexical analyzer (scanner)
20 * token_cmp: Compare token with keyword(s)
21 * kw: Keyword list. Each keyword is separated by space.
23 * return: 1 if token string matches one of the keywords in list;
26 static int token_cmp(CCL_parser cclp, const char **kw, struct ccl_token *token)
29 int case_sensitive = cclp->ccl_case_sensitive;
32 aliases = ccl_qual_search_special(cclp->bibset, "case");
34 case_sensitive = atoi(aliases[0]);
36 for (i = 0; kw[i]; i++)
38 if (token->len == strlen(kw[i]))
42 if (!memcmp(kw[i], token->name, token->len))
47 if (!ccl_memicmp(kw[i], token->name, token->len))
56 * ccl_tokenize: tokenize CCL command string.
57 * return: CCL token list.
59 struct ccl_token *ccl_parser_tokenize(CCL_parser cclp, const char *command)
62 const unsigned char *cp = (const unsigned char *) command;
63 struct ccl_token *first = NULL;
64 struct ccl_token *last = NULL;
65 cclp->start_pos = command;
69 const unsigned char *cp0 = cp;
70 while (*cp && strchr(" \t\r\n", *cp))
74 first = last = (struct ccl_token *)xmalloc(sizeof(*first));
80 last->next = (struct ccl_token *)xmalloc(sizeof(*first));
81 ccl_assert(last->next);
82 last->next->prev = last;
85 last->left_trunc = last->right_trunc = 0;
86 last->ws_prefix_buf = (const char *) cp0;
87 last->ws_prefix_len = cp - cp0;
89 last->name = (const char *) cp;
94 last->kind = CCL_TOK_EOL;
97 last->kind = CCL_TOK_LP;
100 last->kind = CCL_TOK_RP;
103 last->kind = CCL_TOK_COMMA;
107 last->kind = CCL_TOK_PROX;
117 if (*cp == '=' || *cp == '<' || *cp == '>')
120 last->kind = CCL_TOK_REL;
123 else if (cp[-1] == '=')
124 last->kind = CCL_TOK_EQ;
126 last->kind = CCL_TOK_REL;
133 last->left_trunc = 1;
139 last->kind = CCL_TOK_TERM;
140 last->name = (const char *) cp;
141 while (*cp && *cp != '"')
151 last->kind = CCL_TOK_TERM;
152 last->name = (const char *) cp;
153 while (*cp && !strchr("(),%!><=? \t\n\r", *cp))
158 aliases = ccl_qual_search_special(cclp->bibset, "and");
160 aliases = cclp->ccl_token_and;
161 if (token_cmp(cclp, aliases, last))
162 last->kind = CCL_TOK_AND;
164 aliases = ccl_qual_search_special(cclp->bibset, "or");
166 aliases = cclp->ccl_token_or;
167 if (token_cmp(cclp, aliases, last))
168 last->kind = CCL_TOK_OR;
170 aliases = ccl_qual_search_special(cclp->bibset, "not");
172 aliases = cclp->ccl_token_not;
173 if (token_cmp(cclp, aliases, last))
174 last->kind = CCL_TOK_NOT;
176 aliases = ccl_qual_search_special(cclp->bibset, "set");
178 aliases = cclp->ccl_token_set;
180 if (token_cmp(cclp, aliases, last))
181 last->kind = CCL_TOK_SET;
185 last->right_trunc = 1;
193 struct ccl_token *ccl_token_add(struct ccl_token *at)
195 struct ccl_token *n = (struct ccl_token *)xmalloc(sizeof(*n));
203 n->kind = CCL_TOK_TERM;
204 n->left_trunc = n->right_trunc = 0;
207 n->ws_prefix_buf = 0;
208 n->ws_prefix_len = 0;
213 * ccl_token_del: delete CCL tokens
215 void ccl_token_del(struct ccl_token *list)
217 struct ccl_token *list1;
227 static const char **create_ar(const char *v1, const char *v2)
229 const char **a = (const char **) xmalloc(3 * sizeof(*a));
241 static void destroy_ar(const char **a)
246 for (i = 0; a[i]; i++)
247 xfree((char *) a[i]);
252 CCL_parser ccl_parser_create(CCL_bibset bibset)
254 CCL_parser p = (CCL_parser)xmalloc(sizeof(*p));
257 p->look_token = NULL;
262 p->ccl_token_and = create_ar("and", 0);
263 p->ccl_token_or = create_ar("or", 0);
264 p->ccl_token_not = create_ar("not", "andnot");
265 p->ccl_token_set = create_ar("set", 0);
266 p->ccl_case_sensitive = 1;
271 void ccl_parser_destroy(CCL_parser p)
275 destroy_ar(p->ccl_token_and);
276 destroy_ar(p->ccl_token_or);
277 destroy_ar(p->ccl_token_not);
278 destroy_ar(p->ccl_token_set);
282 void ccl_parser_set_case(CCL_parser p, int case_sensitivity_flag)
285 p->ccl_case_sensitive = case_sensitivity_flag;
288 int ccl_parser_get_error(CCL_parser cclp, int *pos)
290 if (pos && cclp->error_code)
291 *pos = cclp->error_pos - cclp->start_pos;
292 return cclp->error_code;
298 * c-file-style: "Stroustrup"
299 * indent-tabs-mode: nil
301 * vim: shiftwidth=4 tabstop=8 expandtab