aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-05-24 16:53:08 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2011-05-24 16:53:08 +0300
commit26a84bc3a797d60998b3ad6c3732c76ebc154f8c (patch)
tree6cfe675cd89ff9fb2482ace828317fbb7222ef51 /src
parent489dee21c5b9635cba804357ab818583659f43ad (diff)
downloadgrecs-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.c157
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;
37struct token { 37struct 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
50rawinput() 50rawinput()
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
88static void 90static void
89collect_tag() 91collect_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
100static void
101collect_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
98static void 110static void
@@ -122,14 +134,6 @@ collect_substring()
122} 134}
123 135
124static void 136static void
125collect_string()
126{
127 collect_substring();
128 grecs_txtacc_grow_char(acc, 0);
129 tok.tag = grecs_txtacc_finish(acc, 0);
130}
131
132static void
133gettoken(void) 137gettoken(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
332struct grecs_node *
333create_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
296static int 352static int
297read_section(struct grecs_node *parent) 353read_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