diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-24 16:53:08 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-24 16:53:08 +0300 |
commit | 26a84bc3a797d60998b3ad6c3732c76ebc154f8c (patch) | |
tree | 6cfe675cd89ff9fb2482ace828317fbb7222ef51 /src | |
parent | 489dee21c5b9635cba804357ab818583659f43ad (diff) | |
download | grecs-26a84bc3a797d60998b3ad6c3732c76ebc154f8c.tar.gz grecs-26a84bc3a797d60998b3ad6c3732c76ebc154f8c.tar.bz2 |
Improve git parser.
* src/git-parser.c (token)<tag>: Remove.
(token)<path>: New field.
(rawinput): Set input_char to 0 on EOF.
(collect_tag): Remove.
(collect_unquoted,collect_subsection_name): New functions.
(collect_string): Remove.
(gettoken): Handle multiple subsections.
Handle dot-delimited section names.
(create_subsection_node): New function.
(read_section): Rewrite using create_subsection_node.
(grecs_git_parser): Initialize and free tok.path.
* tests/git.conf: Provide a dot-delimited section name.
* tests/parser-git.at: Change. expected output.
Diffstat (limited to 'src')
-rw-r--r-- | src/git-parser.c | 157 |
1 files changed, 102 insertions, 55 deletions
diff --git a/src/git-parser.c b/src/git-parser.c index 37eeab7..4ab64be 100644 --- a/src/git-parser.c +++ b/src/git-parser.c | |||
@@ -37,9 +37,9 @@ static struct grecs_txtacc *acc; | |||
37 | struct token { | 37 | struct token { |
38 | int type; | 38 | int type; |
39 | char *buf; | 39 | char *buf; |
40 | char *tag; | ||
41 | char chbuf[2]; | 40 | char chbuf[2]; |
42 | int putback; | 41 | int putback; |
42 | struct grecs_list *path; | ||
43 | } tok; | 43 | } tok; |
44 | 44 | ||
45 | #define ISSPACE(c) (strchr(" \t\r\f\n", c) != NULL) | 45 | #define ISSPACE(c) (strchr(" \t\r\f\n", c) != NULL) |
@@ -50,10 +50,12 @@ static int | |||
50 | rawinput() | 50 | rawinput() |
51 | { | 51 | { |
52 | if (!infile || feof(infile)) | 52 | if (!infile || feof(infile)) |
53 | return 0; | 53 | return input_char = 0; |
54 | input_char = fgetc(infile); | 54 | input_char = fgetc(infile); |
55 | if (input_char == '\n') | 55 | if (input_char == '\n') |
56 | grecs_current_locus.line++; | 56 | grecs_current_locus.line++; |
57 | else if (input_char < 0) | ||
58 | input_char == 0; | ||
57 | return input_char; | 59 | return input_char; |
58 | } | 60 | } |
59 | 61 | ||
@@ -86,13 +88,23 @@ error_recovery() | |||
86 | } | 88 | } |
87 | 89 | ||
88 | static void | 90 | static void |
89 | collect_tag() | 91 | collect_unquoted() |
90 | { | 92 | { |
93 | do | ||
94 | grecs_txtacc_grow_char(acc, input_char); | ||
91 | while (input() && | 95 | while (input() && |
92 | !(ISSPACE(input_char) || input_char == ']')) | 96 | !(ISSPACE(input_char) || input_char == ']')); |
97 | |||
98 | } | ||
99 | |||
100 | static void | ||
101 | collect_subsection_name() | ||
102 | { | ||
103 | do | ||
93 | grecs_txtacc_grow_char(acc, input_char); | 104 | grecs_txtacc_grow_char(acc, input_char); |
94 | grecs_txtacc_grow_char(acc, 0); | 105 | while (input() && |
95 | tok.tag = grecs_txtacc_finish(acc, 0); | 106 | (isalnum(input_char) || input_char == '_' || |
107 | input_char == '-')); | ||
96 | } | 108 | } |
97 | 109 | ||
98 | static void | 110 | static void |
@@ -122,14 +134,6 @@ collect_substring() | |||
122 | } | 134 | } |
123 | 135 | ||
124 | static void | 136 | static void |
125 | collect_string() | ||
126 | { | ||
127 | collect_substring(); | ||
128 | grecs_txtacc_grow_char(acc, 0); | ||
129 | tok.tag = grecs_txtacc_finish(acc, 0); | ||
130 | } | ||
131 | |||
132 | static void | ||
133 | gettoken(void) | 137 | gettoken(void) |
134 | { | 138 | { |
135 | int putback = tok.putback; | 139 | int putback = tok.putback; |
@@ -137,7 +141,7 @@ gettoken(void) | |||
137 | if (putback) | 141 | if (putback) |
138 | return; | 142 | return; |
139 | 143 | ||
140 | tok.buf = tok.tag = NULL; | 144 | tok.buf = NULL; |
141 | /* Skip whitespace */ | 145 | /* Skip whitespace */ |
142 | while (input() && ISSPACE(input_char)) | 146 | while (input() && ISSPACE(input_char)) |
143 | ; | 147 | ; |
@@ -148,38 +152,70 @@ gettoken(void) | |||
148 | } | 152 | } |
149 | 153 | ||
150 | if (input_char == '[') { | 154 | if (input_char == '[') { |
155 | int dot_delimited = -1; | ||
156 | |||
151 | tok.type = TOK_SECTION; | 157 | tok.type = TOK_SECTION; |
152 | while (input() && | 158 | grecs_list_clear(tok.path); |
153 | !(ISSPACE(input_char) || input_char == ']')) | 159 | input(); |
154 | grecs_txtacc_grow_char(acc, input_char); | 160 | for (;;) { |
155 | grecs_txtacc_grow_char(acc, 0); | 161 | char *p; |
156 | tok.buf = grecs_txtacc_finish(acc, 0); | 162 | |
157 | if (input_char != ']') { | 163 | if (!dot_delimited) |
158 | while (input() && ISSPACE(input_char)) | 164 | while (ISSPACE(input_char)) |
159 | ; | 165 | input(); |
160 | if (input_char == '"') | 166 | else { |
161 | collect_string(); | 167 | if (input_char == ']') |
162 | else if (input_char != ']') | 168 | break; |
163 | collect_tag(); | 169 | if (dot_delimited == 1) |
164 | } | 170 | input(); |
165 | if (input_char != ']') { | 171 | } |
166 | while (input() && ISSPACE(input_char)) | 172 | |
167 | ; | 173 | if (input_char == TOK_EOF) { |
168 | if (input_char != ']') { | 174 | grecs_error(&grecs_current_locus, 0, |
169 | if (isascii(input_char) && isprint(input_char)) | 175 | "unexpected EOF in section header"); |
170 | grecs_error(&grecs_current_locus, 0, | 176 | tok.type = TOK_ERR; |
171 | "expected `]' but found `%c'", | 177 | return; |
172 | input_char); | 178 | } |
173 | else if (!input_char) | 179 | if (input_char == ']') |
174 | grecs_error(&grecs_current_locus, 0, | 180 | break; |
175 | "expected `]' but found EOF"); | 181 | if (input_char == '\n') { |
176 | else | 182 | grecs_error(&grecs_current_locus, 0, |
177 | grecs_error(&grecs_current_locus, 0, | 183 | "unexpect newline in in section header"); |
178 | "expected `]' but found \\%03o", | ||
179 | (unsigned char)input_char); | ||
180 | tok.type = TOK_ERR; | 184 | tok.type = TOK_ERR; |
185 | return; | ||
181 | } | 186 | } |
187 | |||
188 | if (dot_delimited != 1 && input_char == '"') { | ||
189 | collect_substring(); | ||
190 | input(); | ||
191 | dot_delimited = 0; | ||
192 | } else if (dot_delimited == 1) | ||
193 | collect_subsection_name(); | ||
194 | else | ||
195 | collect_unquoted(); | ||
196 | if (dot_delimited == -1) | ||
197 | dot_delimited = input_char == '.'; | ||
198 | else if (dot_delimited == 1) { | ||
199 | if (input_char != '.' && input_char != ']') { | ||
200 | grecs_error(&grecs_current_locus, 0, | ||
201 | "unexpected character in section header"); | ||
202 | tok.type = TOK_ERR; | ||
203 | return; | ||
204 | } | ||
205 | } | ||
206 | grecs_txtacc_grow_char(acc, 0); | ||
207 | p = grecs_txtacc_finish(acc, 0); | ||
208 | grecs_list_append(tok.path, p); | ||
209 | } | ||
210 | |||
211 | if (grecs_list_size(tok.path) == 0) { | ||
212 | grecs_error(&grecs_current_locus, 0, | ||
213 | "empty section header"); | ||
214 | tok.type = TOK_ERR; | ||
215 | return; | ||
182 | } | 216 | } |
217 | |||
218 | tok.type = TOK_SECTION; | ||
183 | return; | 219 | return; |
184 | } | 220 | } |
185 | 221 | ||
@@ -293,6 +329,26 @@ read_statement_list(struct grecs_node *parent) | |||
293 | ; | 329 | ; |
294 | } | 330 | } |
295 | 331 | ||
332 | struct grecs_node * | ||
333 | create_subsection_node(struct grecs_node *root) | ||
334 | { | ||
335 | struct grecs_list_entry *ep; | ||
336 | struct grecs_node *p; | ||
337 | |||
338 | for (ep = tok.path->head; ep; ep = ep->next) { | ||
339 | char *ident = ep->data; | ||
340 | p = grecs_find_node(root, ident); | ||
341 | if (!p) { | ||
342 | p = grecs_node_create(grecs_node_block, | ||
343 | &grecs_current_locus); | ||
344 | p->ident = grecs_strdup(ident); | ||
345 | grecs_node_bind(root, p, 1); | ||
346 | } | ||
347 | root = p; | ||
348 | } | ||
349 | return root; | ||
350 | } | ||
351 | |||
296 | static int | 352 | static int |
297 | read_section(struct grecs_node *parent) | 353 | read_section(struct grecs_node *parent) |
298 | { | 354 | { |
@@ -300,17 +356,7 @@ read_section(struct grecs_node *parent) | |||
300 | if (tok.type == TOK_EOF) | 356 | if (tok.type == TOK_EOF) |
301 | return 0; | 357 | return 0; |
302 | else if (tok.type == TOK_SECTION) { | 358 | else if (tok.type == TOK_SECTION) { |
303 | struct grecs_node *node = | 359 | struct grecs_node *node = create_subsection_node(parent); |
304 | grecs_node_create(grecs_node_block, | ||
305 | &grecs_current_locus); | ||
306 | node->ident = grecs_strdup(tok.buf); | ||
307 | if (tok.tag) { | ||
308 | struct grecs_value *val= grecs_malloc(sizeof(val[0])); | ||
309 | val->type = GRECS_TYPE_STRING; | ||
310 | val->v.string = grecs_strdup(tok.tag); | ||
311 | node->v.value = val; | ||
312 | } | ||
313 | grecs_node_bind(parent, node, 1); | ||
314 | read_statement_list(node); | 360 | read_statement_list(node); |
315 | } else if (tok.type == TOK_KEYWORD) { | 361 | } else if (tok.type == TOK_K |