store full token and completion in completed_item
[protos/libecoli.git] / lib / ecoli_parsed.c
1 /*
2  * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <stdint.h>
31 #include <string.h>
32 #include <assert.h>
33 #include <errno.h>
34
35 #include <ecoli_assert.h>
36 #include <ecoli_malloc.h>
37 #include <ecoli_strvec.h>
38 #include <ecoli_keyval.h>
39 #include <ecoli_log.h>
40 #include <ecoli_node.h>
41 #include <ecoli_parsed.h>
42
43 TAILQ_HEAD(ec_parsed_list, ec_parsed);
44
45 /* XXX idea for parse: maintain a "cursor" ?
46 struct ec_parsed {
47    struct ec_parsed_tree *root;
48    stuct ec_parsed_tree *cursor;
49 };
50 */
51
52 struct ec_parsed {
53         TAILQ_ENTRY(ec_parsed) next;
54         struct ec_parsed_list children;
55         struct ec_parsed *parent;
56         const struct ec_node *node;
57         struct ec_strvec *strvec;
58         struct ec_keyval *attrs;
59 };
60
61 static int __ec_node_parse_child(struct ec_node *node, struct ec_parsed *state,
62                                 bool is_root, const struct ec_strvec *strvec)
63 {
64         struct ec_strvec *match_strvec;
65         struct ec_parsed *child;
66         int ret;
67
68         /* build the node if required */
69         if (node->type->build != NULL) {
70                 if ((node->flags & EC_NODE_F_BUILT) == 0) {
71                         ret = node->type->build(node);
72                         if (ret < 0)
73                                 return ret;
74                 }
75         }
76         node->flags |= EC_NODE_F_BUILT;
77
78         if (node->type->parse == NULL)
79                 return -ENOTSUP;
80
81         if (!is_root) {
82                 child = ec_parsed();
83                 if (child == NULL)
84                         return -ENOMEM;
85
86                 ec_parsed_add_child(state, child);
87         } else {
88                 child = state;
89         }
90         ec_parsed_set_node(child, node);
91         ret = node->type->parse(node, child, strvec);
92         if (ret < 0) // XXX should we free state, child?
93                 return ret;
94
95         if (ret == EC_PARSED_NOMATCH) {
96                 if (!is_root) {
97                         ec_parsed_del_child(state, child);
98                         assert(TAILQ_EMPTY(&child->children));
99                         ec_parsed_free(child);
100                 }
101                 return ret;
102         }
103
104         match_strvec = ec_strvec_ndup(strvec, 0, ret);
105         if (match_strvec == NULL)
106                 return -ENOMEM;
107
108         child->strvec = match_strvec;
109
110         return ret;
111 }
112
113 int ec_node_parse_child(struct ec_node *node, struct ec_parsed *state,
114                         const struct ec_strvec *strvec)
115 {
116         assert(state != NULL);
117         return __ec_node_parse_child(node, state, false, strvec);
118 }
119
120 struct ec_parsed *ec_node_parse_strvec(struct ec_node *node,
121                                 const struct ec_strvec *strvec)
122 {
123         struct ec_parsed *parsed = ec_parsed();
124         int ret;
125
126         if (parsed == NULL)
127                 return NULL;
128
129         ret = __ec_node_parse_child(node, parsed, true, strvec);
130         if (ret < 0) {
131                 ec_parsed_free(parsed);
132                 return NULL;
133         }
134
135         return parsed;
136 }
137
138 struct ec_parsed *ec_node_parse(struct ec_node *node, const char *str)
139 {
140         struct ec_strvec *strvec = NULL;
141         struct ec_parsed *parsed = NULL;
142
143         errno = ENOMEM;
144         strvec = ec_strvec();
145         if (strvec == NULL)
146                 goto fail;
147
148         if (ec_strvec_add(strvec, str) < 0)
149                 goto fail;
150
151         parsed = ec_node_parse_strvec(node, strvec);
152         if (parsed == NULL)
153                 goto fail;
154
155         ec_strvec_free(strvec);
156         return parsed;
157
158  fail:
159         ec_strvec_free(strvec);
160         ec_parsed_free(parsed);
161         return NULL;
162 }
163
164 struct ec_parsed *ec_parsed(void)
165 {
166         struct ec_parsed *parsed = NULL;
167
168         parsed = ec_calloc(1, sizeof(*parsed));
169         if (parsed == NULL)
170                 goto fail;
171
172         TAILQ_INIT(&parsed->children);
173
174         parsed->attrs = ec_keyval();
175         if (parsed->attrs == NULL)
176                 goto fail;
177
178         return parsed;
179
180  fail:
181         if (parsed != NULL)
182                 ec_keyval_free(parsed->attrs);
183         ec_free(parsed);
184
185         return NULL;
186 }
187
188 static struct ec_parsed *
189 __ec_parsed_dup(const struct ec_parsed *root, const struct ec_parsed *ref,
190                 struct ec_parsed **new_ref)
191 {
192         struct ec_parsed *dup = NULL;
193         struct ec_parsed *child, *dup_child;
194         struct ec_keyval *attrs = NULL;
195
196         if (root == NULL)
197                 return NULL;
198
199         dup = ec_parsed();
200         if (dup == NULL)
201                 return NULL;
202
203         if (root == ref)
204                 *new_ref = dup;
205
206         attrs = ec_keyval_dup(root->attrs);
207         if (attrs == NULL)
208                 goto fail;
209         ec_keyval_free(dup->attrs);
210         dup->attrs = attrs;
211         dup->node = root->node;
212
213         if (root->strvec != NULL) {
214                 dup->strvec = ec_strvec_dup(root->strvec);
215                 if (dup->strvec == NULL)
216                         goto fail;
217         }
218
219         TAILQ_FOREACH(child, &root->children, next) {
220                 dup_child = __ec_parsed_dup(child, ref, new_ref);
221                 if (dup_child == NULL)
222                         goto fail;
223                 ec_parsed_add_child(dup, dup_child);
224         }
225
226         return dup;
227
228 fail:
229         ec_parsed_free(dup);
230         return NULL;
231 }
232
233 struct ec_parsed *ec_parsed_dup(struct ec_parsed *parsed) //XXX const
234 {
235         struct ec_parsed *root, *dup_root, *dup = NULL;
236
237         root = ec_parsed_get_root(parsed);
238         dup_root = __ec_parsed_dup(root, parsed, &dup);
239         if (dup_root == NULL)
240                 return NULL;
241         assert(dup != NULL);
242
243         return dup;
244 }
245
246 void ec_parsed_free_children(struct ec_parsed *parsed)
247 {
248         struct ec_parsed *child;
249
250         if (parsed == NULL)
251                 return;
252
253         while (!TAILQ_EMPTY(&parsed->children)) {
254                 child = TAILQ_FIRST(&parsed->children);
255                 TAILQ_REMOVE(&parsed->children, child, next);
256                 ec_parsed_free(child);
257         }
258 }
259
260 void ec_parsed_free(struct ec_parsed *parsed)
261 {
262         if (parsed == NULL)
263                 return;
264
265         // assert(parsed->parent == NULL); XXX
266         // or
267         // parsed = ec_parsed_get_root(parsed);
268
269         ec_parsed_free_children(parsed);
270         ec_strvec_free(parsed->strvec);
271         ec_keyval_free(parsed->attrs);
272         ec_free(parsed);
273 }
274
275 static void __ec_parsed_dump(FILE *out,
276         const struct ec_parsed *parsed, size_t indent)
277 {
278         struct ec_parsed *child;
279         const struct ec_strvec *vec;
280         size_t i;
281         const char *id = "none", *typename = "none";
282
283         if (parsed->node != NULL) {
284                 if (parsed->node->id != NULL)
285                         id = parsed->node->id;
286                 typename = parsed->node->type->name;
287         }
288
289         /* XXX enhance */
290         for (i = 0; i < indent; i++) {
291                 if (i % 2)
292                         fprintf(out, " ");
293                 else
294                         fprintf(out, "|");
295         }
296
297         fprintf(out, "node_type=%s id=%s vec=", typename, id);
298         vec = ec_parsed_strvec(parsed);
299         ec_strvec_dump(out, vec);
300
301         TAILQ_FOREACH(child, &parsed->children, next)
302                 __ec_parsed_dump(out, child, indent + 2);
303 }
304
305 void ec_parsed_dump(FILE *out, const struct ec_parsed *parsed)
306 {
307         fprintf(out, "------------------- parsed dump:\n"); //XXX
308
309         if (parsed == NULL) {
310                 fprintf(out, "parsed is NULL, error in parse\n");
311                 return;
312         }
313
314         /* only exist if it does not match (strvec == NULL) and if it
315          * does not have children: an incomplete parse, like those
316          * generated by complete() don't match but have children that
317          * may match. */
318         if (!ec_parsed_matches(parsed) && TAILQ_EMPTY(&parsed->children)) {
319                 fprintf(out, "no match\n");
320                 return;
321         }
322
323         __ec_parsed_dump(out, parsed, 0);
324 }
325
326 void ec_parsed_add_child(struct ec_parsed *parsed,
327         struct ec_parsed *child)
328 {
329         TAILQ_INSERT_TAIL(&parsed->children, child, next);
330         child->parent = parsed;
331 }
332
333 // XXX we can remove the first arg ? parsed == child->parent ?
334 void ec_parsed_del_child(struct ec_parsed *parsed, // XXX rename del in unlink?
335         struct ec_parsed *child)
336 {
337         TAILQ_REMOVE(&parsed->children, child, next);
338         child->parent = NULL;
339 }
340
341 struct ec_parsed *
342 ec_parsed_get_first_child(const struct ec_parsed *parsed)
343 {
344         return TAILQ_FIRST(&parsed->children);
345 }
346
347 struct ec_parsed *
348 ec_parsed_get_last_child(const struct ec_parsed *parsed)
349 {
350         return TAILQ_LAST(&parsed->children, ec_parsed_list);
351 }
352
353 struct ec_parsed *ec_parsed_get_next(const struct ec_parsed *parsed)
354 {
355         return TAILQ_NEXT(parsed, next);
356 }
357
358 bool ec_parsed_has_child(const struct ec_parsed *parsed)
359 {
360         return !TAILQ_EMPTY(&parsed->children);
361 }
362
363 const struct ec_node *ec_parsed_get_node(const struct ec_parsed *parsed)
364 {
365         return parsed->node;
366 }
367
368 void ec_parsed_set_node(struct ec_parsed *parsed, const struct ec_node *node)
369 {
370         parsed->node = node;
371 }
372
373 void ec_parsed_del_last_child(struct ec_parsed *parsed) // rename in free
374 {
375         struct ec_parsed *child;
376
377         child = ec_parsed_get_last_child(parsed);
378         ec_parsed_del_child(parsed, child);
379         ec_parsed_free(child);
380 }
381
382 struct ec_parsed *ec_parsed_get_root(struct ec_parsed *parsed)
383 {
384         if (parsed == NULL)
385                 return NULL;
386
387         while (parsed->parent != NULL)
388                 parsed = parsed->parent;
389
390         return parsed;
391 }
392
393 struct ec_parsed *ec_parsed_get_parent(struct ec_parsed *parsed)
394 {
395         if (parsed == NULL)
396                 return NULL;
397
398         return parsed->parent;
399 }
400
401 struct ec_parsed *ec_parsed_find_first(struct ec_parsed *parsed,
402         const char *id)
403 {
404         struct ec_parsed *child, *ret;
405
406         if (parsed == NULL)
407                 return NULL;
408
409         if (parsed->node != NULL &&
410                         parsed->node->id != NULL &&
411                         !strcmp(parsed->node->id, id))
412                 return parsed;
413
414         TAILQ_FOREACH(child, &parsed->children, next) {
415                 ret = ec_parsed_find_first(child, id);
416                 if (ret != NULL)
417                         return ret;
418         }
419
420         return NULL;
421 }
422
423 const struct ec_strvec *ec_parsed_strvec(const struct ec_parsed *parsed)
424 {
425         if (parsed == NULL || parsed->strvec == NULL)
426                 return NULL;
427
428         return parsed->strvec;
429 }
430
431 /* number of strings in the parsed vector */
432 size_t ec_parsed_len(const struct ec_parsed *parsed)
433 {
434         if (parsed == NULL || parsed->strvec == NULL)
435                 return 0;
436
437         return ec_strvec_len(parsed->strvec);
438 }
439
440 size_t ec_parsed_matches(const struct ec_parsed *parsed)
441 {
442         if (parsed == NULL)
443                 return 0;
444
445         if (parsed->strvec == NULL)
446                 return 0;
447
448         return 1;
449 }