on master help sign in
Improve the parsing in various ways, clean up lots of details
78bf30bNeil Mitchell
hexml.c+53−17
@@ -139,6 +139,16 @@ void render_tag(render* r, node* n)
139{
139{
140 render_char(r, '<');
140 render_char(r, '<');
141 render_str(r, n->name);
141 render_str(r, n->name);
142+ for (int i = 0; i < n->attrs.length; i++)
143+ {
144+ attr* x = &r->d->attrs.attrs[n->attrs.start + i];
145+ render_char(r, ' ');
146+ render_str(r, x->name);
147+ render_char(r, '=');
148+ render_char(r, '\"');
149+ render_str(r, x->value);
150+ render_char(r, '\"');
151+ }
142 render_char(r, '>');
152 render_char(r, '>');
143 render_content(r, n);
153 render_content(r, n);
144 render_char(r, '<');
154 render_char(r, '<');
@@ -270,7 +280,11 @@ void attr_alloc(attr_buffer* b, int ask)
270{
280{
271 int space = b->size - b->used;
281 int space = b->size - b->used;
272 if (space >= ask) return;
282 if (space >= ask) return;
273− assert(0);
283+ int size2 = (b->size + 1000 + ask) * 2;
284+ attr* buf2 = malloc(size2 * sizeof(attr));
285+ memcpy(buf2, b->attrs, b->used * sizeof(attr));
286+ free(b->attrs);
287+ b->attrs = buf2;
274}
288}
275
289
276void lexeme(char* msg, document* d, str s)
290void lexeme(char* msg, document* d, str s)
@@ -302,18 +316,42 @@ str parse_attrval(document* d)
302{
316{
303 trim(d);
317 trim(d);
304 if (peek(d) != '=') return start_length(0,0);
318 if (peek(d) != '=') return start_length(0,0);
319+ skip(d, 1);
305 trim(d);
320 trim(d);
321+ char c = peek(d);
322+ if (c == '\"' || c == '\'')
323+ {
324+ skip(d, 1);
325+ int start = d->cursor;
326+ if (!find(d, c))
327+ {
328+ d->error_message = _strdup("Couldn't find closing attribute bit");
329+ return start_length(0, 0);
330+ }
331+ skip(d, 1);
332+ return start_end(start, d->cursor - 1);
333+ }
334+ else
306− return parse_name(d);
335+ return parse_name(d);
307}
336}
308
337
309
338
339+
310// seen a tag name, now looking for attributes terminated by >
340// seen a tag name, now looking for attributes terminated by >
311// puts the attributes it finds in the attribute buffer
341// puts the attributes it finds in the attribute buffer
312str parse_attributes(document* d)
342str parse_attributes(document* d)
313{
343{
314 str res;
344 str res;
315 res.start = d->attrs.used;
345 res.start = d->attrs.used;
316− // do attribute parsing here
346+ for (int i = 0; ; i++)
347+ {
348+ str name = parse_name(d);
349+ if (name.length == 0) break;
350+ attr_alloc(&d->attrs, 1);
351+ d->attrs.attrs[d->attrs.used].name = name;
352+ d->attrs.attrs[d->attrs.used].value = parse_attrval(d);
353+ d->attrs.used++;
354+ }
317 res.length = d->attrs.used - res.start;
355 res.length = d->attrs.used - res.start;
318 return res;
356 return res;
319}
357}
@@ -328,22 +366,27 @@ void parse_tag(document* d)
328 d->nodes.used_back++;
366 d->nodes.used_back++;
329 int me = d->nodes.size - d->nodes.used_back;
367 int me = d->nodes.size - d->nodes.used_back;
330
368
369+ d->nodes.nodes[me].outer.start = d->cursor;
331 char c = get(d);
370 char c = get(d);
332 assert(c == '<');
371 assert(c == '<');
333−
372+ if (peek(d) == '?') skip(d, 1);
334− d->nodes.nodes[me].outer.start = d->cursor;
335 d->nodes.nodes[me].name = parse_name(d);
373 d->nodes.nodes[me].name = parse_name(d);
336 d->nodes.nodes[me].attrs = parse_attributes(d);
374 d->nodes.nodes[me].attrs = parse_attributes(d);
337
375
338− c = peek(d);
376+ c = get(d);
339− if ((c == '/' || c == '?') && peekAt(d, 1) == '>')
377+ if ((c == '/' || c == '?') && peek(d) == '>')
340 {
378 {
341− skip(d, 2);
379+ skip(d, 1);
342 d->nodes.nodes[me].nodes = start_length(0, 0);
380 d->nodes.nodes[me].nodes = start_length(0, 0);
343 d->nodes.nodes[me].outer.length = start_end(d->nodes.nodes[me].outer.start, d->cursor).length;
381 d->nodes.nodes[me].outer.length = start_end(d->nodes.nodes[me].outer.start, d->cursor).length;
344 d->nodes.nodes[me].inner = start_length(d->cursor, 0);
382 d->nodes.nodes[me].inner = start_length(d->cursor, 0);
345 return;
383 return;
346 }
384 }
385+ else if (c != '>')
386+ {
387+ d->error_message = _strdup("Gunk at the end of the tag");
388+ return;
389+ }
347 d->nodes.nodes[me].inner.start = d->cursor;
390 d->nodes.nodes[me].inner.start = d->cursor;
348 d->nodes.nodes[me].nodes = parse_content(d);
391 d->nodes.nodes[me].nodes = parse_content(d);
349 d->nodes.nodes[me].inner.length = start_end(d->nodes.nodes[me].inner.start, d->cursor).length;
392 d->nodes.nodes[me].inner.length = start_end(d->nodes.nodes[me].inner.start, d->cursor).length;
@@ -358,7 +401,8 @@ void parse_tag(document* d)
358 trim(d);
401 trim(d);
359 d->nodes.nodes[me].outer.length = start_end(d->nodes.nodes[me].outer.start, d->cursor).length;
402 d->nodes.nodes[me].outer.length = start_end(d->nodes.nodes[me].outer.start, d->cursor).length;
360 if (close.length == d->nodes.nodes[me].name.length &&
403 if (close.length == d->nodes.nodes[me].name.length &&
361− memcmp(&d->body[close.start], &d->body[d->nodes.nodes[me].name.start], close.length) == 0)
404+ memcmp(&d->body[close.start], &d->body[d->nodes.nodes[me].name.start], close.length) == 0 &&
405+ get(d) == '>');
362 return;
406 return;
363 d->error_message = _strdup("Mismatch in closing tags");
407 d->error_message = _strdup("Mismatch in closing tags");
364 return;
408 return;
@@ -423,14 +467,6 @@ document* document_parse(char* s, int slen)
423 d->nodes.nodes[0].attrs = start_length(0, 0);
467 d->nodes.nodes[0].attrs = start_length(0, 0);
424 d->nodes.nodes[0].nodes = parse_content(d);
468 d->nodes.nodes[0].nodes = parse_content(d);
425
469
426− node* me = &d->nodes.nodes[0];
427−// printf("Got %i %i\n", me->nodes.start, me->nodes.length);
428− assert(me->nodes.start == 1 && me->nodes.length == 1);
429−
430− me = &d->nodes.nodes[1];
431−// printf("Got %i %i\n", me->nodes.start, me->nodes.length);
432− assert(me->nodes.length == 0);
433−
434 if (d->cursor < d->length && d->error_message == NULL)
470 if (d->cursor < d->length && d->error_message == NULL)
435 {
471 {
436 printf("%i vs %i\n", d->cursor, d->length);
472 printf("%i vs %i\n", d->cursor, d->length);