Added functions to create CCL RPN nodes. Added small tokenizer
[yaz-moved-to-github.git] / src / tokenizer.c
1 /*
2  * Copyright (C) 1995-2007, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: tokenizer.c,v 1.1 2007-04-26 21:45:17 adam Exp $
6  */
7
8 /**
9  * \file tokenizer.c
10  * \brief Implements attribute match of CCL RPN nodes
11  */
12
13 #include <assert.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include <yaz/log.h>
18 #include <yaz/wrbuf.h>
19 #include <yaz/tokenizer.h>
20
21 struct yaz_tokenizer {
22     int (*get_byte_func)(const void **vp);
23     const void *get_byte_data;
24
25     int unget_byte;
26     char *white_space;
27     char *single_tokens;
28     char *quote_tokens_begin;
29     char *quote_tokens_end;
30     WRBUF wr_string;
31     int look;
32 };
33
34 void yaz_tokenizer_single_tokens(yaz_tokenizer_t t, const char *simple)
35 {
36     xfree(t->single_tokens);
37     t->single_tokens = xstrdup(simple);
38 }
39
40 yaz_tokenizer_t yaz_tokenizer_create(void)
41 {
42     yaz_tokenizer_t t = xmalloc(sizeof(*t));
43     t->white_space = xstrdup(" \t\r\n");
44     t->single_tokens = xstrdup("");
45     t->quote_tokens_begin = xstrdup("\"");
46     t->quote_tokens_end = xstrdup("\"");
47     t->get_byte_func = 0;
48     t->get_byte_data = 0;
49     t->wr_string = wrbuf_alloc();
50     t->look = YAZ_TOKENIZER_ERROR;
51     t->unget_byte = 0;
52     return t;
53 }
54
55 void yaz_tokenizer_destroy(yaz_tokenizer_t t)
56 {
57     xfree(t->white_space);
58     xfree(t->single_tokens);
59     xfree(t->quote_tokens_begin);
60     xfree(t->quote_tokens_end);
61     wrbuf_destroy(t->wr_string);
62     xfree(t);
63 }
64
65 static int read_buf(const void **vp)
66 {
67     const char *cp = *(const char **) vp;
68     int ch = *cp;
69     if (ch)
70     {
71         cp++;
72         *(const char **)vp = cp;
73     }
74     return ch;
75 }
76
77 static int get_byte(yaz_tokenizer_t t)
78 {
79     int ch = t->unget_byte;
80     assert(t->get_byte_func);
81     if (ch)
82         t->unget_byte = 0;
83     else
84         ch = t->get_byte_func(&t->get_byte_data);
85     return ch;
86 }
87
88 static void unget_byte(yaz_tokenizer_t t, int ch)
89 {
90     t->unget_byte = ch;
91 }
92
93 void yaz_tokenizer_read_buf(yaz_tokenizer_t t, const char *buf)
94 {
95     assert(t);
96     t->get_byte_func = read_buf;
97     t->get_byte_data = buf;
98 }
99
100 int yaz_tokenizer_move(yaz_tokenizer_t t)
101 {
102     const char *cp;
103     int ch = get_byte(t);
104
105     /* skip white space */
106     while (ch && strchr(t->white_space, ch))
107         ch = get_byte(t);
108     if (!ch) 
109     {
110         ch = YAZ_TOKENIZER_EOF;
111     }
112     else if ((cp = strchr(t->single_tokens, ch)))
113         ch = *cp;  /* single token match */
114     else if ((cp = strchr(t->quote_tokens_begin, ch)))
115     {   /* quoted string */
116         int end_ch = t->quote_tokens_end[cp - t->quote_tokens_begin];
117         ch = get_byte(t);
118         wrbuf_rewind(t->wr_string);
119         while (ch && ch != end_ch)
120             wrbuf_putc(t->wr_string, ch);
121         if (!ch)
122             ch = YAZ_TOKENIZER_ERROR;
123         else
124             ch = YAZ_TOKENIZER_QSTRING;
125     }
126     else
127     {  /* unquoted string */
128         wrbuf_rewind(t->wr_string);
129         while (ch && !strchr(t->white_space, ch)
130                && !strchr(t->single_tokens, ch))
131         {
132             wrbuf_putc(t->wr_string, ch);
133             ch = get_byte(t);
134         }
135         unget_byte(t, ch);
136         ch = YAZ_TOKENIZER_STRING;
137     }
138     t->look = ch;
139     yaz_log(YLOG_LOG, "tokenizer returns %d (%s)", ch, 
140             wrbuf_cstr(t->wr_string));
141     
142     return ch;
143 }
144
145 const char *yaz_tokenizer_string(yaz_tokenizer_t t)
146 {
147     return wrbuf_cstr(t->wr_string);
148 }
149
150 /*
151  * Local variables:
152  * c-basic-offset: 4
153  * indent-tabs-mode: nil
154  * End:
155  * vim: shiftwidth=4 tabstop=8 expandtab
156  */
157