Kestrel Interface
Loading...
Searching...
No Matches
kest_dictionary.c
Go to the documentation of this file.
1#include <stdlib.h>
2#include <string.h>
3#include <stdio.h>
4#include <math.h>
5
6#include "kest_int.h"
7
8#ifndef PRINTLINES_ALLOWED
9#define PRINTLINES_ALLOWED 1
10#endif
11
12static const char *FNAME = "kest_dictionary.c";
13
15
16const char *kest_dict_entry_type_to_string(int type)
17{
18 switch (type)
19 {
20 case DICT_ENTRY_TYPE_INT: return "DICT_ENTRY_TYPE_INT";
21 case DICT_ENTRY_TYPE_FLOAT: return "DICT_ENTRY_TYPE_FLOAT";
22 case DICT_ENTRY_TYPE_STR: return "DICT_ENTRY_TYPE_STR";
23 case DICT_ENTRY_TYPE_EXPR: return "DICT_ENTRY_TYPE_EXPR";
24 case DICT_ENTRY_TYPE_SUBDICT: return "DICT_ENTRY_TYPE_SUBDICT";
25 case DICT_ENTRY_TYPE_LIST: return "DICT_ENTRY_TYPE_LIST";
26 default: return "DICT_ENTRY_TYPE_UNKNOWN";
27 }
28}
29
31{
32 switch (type)
33 {
34 case DICT_ENTRY_TYPE_INT: return "int";
35 case DICT_ENTRY_TYPE_FLOAT: return "float";
36 case DICT_ENTRY_TYPE_STR: return "string";
37 case DICT_ENTRY_TYPE_EXPR: return "expression";
38 case DICT_ENTRY_TYPE_SUBDICT: return "dictionary";
39 case DICT_ENTRY_TYPE_LIST: return "list";
40 default: return "unknown";
41 }
42}
43
45{
46 if (!entry)
47 return NULL;
48
49 kest_string *result = kest_allocator_alloc(NULL, sizeof(kest_string));
50 kest_string *str;
51 kest_string_init(result);
52
53 kest_string_appendf(result, "%s: ", entry->name ? entry->name : "(NULL)");
54
55 kest_dictionary *dict = entry->value.val_dict;
56 kest_dictionary_entry_list *list = entry->value.val_list;
57
58 int any = 0;
59
60 switch (entry->type)
61 {
63 kest_string_appendf(result, "(int) %d", entry->value.val_int);
64 break;
66 kest_string_appendf(result, "(float) %.04f", entry->value.val_float);
67 break;
69 kest_string_appendf(result, "(string) \"%s\"", entry->value.val_string);
70 break;
72 kest_string_appendf(result, "(expr) %s", kest_expression_to_string(entry->value.val_expr));
73 break;
75 kest_string_append(result, '(');
76 if (!dict)
77 {
78 kest_string_appendf(result, "(NULL))");
79 }
80 else
81 {
82 for (int i = 0; i < KEST_DICTIONARY_N_BUCKETS; i++)
83 {
84 for (int j = 0; j < dict->buckets[i].n_entries; j++)
85 {
86 if (any)
87 {
88 kest_string_append(result, ',');
89 kest_string_append(result, ' ');
90 }
91 str = kest_dict_entry_to_string(&dict->buckets[i].entries[j]);
92 kest_string_concat(result, str);
94
95 any = 1;
96 }
97 }
98
99 kest_string_append(result, ')');
100 }
101 break;
103 kest_string_append(result, '{');
104 if (!list)
105 {
106 kest_string_appendf(result, "(NULL)}");
107 }
108 else
109 {
110 for (int i = 0; i < list->count; i++)
111 {
112 if (i != 0)
113 {
114 kest_string_append(result, ',');
115 kest_string_append(result, ' ');
116 }
117 str = kest_dict_entry_to_string(&list->entries[i]);
118 kest_string_concat(result, str);
120 }
121
122 kest_string_append(result, '}');
123 }
124 break;
125 }
126
127 return result;
128}
129
131{
132 if (!bucket)
133 return ERR_NULL_PTR;
134
135 memset(bucket, 0, sizeof(kest_dictionary_bucket));
136
137 return NO_ERROR;
138}
139
141{
142 if (!bucket)
143 return ERR_NULL_PTR;
144
146
147 if (bucket->entry_array_length == 0)
148 {
149 bucket->entries = kest_parser_alloc(sizeof(kest_dictionary_entry) * 2);
150
151 if (!bucket->entries)
152 {
153 bucket->entry_array_length = 0;
154 return ERR_ALLOC_FAIL;
155 }
156
157 bucket->entry_array_length = 2;
158 }
159 else if (bucket->n_entries == bucket->entry_array_length)
160 {
162
163 if (!na) return ERR_ALLOC_FAIL;
164
165 for (int i = 0; i < bucket->n_entries; i++)
166 na[i] = bucket->entries[i];
167
168 bucket->entries = na;
169 bucket->entry_array_length *= 2;
170 }
171
172 return NO_ERROR;
173}
174
176{
177 if (!bucket)
178 return ERR_NULL_PTR;
179
180 int ret_val = NO_ERROR;
181
182 if ((ret_val = kest_dictionary_bucket_ensure_capacity(bucket)) != NO_ERROR)
183 return ret_val;
184
185 bucket->entries[bucket->n_entries].name = strndup(entry.name, 32);
186 bucket->entries[bucket->n_entries].type = entry.type;
187 bucket->entries[bucket->n_entries].value = entry.value;
188
189 bucket->n_entries++;
190
191 return ret_val;
192}
193
194int kest_dictionary_bucket_add_entry_str(kest_dictionary_bucket *bucket, const char *name, const char *value)
195{
196 if (!bucket)
197 return ERR_NULL_PTR;
198
199 if (!name || !value)
200 return ERR_BAD_ARGS;
201
202 int ret_val = NO_ERROR;
203
204 if ((ret_val = kest_dictionary_bucket_ensure_capacity(bucket)) != NO_ERROR)
205 return ret_val;
206
207 bucket->entries[bucket->n_entries].name = name;
208 bucket->entries[bucket->n_entries].type = DICT_ENTRY_TYPE_STR;
209 bucket->entries[bucket->n_entries].value.val_string = value;
210
211 bucket->n_entries++;
212
213 return NO_ERROR;
214}
215
216int kest_dictionary_bucket_add_entry_int(kest_dictionary_bucket *bucket, const char *name, int value)
217{
218 if (!bucket)
219 return ERR_NULL_PTR;
220
221 if (!name || !value)
222 return ERR_BAD_ARGS;
223
224 int ret_val = NO_ERROR;
225
226 if ((ret_val = kest_dictionary_bucket_ensure_capacity(bucket)) != NO_ERROR)
227 return ret_val;
228
229 bucket->entries[bucket->n_entries].name = name;
230 bucket->entries[bucket->n_entries].type = DICT_ENTRY_TYPE_INT;
231 bucket->entries[bucket->n_entries].value.val_int = value;
232
233 bucket->n_entries++;
234
235 return NO_ERROR;
236}
237
238int kest_dictionary_bucket_add_entry_float(kest_dictionary_bucket *bucket, const char *name, float value)
239{
240 if (!bucket)
241 return ERR_NULL_PTR;
242
243 if (!name || !value)
244 return ERR_BAD_ARGS;
245
246 int ret_val = NO_ERROR;
247
248 if ((ret_val = kest_dictionary_bucket_ensure_capacity(bucket)) != NO_ERROR)
249 return ret_val;
250
251 bucket->entries[bucket->n_entries].name = name;
252 bucket->entries[bucket->n_entries].type = DICT_ENTRY_TYPE_FLOAT;
253 bucket->entries[bucket->n_entries].value.val_float = value;
254
255 bucket->n_entries++;
256
257 return NO_ERROR;
258}
259
261{
262 if (!bucket)
263 return ERR_NULL_PTR;
264
265 if (!name || !value)
266 return ERR_BAD_ARGS;
267
268 int ret_val = NO_ERROR;
269
270 if ((ret_val = kest_dictionary_bucket_ensure_capacity(bucket)) != NO_ERROR)
271 return ret_val;
272
273 bucket->entries[bucket->n_entries].name = name;
274 bucket->entries[bucket->n_entries].type = DICT_ENTRY_TYPE_EXPR;
275 bucket->entries[bucket->n_entries].value.val_expr = value;
276
277 bucket->n_entries++;
278
279 return NO_ERROR;
280}
281
283{
284 if (!bucket)
285 return ERR_NULL_PTR;
286
287 if (!name || !value)
288 return ERR_BAD_ARGS;
289
290 int ret_val = NO_ERROR;
291
292 if ((ret_val = kest_dictionary_bucket_ensure_capacity(bucket)) != NO_ERROR)
293 return ret_val;
294
295 bucket->entries[bucket->n_entries].name = name;
297 bucket->entries[bucket->n_entries].value.val_dict = value;
298
299 bucket->n_entries++;
300
301 return NO_ERROR;
302}
303
304int kest_dictionary_bucket_lookup(kest_dictionary_bucket *bucket, const char *name, void *result, int type)
305{
306 if (!bucket || !result || !name)
307 return ERR_NULL_PTR;
308
309 for (int i = 0; i < bucket->n_entries; i++)
310 {
311 if (strcmp(bucket->entries[i].name, name) == 0)
312 {
313 if (bucket->entries[i].type == type)
314 {
315 switch (type)
316 {
318 *((const char**)result) = bucket->entries[i].value.val_string;
319 break;
321 *((float*)result) = bucket->entries[i].value.val_float;
322 break;
324 *((int*)result) = bucket->entries[i].value.val_int;
325 break;
327 *((kest_expression**)result) = bucket->entries[i].value.val_expr;
328 break;
330 *((kest_dictionary**)result) = bucket->entries[i].value.val_dict;
331 break;
333 *((kest_dictionary_entry_list**)result) = bucket->entries[i].value.val_list;
334 break;
335 }
336 }
337 else if (type == DICT_ENTRY_TYPE_FLOAT && bucket->entries[i].type == DICT_ENTRY_TYPE_INT)
338 {
339 *((float*)result) = (float)bucket->entries[i].value.val_int;
340 }
341 else if (type == DICT_ENTRY_TYPE_INT && bucket->entries[i].type == DICT_ENTRY_TYPE_FLOAT)
342 {
343 *((int*)result) = (int)roundf(bucket->entries[i].value.val_float);
344 }
345 else
346 {
347 return ERR_WRONG_TYPE;
348 }
349
350 return NO_ERROR;
351 }
352 }
353
354 return ERR_NOT_FOUND;
355}
356
357int kest_dictionary_bucket_lookup_str(kest_dictionary_bucket *bucket, const char *name, const char **result)
358{
359 return kest_dictionary_bucket_lookup(bucket, name, result, DICT_ENTRY_TYPE_STR);
360}
361
362int kest_dictionary_bucket_lookup_float(kest_dictionary_bucket *bucket, const char *name, float *result)
363{
364 return kest_dictionary_bucket_lookup(bucket, name, result, DICT_ENTRY_TYPE_FLOAT);
365}
366
367int kest_dictionary_bucket_lookup_int(kest_dictionary_bucket *bucket, const char *name, int *result)
368{
369 return kest_dictionary_bucket_lookup(bucket, name, result, DICT_ENTRY_TYPE_INT);
370}
371
373{
374 return kest_dictionary_bucket_lookup(bucket, name, result, DICT_ENTRY_TYPE_EXPR);
375}
376
378{
379 return kest_dictionary_bucket_lookup(bucket, name, result, DICT_ENTRY_TYPE_SUBDICT);
380}
381
382int kest_dictionary_bucket_lookup_list(kest_dictionary_bucket *bucket, const char *name, kest_dictionary_entry_list **result)
383{
384 return kest_dictionary_bucket_lookup(bucket, name, result, DICT_ENTRY_TYPE_LIST);
385}
386
387
389{
391
392 if (!dict)
393 return NULL;
394
395 dict->name = NULL;
396 dict->n_entries = 0;
398
399 if (!dict->entries)
400 {
401 dict->entry_array_length = 0;
402 return NULL;
403 }
404
405 dict->entry_array_length = 8;
406
407 for (int i = 0; i < KEST_DICTIONARY_N_BUCKETS; i++)
409
410 return dict;
411}
412
414{
415 if (!dict)
416 return ERR_NULL_PTR;
417
419
420 if (dict->n_entries == dict->entry_array_length)
421 {
423
424 if (!na) return ERR_ALLOC_FAIL;
425
426 for (int i = 0; i < dict->n_entries; i++)
427 na[i] = dict->entries[i];
428
429 dict->entries = na;
430 dict->entry_array_length *= 2;
431 }
432
433 return NO_ERROR;
434}
435
437{
438 if (!dict)
439 return ERR_NULL_PTR;
440
441 int ret_val = NO_ERROR;
442
443 if ((ret_val = kest_dictionary_ensure_capacity(dict)) != NO_ERROR)
444 return ret_val;
445
446 dict->entries[dict->n_entries].name = strndup(entry.name, 32);
447 dict->entries[dict->n_entries].type = entry.type;
448 dict->entries[dict->n_entries].value = entry.value;
449
450 dict->n_entries++;
451
452 uint32_t bucket = hash(entry.name) & (KEST_DICTIONARY_N_BUCKETS - 1);
453
454 return kest_dictionary_bucket_add_entry(&dict->buckets[bucket], entry);
455}
456
457int kest_dictionary_add_entry_str(kest_dictionary *dict, const char *name, const char *value)
458{
459 if (!dict)
460 return ERR_NULL_PTR;
461
462 if (!name || !value)
463 return ERR_BAD_ARGS;
464
465 int ret_val = NO_ERROR;
466
467 if ((ret_val = kest_dictionary_ensure_capacity(dict)) != NO_ERROR)
468 return ret_val;
469
470 dict->entries[dict->n_entries].name = name;
472 dict->entries[dict->n_entries].value.val_string = value;
473
474 dict->n_entries++;
475
476 uint32_t bucket = hash(name) & (KEST_DICTIONARY_N_BUCKETS - 1);
477
478 return kest_dictionary_bucket_add_entry_str(&dict->buckets[bucket], name, value);
479}
480
481int kest_dictionary_add_entry_int(kest_dictionary *dict, const char *name, int value)
482{
483 if (!dict)
484 return ERR_NULL_PTR;
485
486 if (!name || !value)
487 return ERR_BAD_ARGS;
488
489 int ret_val = NO_ERROR;
490
491 if ((ret_val = kest_dictionary_ensure_capacity(dict)) != NO_ERROR)
492 return ret_val;
493
494 dict->entries[dict->n_entries].name = name;
496 dict->entries[dict->n_entries].value.val_int = value;
497
498 dict->n_entries++;
499
500 uint32_t bucket = hash(name) & (KEST_DICTIONARY_N_BUCKETS - 1);
501
502 return kest_dictionary_bucket_add_entry_int(&dict->buckets[bucket], name, value);
503}
504
505int kest_dictionary_add_entry_float(kest_dictionary *dict, const char *name, float value)
506{
507 if (!dict)
508 return ERR_NULL_PTR;
509
510 if (!name || !value)
511 return ERR_BAD_ARGS;
512
513 int ret_val = NO_ERROR;
514
515 if ((ret_val = kest_dictionary_ensure_capacity(dict)) != NO_ERROR)
516 return ret_val;
517
518 dict->entries[dict->n_entries].name = name;
520 dict->entries[dict->n_entries].value.val_float = value;
521
522 dict->n_entries++;
523
524 uint32_t bucket = hash(name) & (KEST_DICTIONARY_N_BUCKETS - 1);
525
526 return kest_dictionary_bucket_add_entry_float(&dict->buckets[bucket], name, value);
527}
528
530{
531 if (!dict)
532 return ERR_NULL_PTR;
533
534 if (!name || !value)
535 return ERR_BAD_ARGS;
536
537 int ret_val = NO_ERROR;
538
539 if ((ret_val = kest_dictionary_ensure_capacity(dict)) != NO_ERROR)
540 return ret_val;
541
542 dict->entries[dict->n_entries].name = name;
544 dict->entries[dict->n_entries].value.val_expr = value;
545
546 dict->n_entries++;
547
548 uint32_t bucket = hash(name) & (KEST_DICTIONARY_N_BUCKETS - 1);
549
550 return kest_dictionary_bucket_add_entry_expr(&dict->buckets[bucket], name, value);
551}
552
554{
555 if (!dict)
556 return ERR_NULL_PTR;
557
558 if (!name || !value)
559 return ERR_BAD_ARGS;
560
561 int ret_val = NO_ERROR;
562
563 if ((ret_val = kest_dictionary_ensure_capacity(dict)) != NO_ERROR)
564 return ret_val;
565
566 dict->entries[dict->n_entries].name = name;
568 dict->entries[dict->n_entries].value.val_dict = value;
569
570 dict->n_entries++;
571
572 uint32_t bucket = hash(name) & (KEST_DICTIONARY_N_BUCKETS - 1);
573
574 return kest_dictionary_bucket_add_entry_dict(&dict->buckets[bucket], name, value);
575}
576
577int kest_dictionary_lookup(kest_dictionary *dict, const char *name, void *result, int type)
578{
579 if (!dict || !result || !name)
580 return ERR_NULL_PTR;
581
582 uint32_t bucket = hash(name) & (KEST_DICTIONARY_N_BUCKETS - 1);
583
584 return kest_dictionary_bucket_lookup(&dict->buckets[bucket], name, result, type);
585}
586
587int kest_dictionary_lookup_str(kest_dictionary *dict, const char *name, const char **result)
588{
589 return kest_dictionary_lookup(dict, name, result, DICT_ENTRY_TYPE_STR);
590}
591
592int kest_dictionary_lookup_float(kest_dictionary *dict, const char *name, float *result)
593{
594 return kest_dictionary_lookup(dict, name, result, DICT_ENTRY_TYPE_FLOAT);
595}
596
597int kest_dictionary_lookup_int(kest_dictionary *dict, const char *name, int *result)
598{
599 return kest_dictionary_lookup(dict, name, result, DICT_ENTRY_TYPE_INT);
600}
601
602int kest_dictionary_lookup_expr(kest_dictionary *dict, const char *name, kest_expression **result)
603{
604 return kest_dictionary_lookup(dict, name, result, DICT_ENTRY_TYPE_EXPR);
605}
606
607int kest_dictionary_lookup_dict(kest_dictionary *dict, const char *name, kest_dictionary **result)
608{
609 return kest_dictionary_lookup(dict, name, result, DICT_ENTRY_TYPE_SUBDICT);
610}
611
612int kest_dictionary_lookup_list(kest_dictionary *dict, const char *name, kest_dictionary_entry_list **result)
613{
614 return kest_dictionary_lookup(dict, name, result, DICT_ENTRY_TYPE_LIST);
615}
616
618{
619 if (!entry)
620 {
621 KEST_PRINTF("(null)");
622 return;
623 }
624 KEST_PRINTF("%s: ", entry->name);
625
626 switch (entry->type)
627 {
629 KEST_PRINTF("\"%s\"", entry->value.val_string);
630 break;
631
633 KEST_PRINTF("%d", entry->value.val_int);
634 break;
635
637 KEST_PRINTF("%f", entry->value.val_float);
638 break;
639
641 KEST_PRINTF("(expression)");
642 break;
643
644 default:
645 KEST_PRINTF("mangled !");
646 break;
647 }
648}
649
651{
652 KEST_PRINTF("Dictionary ");
653 if (!dict)
654 {
655 KEST_PRINTF("(null)\n");
656 return;
657 }
658
659 kest_string full_string;
660 kest_string_init(&full_string);
661
662 kest_string_appendf(&full_string, "\"%s\" (%d entries):\n", dict->name, dict->n_entries);
663
664 kest_string *string;
665 char *str = NULL;
666
667 for (int i = 0; i < dict->n_entries; i++)
668 {
669 kest_string_append(&full_string, '\t');
670 string = kest_dict_entry_to_string(&dict->entries[i]);
671 kest_string_concat(&full_string, string);
672 kest_string_destroy(string);
673 kest_string_append(&full_string, '\n');
674 }
675
676 str = kest_string_to_native(&full_string);
677 KEST_PRINTF("%s", str);
678 kest_free(str);
679 kest_string_destroy(&full_string);
680}
681
682#define LIST_ENTRY_NAME_BUF_LEN 128
683
685{
686 KEST_PRINTF("kest_parse_dict_list\n");
687
688 if (!ps || !dict || !result)
689 return ERR_NULL_PTR;
690
691 char *str;
692
694
695 kest_token_ll *current = ps->current_token;
696
697 if (!current)
698 return ERR_BAD_ARGS;
699
700 if (!result->name)
701 return ERR_BAD_ARGS;
702 int name_len = strlen(result->name);
703
704 if (name_len > LIST_ENTRY_NAME_BUF_LEN - 4)
705 return ERR_BAD_ARGS;
706
707 result->line = current->line;
708
709 int base_len;
710
712
713 int ret_val = NO_ERROR;
714
715 result->value.val_list = kest_parser_alloc(sizeof(kest_dictionary_entry_list));
716
717 if (!result->value.val_list)
718 return ERR_ALLOC_FAIL;
719
720 kest_dictionary_entry_list_init(result->value.val_list);
721
722 kest_string name;
723 kest_string *s;
724
726 goto parse_dict_list_fin;
727
728 kest_string_append_str(&name, dict->name);
729 kest_string_append(&name, '.');
730 kest_string_append_str(&name, result->name);
731
732 kest_string_append(&name, '[');
733
734 base_len = kest_string_len(&name);
735
736 kest_token_ll_skip_ws(&current);
737
738 int i = 0;
739
740 while (current)
741 {
742 while (kest_string_len(&name) > base_len)
744
745 kest_string_appendf(&name, "%d]", i);
746
748
749 KEST_PRINTF("Current entry: %s, current token: \"%s\"\n", str, current->data);
750
751 centry.name = str;
752
753 ps->current_token = current;
754
755 if ((ret_val = kest_parse_dict_val(ps, dict, &centry)) != NO_ERROR)
756 goto parse_dict_list_fin;
757
758 kest_dictionary_add_entry(dict, centry);
759 kest_dictionary_entry_list_append(result->value.val_list, centry);
760
761 current = ps->current_token;
762
763 s = kest_dict_entry_to_string(&centry);
764 str = kest_string_to_native(s);
765 KEST_PRINTF("Adding entry to list; %s. Current token is \"%s\"\n", str, current ? (current->data[0] == '\n' ? "\\n" : current->data) : "(NULL)");
766 kest_free(str);
768
769 kest_token_ll_skip_ws(&current);
770 if (!current || strcmp(current->data, "}") == 0)
771 break;
772
773 if (strcmp(current->data, ",") == 0)
774 kest_token_ll_advance(&current);
775
776 i++;
777 }
778
779 KEST_PRINTF("kest_parse_dict_list done\n");
780
781parse_dict_list_fin:
782
783 kest_token_ll_skip_ws(&current);
784
785 ps->current_token = current;
786
787 s = kest_dict_entry_to_string(result);
788 str = kest_string_to_native(s);
789
790 KEST_PRINTF("kest_parse_dict_list: result: %s\n", str);
791 kest_free(str);
793
794
795 KEST_PRINTF("kest_parse_dict_list done\n");
796 return ret_val;
797}
798
800{
801 KEST_PRINTF("kest_parse_dict_val\n");
802 if (!ps || !result)
803 return ERR_NULL_PTR;
804
805 kest_token_ll *current = ps->current_token;
806
807 if (!current)
808 return ERR_BAD_ARGS;
809
810 if (!current->data)
811 return ERR_BAD_ARGS;
812
813 kest_string *string;
814 char *str;
815
816 kest_token_ll *end = current;
817
818 int ret_val = NO_ERROR;
819 int len;
820
821 int paren_cnt = 0;
822 int n_tokens = 0;
823
824 int contains_semicolon = 0;
825
826 result->line = current->line;
827
828 while (end)
829 {
830 if (strcmp(end->data, ":") == 0)
831 {
832 contains_semicolon = 1;
833 }
834 else if (strcmp(end->data, "(") == 0)
835 {
836 paren_cnt++;
837 }
838 else if (strcmp(end->data, ")") == 0)
839 {
840 if (paren_cnt > 0)
841 paren_cnt--;
842 else
843 break;
844 }
845
846 if (paren_cnt == 0 && token_is_dict_entry_seperator(end->data))
847 break;
848
849 end = end->next;
850 n_tokens++;
851 }
852
853 if (current->data[0] == '"')
854 {
855 result->type = DICT_ENTRY_TYPE_STR;
856
857 len = strlen(current->data) - 2;
858 if (n_tokens > 1)
859 {
860 KEST_PRINTF("Syntax error (line %d): excess tokens following string %s\n", current->line, current->data);
861 ret_val = ERR_BAD_ARGS;
862 goto parse_dict_val_fin;
863 }
864
865 result->value.val_string = kest_parser_strndup(&current->data[1], len);
866
867 kest_token_ll_advance(&current);
868
869 goto parse_dict_val_fin;
870 }
871 else if (strcmp(current->data, "(") == 0 && contains_semicolon)
872 {
874 ps->current_token = current->next;
875 ret_val = kest_parse_dictionary(ps, &result->value.val_dict, result->name);
876
877 current = ps->current_token;
878
879 if (current && strcmp(current->data, ")") != 0)
880 {
881 kest_parser_error_at(ps, current, "Expected \")\", got \"%s\"", (current->data[0] == '\n') ? "\\n" : current->data);
882 }
883
884 kest_token_ll_advance(&current);
885
886 goto parse_dict_val_fin;
887 }
888 else if (strcmp(current->data, "{") == 0)
889 {
890 result->type = DICT_ENTRY_TYPE_LIST;
891 ps->current_token = current->next;
892 ret_val = kest_parse_dict_list(ps, dict, result);
893
894 current = ps->current_token;
895
896 if (current && strcmp(current->data, "}") != 0)
897 {
898 kest_parser_error_at(ps, current, "Expected \"}\", got \"%s\"", (current->data[0] == '\n') ? "\\n" : current->data);
899 }
900
901 kest_token_ll_advance(&current);
902
903 goto parse_dict_val_fin;
904 }
905 else
906 {
907 result->type = DICT_ENTRY_TYPE_EXPR;
908 result->value.val_expr = kest_parse_expression(ps, current, end);
909
910 if (!result->value.val_expr)
911 {
913 ret_val = ERR_BAD_ARGS;
914 }
915
916 current = ps->current_token;
917
918 goto parse_dict_val_fin;
919 }
920
921parse_dict_val_fin:
922
923 ps->current_token = current;
924
925 if (result && ret_val == NO_ERROR)
926 {
927 string = kest_dict_entry_to_string(result);
928 str = kest_string_to_native(string);
929 KEST_PRINTF("Obtained entry %s\n", str);
930 kest_free(str);
931 kest_string_destroy(string);
932 }
933
934 KEST_PRINTF("kest_parse_dict_val done\n");
935 return ret_val;
936}
937
939{
940 KEST_PRINTF("kest_parse_dictionary\n");
941 if (!ps || !result)
942 return ERR_NULL_PTR;
943
944 kest_token_ll *current = ps->current_token;
945 kest_token_ll *nt = NULL;
946
947 if (!current)
948 return ERR_BAD_ARGS;
949
951
952 int ret_val = NO_ERROR;
953
954 kest_dictionary *dict = NULL;
955
956 kest_string *string = NULL;
957 char *str;
958
959 dict = kest_new_dictionary();
960
961 if (!dict)
962 {
963 ret_val = ERR_ALLOC_FAIL;
964 goto parse_dict_fin;
965 }
966
967 char *cname;
968 dict->name = kest_parser_strndup(name, 128);
969
970 KEST_PRINTF("Parsing dictionary with name \"%s\"\n", dict->name);
971
972 kest_token_ll_skip_ws(&current);
973
974 while (current)
975 {
976 KEST_PRINTF("Looking for entry. Current token = \"%s\"\n", current->data[0] == '\n' ? "\\n" : current->data);
977 if (!token_is_name(current->data))
978 {
979 kest_parser_error_at(ps, current, "Expected name, got \"%s\"", current->data[0] == '\n' ? "\\n" : current->data);
980 ret_val = ERR_BAD_ARGS;
981 goto parse_dict_fin;
982 }
983
984 cname = kest_parser_strndup(current->data, 64);
985
986 if (!cname)
987 {
988 ret_val = ERR_ALLOC_FAIL;
989 goto parse_dict_fin;
990 }
991
992 centry.name = cname;
993
994 kest_token_ll_advance(&current);
995
996 if (!current || (strcmp(current->data, ":") != 0 && strcmp(current->data, "=") != 0))
997 {
998 kest_parser_error_at(ps, current, "Expected \":\" or \"=\", got \"%s\"", current->data);
999 ret_val = ERR_BAD_ARGS;
1000 goto parse_dict_fin;
1001 }
1002 kest_token_ll_advance(&current);
1003
1004 ps->current_token = current;
1005 if ((ret_val = kest_parse_dict_val(ps, dict, &centry)) != NO_ERROR)
1006 {
1007 kest_parser_error(ps, "Error parsing attribute %s.%s", dict->name, cname);
1008 goto parse_dict_fin;
1009 }
1010 else
1011 {
1012 kest_dictionary_add_entry(dict, centry);
1013 }
1014
1015 current = ps->current_token;
1016 kest_token_ll_skip_ws(&current);
1017
1018 if (!current || strcmp(current->data, ")") == 0)
1019 break;
1020
1021 if (strcmp(current->data, ",") == 0)
1022 kest_token_ll_advance(&current);
1023 }
1024
1025 *result = dict;
1026
1027parse_dict_fin:
1028
1029 ps->current_token = current;
1030 KEST_PRINTF("Done parsing dictionary; next token: \"%s\"\n", current ? (current->data[0] == '\n' ? "\\n" : current->data) : "(NULL)");
1031
1032 return ret_val;
1033}
void kest_free(void *ptr)
Definition kest_alloc.c:32
void * kest_allocator_alloc(kest_allocator *a, size_t n)
Definition kest_alloc.c:177
int kest_dictionary_bucket_lookup_expr(kest_dictionary_bucket *bucket, const char *name, kest_expression **result)
int kest_dictionary_lookup_dict(kest_dictionary *dict, const char *name, kest_dictionary **result)
int kest_dictionary_lookup_int(kest_dictionary *dict, const char *name, int *result)
int kest_dictionary_lookup_list(kest_dictionary *dict, const char *name, kest_dictionary_entry_list **result)
int kest_dictionary_bucket_lookup_int(kest_dictionary_bucket *bucket, const char *name, int *result)
int kest_dictionary_bucket_add_entry_int(kest_dictionary_bucket *bucket, const char *name, int value)
kest_string * kest_dict_entry_to_string(kest_dictionary_entry *entry)
void print_dict(kest_dictionary *dict)
int kest_dictionary_bucket_add_entry_float(kest_dictionary_bucket *bucket, const char *name, float value)
void print_dict_entry(kest_dictionary_entry *entry)
int kest_dictionary_bucket_add_entry_str(kest_dictionary_bucket *bucket, const char *name, const char *value)
int kest_dictionary_bucket_add_entry(kest_dictionary_bucket *bucket, kest_dictionary_entry entry)
int kest_dictionary_add_entry_float(kest_dictionary *dict, const char *name, float value)
int kest_dictionary_bucket_lookup_list(kest_dictionary_bucket *bucket, const char *name, kest_dictionary_entry_list **result)
int kest_dictionary_lookup_str(kest_dictionary *dict, const char *name, const char **result)
int kest_dictionary_bucket_lookup_float(kest_dictionary_bucket *bucket, const char *name, float *result)
#define LIST_ENTRY_NAME_BUF_LEN
int kest_dictionary_bucket_add_entry_dict(kest_dictionary_bucket *bucket, const char *name, kest_dictionary *value)
int kest_parse_dict_list(kest_eff_parsing_state *ps, kest_dictionary *dict, kest_dictionary_entry *result)
const char * kest_dict_entry_type_to_string(int type)
int kest_dictionary_bucket_lookup_str(kest_dictionary_bucket *bucket, const char *name, const char **result)
kest_dictionary * kest_new_dictionary()
int kest_dictionary_lookup_expr(kest_dictionary *dict, const char *name, kest_expression **result)
int kest_dictionary_bucket_lookup_dict(kest_dictionary_bucket *bucket, const char *name, kest_dictionary **result)
int kest_parse_dictionary(kest_eff_parsing_state *ps, kest_dictionary **result, const char *name)
int kest_dictionary_ensure_capacity(kest_dictionary *dict)
const char * kest_dict_entry_type_to_string_nice(int type)
int kest_dictionary_lookup_float(kest_dictionary *dict, const char *name, float *result)
int kest_dictionary_lookup(kest_dictionary *dict, const char *name, void *result, int type)
int kest_dictionary_add_entry_dict(kest_dictionary *dict, const char *name, kest_dictionary *value)
int kest_dictionary_bucket_init(kest_dictionary_bucket *bucket)
int kest_dictionary_add_entry(kest_dictionary *dict, kest_dictionary_entry entry)
int kest_dictionary_bucket_ensure_capacity(kest_dictionary_bucket *bucket)
int kest_dictionary_bucket_add_entry_expr(kest_dictionary_bucket *bucket, const char *name, kest_expression *value)
int kest_dictionary_bucket_lookup(kest_dictionary_bucket *bucket, const char *name, void *result, int type)
int kest_parse_dict_val(kest_eff_parsing_state *ps, kest_dictionary *dict, kest_dictionary_entry *result)
int kest_dictionary_add_entry_expr(kest_dictionary *dict, const char *name, kest_expression *value)
int kest_dictionary_add_entry_str(kest_dictionary *dict, const char *name, const char *value)
int kest_dictionary_add_entry_int(kest_dictionary *dict, const char *name, int value)
#define ERR_NOT_FOUND
#define DICT_ENTRY_TYPE_SUBDICT
#define ERR_WRONG_TYPE
#define DICT_ENTRY_TYPE_INT
#define DICT_ENTRY_TYPE_FLOAT
#define DICT_ENTRY_TYPE_STR
#define DICT_ENTRY_TYPE_LIST
#define DICT_ENTRY_TYPE_NOTHING
#define KEST_DICTIONARY_N_BUCKETS
#define DICT_ENTRY_TYPE_EXPR
char * kest_parser_strndup(const char *str, int n)
kest_allocator * kest_parser_allocator
void kest_parser_error(kest_eff_parsing_state *ps, const char *msg,...)
void * kest_parser_alloc(size_t size)
void kest_parser_error_at(kest_eff_parsing_state *ps, kest_token_ll *token, const char *msg,...)
#define ERR_ALLOC_FAIL
#define ERR_BAD_ARGS
#define NO_ERROR
#define ERR_NULL_PTR
kest_expression * kest_parse_expression(kest_eff_parsing_state *ps, kest_token_ll *tokens, kest_token_ll *tokens_end)
const char * kest_expression_to_string(kest_expression *expr)
#define IMPLEMENT_LIST(X)
Definition kest_list.h:33
#define KEST_PRINTF(...)
Definition kest_printf.h:10
int kest_string_concat(kest_string *a, kest_string *b)
Definition kest_string.c:92
int kest_string_pop_tail(kest_string *string)
int kest_string_append(kest_string *string, char x)
Definition kest_string.c:56
char * kest_string_to_native(kest_string *string)
int kest_string_init_with_allocator(kest_string *string, const kest_allocator *alloc)
Definition kest_string.c:36
int kest_string_appendf(kest_string *string, const char *fmt,...)
char * kest_string_to_native_with_allocator(kest_string *string, kest_allocator *alloc)
int kest_string_len(kest_string *string)
int kest_string_append_str(kest_string *string, const char *str)
Definition kest_string.c:73
int kest_string_init(kest_string *string)
Definition kest_string.c:12
int kest_string_destroy(kest_string *string)
Definition kest_string.c:97
char_list kest_string
Definition kest_string.h:6
int token_is_name(char *token)
int token_is_dict_entry_seperator(char *token)
int kest_token_ll_advance(kest_token_ll **list)
int kest_token_ll_skip_ws(kest_token_ll **list)
kest_dictionary_entry * entries
union kest_dictionary_entry::@135165320273153367332213364063306072146165325153 value
int line
const char * name
struct kest_dictionary * val_dict
struct kest_dictionary_entry_list * val_list
int type
int val_int
float val_float
kest_expression * val_expr
const char * val_string
kest_dictionary_entry * entries
kest_dictionary_bucket buckets[KEST_DICTIONARY_N_BUCKETS]
const char * name
kest_token_ll * current_token
struct kest_token_ll * next