-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.c
More file actions
197 lines (167 loc) · 5.52 KB
/
parser.c
File metadata and controls
197 lines (167 loc) · 5.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#include "parser.h"
#include "lexer.h"
#include <stdbool.h>
#include <stdint.h>
#define VEC_IMPLEMENTATION
#define VEC_ITEM_TYPE struct raon_value
#define VEC_SUFFIX raon_value
#include "vendor/vector.h"
#define VEC_ITEM_TYPE struct raon_entry
#define VEC_SUFFIX raon_entry
#include "vendor/vector.h"
// returns true on success
bool raon_is_valid_separator(struct raon_lexer *lexer, struct raon_token first_token,
const enum raon_token_type *optional_separator) {
return first_token.type == raon_token_type_newline || first_token.type == raon_token_type_comma
|| (optional_separator != NULL && first_token.type == *optional_separator);
}
struct raon_entry raon_parse_entry(struct raon_lexer *lexer, struct raon_token first_token) {
const struct raon_entry error_val = { .field_type = raon_field_type_error };
struct raon_entry entry = { 0 };
switch (first_token.type) {
case raon_token_type_field:
case raon_token_type_string:
entry.field_type = raon_field_type_string;
entry.str_field = first_token.str_val;
break;
case raon_token_type_int:
entry.field_type = raon_field_type_int;
entry.int_field = first_token.int_val;
break;
default:
return error_val;
}
struct raon_token token = raon_lexer_eat(lexer);
if (token.type != raon_token_type_equal) {
return error_val;
}
token = raon_lexer_eat(lexer);
struct raon_value val = raon_parse_value(lexer, token);
if (val.type == raon_value_type_error) {
return error_val;
}
entry.value = val;
return entry;
}
struct raon_value raon_parse_value(struct raon_lexer *lexer, struct raon_token first_token) {
const struct raon_value error_val = { .type = raon_value_type_error };
struct raon_value val = { 0 };
switch (first_token.type) {
case raon_token_type_string:
val.type = raon_value_type_string;
val.str_val = first_token.str_val;
break;
case raon_token_type_bool:
val.type = raon_value_type_bool;
val.bool_val = first_token.bool_val;
break;
case raon_token_type_int:
val.type = raon_value_type_int;
val.int_val = first_token.int_val;
break;
case raon_token_type_block_open:
val.type = raon_value_type_block;
val.block_val = raon_parse_block(lexer, first_token);
break;
case raon_token_type_array_open:
val.type = raon_value_type_array;
val.array_val = raon_parse_array(lexer, first_token);
break;
default:
return error_val;
}
return val;
}
struct vector_of_raon_value *raon_parse_array(
struct raon_lexer *lexer, struct raon_token first_token) {
if (first_token.type != raon_token_type_array_open) {
return NULL;
}
struct vector_of_raon_value *values = vec_new_raon_value();
for (;;) {
struct raon_token token = raon_lexer_eat(lexer);
if (token.type == raon_token_type_array_close) {
break;
}
struct raon_value val = raon_parse_value(lexer, token);
if (val.type == raon_value_type_error) {
vec_free_raon_value(values);
return NULL;
}
vec_push_raon_value(values, val);
token = raon_lexer_eat(lexer);
const enum raon_token_type array_close = raon_token_type_array_close;
if (!raon_is_valid_separator(lexer, token, &array_close)) {
vec_free_raon_value(values);
return NULL;
}
if (token.type == raon_token_type_array_close) {
break;
}
}
return values;
}
struct vector_of_raon_entry *raon_parse_block(
struct raon_lexer *lexer, struct raon_token first_token) {
if (first_token.type != raon_token_type_block_open) {
return NULL;
}
struct vector_of_raon_entry *entries = vec_new_raon_entry();
for (;;) {
struct raon_token token = raon_lexer_eat(lexer);
if (token.type == raon_token_type_error || token.type == raon_token_type_eof) {
vec_free_raon_entry(entries);
return NULL;
}
if (token.type == raon_token_type_block_close) {
break;
}
if (token.type == raon_token_type_newline) {
continue;
}
struct raon_entry entry = raon_parse_entry(lexer, token);
if (entry.field_type == raon_field_type_error) {
vec_free_raon_entry(entries);
return NULL;
}
vec_push_raon_entry(entries, entry);
token = raon_lexer_eat(lexer);
const enum raon_token_type block_close = raon_token_type_block_close;
if (!raon_is_valid_separator(lexer, token, &block_close)) {
vec_free_raon_entry(entries);
return NULL;
}
if (token.type == raon_token_type_block_close) {
break;
}
}
return entries;
}
// TODO: free tokens after they're used
// TODO: return NULL when parsing fails
struct vector_of_raon_entry *raon_parse(char *str) {
struct raon_lexer lexer = raon_lexer_init(str);
struct vector_of_raon_entry *entries = vec_new_raon_entry();
for (;;) {
struct raon_token token = raon_lexer_eat(&lexer);
if (token.type == raon_token_type_eof) {
break;
}
if (token.type == raon_token_type_newline) {
continue;
}
if (token.type == raon_token_type_error) {
// TODO free every entry
return NULL;
}
struct raon_entry entry = raon_parse_entry(&lexer, token);
if (entry.value.type != raon_value_type_error) {
vec_push_raon_entry(entries, entry);
}
token = raon_lexer_eat(&lexer);
if (!raon_is_valid_separator(&lexer, token, NULL)) {
break;
}
}
return entries;
}