2 * Copyright (C) 1995-2008, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: ccltoken.c,v 1.15 2008-01-09 21:32:28 adam Exp $
9 * \brief Implements CCL lexical analyzer (scanner)
19 * token_cmp: Compare token with keyword(s)
20 * kw: Keyword list. Each keyword is separated by space.
22 * return: 1 if token string matches one of the keywords in list;
25 static int token_cmp(CCL_parser cclp, const char **kw, struct ccl_token *token)
28 int case_sensitive = cclp->ccl_case_sensitive;
31 aliases = ccl_qual_search_special(cclp->bibset, "case");
33 case_sensitive = atoi(aliases[0]);
35 for (i = 0; kw[i]; i++)
37 if (token->len == strlen(kw[i]))
41 if (!memcmp(kw[i], token->name, token->len))
46 if (!ccl_memicmp(kw[i], token->name, token->len))
55 * ccl_tokenize: tokenize CCL command string.
56 * return: CCL token list.
58 struct ccl_token *ccl_parser_tokenize(CCL_parser cclp, const char *command)
61 const unsigned char *cp = (const unsigned char *) command;
62 struct ccl_token *first = NULL;
63 struct ccl_token *last = NULL;
64 cclp->start_pos = command;
68 const unsigned char *cp0 = cp;
69 while (*cp && strchr(" \t\r\n", *cp))
73 first = last = (struct ccl_token *)xmalloc(sizeof(*first));
79 last->next = (struct ccl_token *)xmalloc(sizeof(*first));
80 ccl_assert(last->next);
81 last->next->prev = last;
84 last->ws_prefix_buf = (const char *) cp0;
85 last->ws_prefix_len = cp - cp0;
87 last->name = (const char *) cp;
92 last->kind = CCL_TOK_EOL;
95 last->kind = CCL_TOK_LP;
98 last->kind = CCL_TOK_RP;
101 last->kind = CCL_TOK_COMMA;
105 last->kind = CCL_TOK_PROX;
115 if (*cp == '=' || *cp == '<' || *cp == '>')
118 last->kind = CCL_TOK_REL;
121 else if (cp[-1] == '=')
122 last->kind = CCL_TOK_EQ;
124 last->kind = CCL_TOK_REL;
127 last->kind = CCL_TOK_TERM;
128 last->name = (const char *) cp;
130 while (*cp && *cp != '\"')
139 if (!strchr("(),%!><= \t\n\r", cp[-1]))
141 while (*cp && !strchr("(),%!><= \t\n\r", *cp))
147 last->kind = CCL_TOK_TERM;
149 aliases = ccl_qual_search_special(cclp->bibset, "and");
151 aliases = cclp->ccl_token_and;
152 if (token_cmp(cclp, aliases, last))
153 last->kind = CCL_TOK_AND;
155 aliases = ccl_qual_search_special(cclp->bibset, "or");
157 aliases = cclp->ccl_token_or;
158 if (token_cmp(cclp, aliases, last))
159 last->kind = CCL_TOK_OR;
161 aliases = ccl_qual_search_special(cclp->bibset, "not");
163 aliases = cclp->ccl_token_not;
164 if (token_cmp(cclp, aliases, last))
165 last->kind = CCL_TOK_NOT;
167 aliases = ccl_qual_search_special(cclp->bibset, "set");
169 aliases = cclp->ccl_token_set;
171 if (token_cmp(cclp, aliases, last))
172 last->kind = CCL_TOK_SET;
178 struct ccl_token *ccl_token_add(struct ccl_token *at)
180 struct ccl_token *n = (struct ccl_token *)xmalloc(sizeof(*n));
188 n->kind = CCL_TOK_TERM;
191 n->ws_prefix_buf = 0;
192 n->ws_prefix_len = 0;
197 * ccl_token_del: delete CCL tokens
199 void ccl_token_del(struct ccl_token *list)
201 struct ccl_token *list1;
211 static const char **create_ar(const char *v1, const char *v2)
213 const char **a = (const char **) xmalloc(3 * sizeof(*a));
225 static void destroy_ar(const char **a)
230 for (i = 0; a[i]; i++)
231 xfree((char *) a[i]);
236 CCL_parser ccl_parser_create(CCL_bibset bibset)
238 CCL_parser p = (CCL_parser)xmalloc(sizeof(*p));
241 p->look_token = NULL;
246 p->ccl_token_and = create_ar("and", 0);
247 p->ccl_token_or = create_ar("or", 0);
248 p->ccl_token_not = create_ar("not", "andnot");
249 p->ccl_token_set = create_ar("set", 0);
250 p->ccl_case_sensitive = 1;
255 void ccl_parser_destroy(CCL_parser p)
259 destroy_ar(p->ccl_token_and);
260 destroy_ar(p->ccl_token_or);
261 destroy_ar(p->ccl_token_not);
262 destroy_ar(p->ccl_token_set);
266 void ccl_parser_set_case(CCL_parser p, int case_sensitivity_flag)
269 p->ccl_case_sensitive = case_sensitivity_flag;
272 int ccl_parser_get_error(CCL_parser cclp, int *pos)
274 if (pos && cclp->error_code)
275 *pos = cclp->error_pos - cclp->start_pos;
276 return cclp->error_code;
282 * indent-tabs-mode: nil
284 * vim: shiftwidth=4 tabstop=8 expandtab