Contiki-NG
Loading...
Searching...
No Matches
aql-lexer.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010, Swedish Institute of Computer Science
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30/**
31 * \file
32 * Lexical analyzer for AQL, the Antelope Query Language.
33 * \author
34 * Nicolas Tsiftes <nvt@sics.se>
35 */
36
37#include "aql.h"
38
39#include <ctype.h>
40#include <errno.h>
41#include <limits.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <strings.h>
46
47struct keyword {
48 char *string;
49 token_t token;
50};
51
52/* The keywords are arranged primarily by length and
53 secondarily by expected lookup frequency. */
54static const struct keyword keywords[] = {
55 {";", END},
56 {"(", LEFT_PAREN},
57 {")", RIGHT_PAREN},
58 {",", COMMA},
59 {"=", EQUAL},
60 {">", GT},
61 {"<", LT},
62 {".", DOT},
63 {"+", ADD},
64 {"-", SUB},
65 {"*", MUL},
66 {"/", DIV},
67 {"#", COMMENT},
68
69 {">=", GEQ},
70 {"<=", LEQ},
71 {"<>", NOT_EQUAL},
72 {"<-", ASSIGN},
73 {"OR", OR},
74 {"IS", IS},
75 {"ON", ON},
76 {"IN", IN},
77
78 {"AND", AND},
79 {"NOT", NOT},
80 {"SUM", SUM},
81 {"MAX", MAX},
82 {"MIN", MIN},
83 {"INT", INT},
84
85 {"INTO", INTO},
86 {"FROM", FROM},
87 {"MEAN", MEAN},
88 {"JOIN", JOIN},
89 {"LONG", LONG},
90 {"TYPE", TYPE},
91
92 {"WHERE", WHERE},
93 {"COUNT", COUNT},
94 {"INDEX", INDEX},
95
96 {"INSERT", INSERT},
97 {"SELECT", SELECT},
98 {"REMOVE", REMOVE},
99 {"CREATE", CREATE},
100 {"MEDIAN", MEDIAN},
101 {"DOMAIN", DOMAIN},
102 {"STRING", STRING},
103 {"INLINE", INLINE},
104
105 {"PROJECT", PROJECT},
106 {"MAXHEAP", MAXHEAP},
107 {"MEMHASH", MEMHASH},
108
109 {"RELATION", RELATION},
110
111 {"ATTRIBUTE", ATTRIBUTE}
112};
113
114/* Provides a pointer to the first keyword of a specific length. */
115static const int8_t skip_hint[] = {0, 13, 21, 27, 33, 36, 44, 47, 48};
116
117static char separators[] = "#.;,() \t\n";
118
119int
120lexer_start(lexer_t *lexer, char *input, token_t *token, value_t *value)
121{
122 lexer->input = input;
123 lexer->prev_pos = input;
124 lexer->token = token;
125 lexer->value = value;
126
127 return 0;
128}
129
130static token_t
131get_token_id(const char *string, const size_t length)
132{
133 int start, end;
134 int i;
135
136 if(sizeof(skip_hint) < length || length < 1) {
137 return NONE;
138 }
139
140
141 start = skip_hint[length - 1];
142 if(sizeof(skip_hint) == length) {
143 end = sizeof(keywords) / sizeof(keywords[0]);
144 } else {
145 end = skip_hint[length];
146 }
147
148 for(i = start; i < end; i++) {
149 if(strncasecmp(keywords[i].string, string, length) == 0) {
150 return keywords[i].token;
151 }
152 }
153
154 return NONE;
155}
156
157static int
158next_real(lexer_t *lexer, const char *s)
159{
160 char *end;
161 long long_value;
162#if DB_FEATURE_FLOATS
163 float float_value;
164#endif /* DB_FEATURE_FLOATS */
165
166 errno = 0;
167 long_value = strtol(s, &end, 10);
168
169#if DB_FEATURE_FLOATS
170 if(*end == '.') {
171 /* Process a float value. */
172 float_value = strtof(s, &end);
173 if(float_value == 0 && s == end) {
174 return -1;
175 }
176 memcpy(lexer->value, &float_value, sizeof(float_value));
177 *lexer->token = FLOAT_VALUE;
178 lexer->input = end;
179
180 return 1;
181 }
182#endif /* DB_FEATURE_FLOATS */
183
184 /* Process an integer value. */
185 if(long_value == 0 && errno != 0) {
186 return -1;
187 }
188 memcpy(lexer->value, &long_value, sizeof(long_value));
189 *lexer->token = INTEGER_VALUE;
190 lexer->input = end;
191
192 return 1;
193}
194
195static int
196next_string(lexer_t *lexer, const char *s)
197{
198 char *end;
199 size_t length;
200
201 end = strchr(s, '\'');
202 if(end == NULL) {
203 return -1;
204 }
205
206 length = end - s;
207 *lexer->token = STRING_VALUE;
208 lexer->input = end + 1; /* Skip the closing delimiter. */
209
210 if(length > DB_MAX_ELEMENT_SIZE - 1) {
211 length = DB_MAX_ELEMENT_SIZE - 1;
212 }
213
214 memcpy(lexer->value, s, length);
215 (*lexer->value)[length] = '\0';
216
217 return 1;
218}
219
220static int
221next_token(lexer_t *lexer, const char *s)
222{
223 size_t length;
224
225 length = strcspn(s, separators);
226 if(length == 0) {
227 /* We encountered a separator, so we try to get a token of
228 precisely 1 byte. */
229 length = 1;
230 }
231
232 *lexer->token = get_token_id(s, length);
233 lexer->input = s + length;
234 if(*lexer->token != NONE) {
235 return 1;
236 }
237
238 /* The input did not constitute a valid token,
239 so we regard it as an identifier. */
240
241 *lexer->token = IDENTIFIER;
242
243 if(length > DB_MAX_ELEMENT_SIZE - 1) {
244 length = DB_MAX_ELEMENT_SIZE - 1;
245 }
246
247 memcpy(lexer->value, s, length);
248 (*lexer->value)[length] = '\0';
249
250 return 1;
251}
252
253int
254lexer_next(lexer_t *lexer)
255{
256 const char *s;
257
258 *lexer->token = NONE;
259 s = lexer->input;
260 s += strspn(s, " \t\n");
261 lexer->prev_pos = s;
262
263 switch(*s) {
264 case '\'':
265 /* Process the string that follows the delimiter. */
266 return next_string(lexer, s + 1);
267 case '\0':
268 return 0;
269 default:
270 if(isdigit((int)*s) || (*s == '-' && isdigit((int)s[1]))) {
271 return next_real(lexer, s);
272 }
273
274 /* Process a token. */
275 return next_token(lexer, s);
276 }
277}
278
279void
280lexer_rewind(lexer_t *lexer)
281{
282 lexer->input = lexer->prev_pos;
283}
Definitions and declarations for AQL, the Antelope Query Language.
static void start(void)
Start measurement.