@@ -5,17 +5,27 @@
5#include <ctype.h>
5#include <ctype.h>
6#include <stdio.h>
6#include <stdio.h>
8/////////////////////////////////////////////////////////////////////
10/////////////////////////////////////////////////////////////////////
13+int static inline end(str s){return s.start + s.length;}
11−str mkStr(int32_t start, int32_t length)
15+str static inline start_length(int32_t start, int32_t length)
17+ if (start < 0 || length < 0) assert(0);
14 res.start = start;
19 res.start = start;
15 res.length = length;
20 res.length = length;
16 return res;
21 return res;
24+str static inline start_end(int32_t start, int32_t end)
26+ return start_length(start, end - start);
19typedef struct
29typedef struct
@@ -51,21 +61,111 @@ struct document
52 char* body; // pointer to initial argument, not owned by us
62 char* body; // pointer to initial argument, not owned by us
54− int cursor; // things only used while parsing
64+ // things only used while parsing
55− int length;
65+ int cursor; // pointer to where we are in body
66+ int length; // total length of body
67+ // if cursor is >= length we have gone past the end
57 char* error_message;
69 char* error_message;
59 node_buffer nodes;
70 node_buffer nodes;
60 attr_buffer attrs;
71 attr_buffer attrs;
75+/////////////////////////////////////////////////////////////////////
86+void static inline render_char(render* r, char c)
88+ if (r->cursor < r->length)
89+ r->buffer[r->cursor] = c;
93+void static inline bound(char* msg, int index, int mn, int mx)
95+ if (index < mn || index > mx)
97+ printf("Bounds checking failed %s, got %i, which should be in %i:%i\n", msg, index, mn, mx);
102+void static inline bound_str(char* msg, str s, int mn, int mx)
104+ if (s.length < 0) assert(0);
105+ bound(msg, s.start, mn, mx);
106+ bound(msg, end(s), mn, mx);
109+void render_str(render* r, str s)
111+ bound_str("render_str", s, 0, r->d->length);
112+ render_char(r, '[');
113+ for (int i = 0; i < s.length; i++)
114+ render_char(r, r->d->body[s.start + i]);
115+ render_char(r, ']');
118+void render_tag(render* r, node* n);
120+void render_content(render* r, node* n)
122+ bound_str("render_conent inner", n->inner, 0, r->d->length);
123+ bound_str("render_conent nodes", n->nodes, 0, r->d->nodes.used_front);
124+ bound_str("render_conent attrs", n->attrs, 0, r->d->attrs.used);
126+ int done = n->inner.start;
127+ printf("%i\n", n->nodes.length);
128+ for (int i = 0; i < n->nodes.length; i++)
130+ node* x = &r->d->nodes.nodes[n->nodes.start + i];
131+ render_str(r, start_end(done, x->outer.start));
132+ done = end(x->outer);
135+ render_str(r, start_end(done, end(n->inner)));
138+void render_tag(render* r, node* n)
140+ render_char(r, '<');
141+ render_str(r, n->name);
142+ render_char(r, '>');
143+ render_content(r, n);
144+ render_char(r, '<');
145+ render_char(r, '/');
146+ render_str(r, n->name);
147+ render_char(r, '>');
150+int document_render(document* d, char* buffer, int length)
157+ node* me = document_node(d);
158+ assert(me->nodes.start == 1 && me->nodes.length == 1);
159+ render_content(&r, document_node(d));
64/////////////////////////////////////////////////////////////////////
164/////////////////////////////////////////////////////////////////////
65// NOT THE PARSER
165// NOT THE PARSER
67char* document_error(document* d){return d->error_message;}
167char* document_error(document* d){return d->error_message;}
68−node* document_node(document* d){return d->node;}
168+node* document_node(document* d){return &d->nodes.nodes[0];}
69str node_inner(node* n){return n->inner;}
169str node_inner(node* n){return n->inner;}
70str node_outer(node* n){return n->outer;}
170str node_outer(node* n){return n->outer;}
@@ -117,17 +217,45 @@ node* node_nextChildBy(document* d, node* parent, node* prev, char* s, int slen)
119/////////////////////////////////////////////////////////////////////
219/////////////////////////////////////////////////////////////////////
120−// PARSER PRIMITIVES
220+// PARSER COMBINATORS
122−int has(document* d, int ask){return (d->length - d->cursor) >= ask;}
222+char static inline peekAt(document* d, int i)
224+ int j = d->cursor + i;
225+ return j >= d->length ? 0 : d->body[j];
228+void static inline skip(document* d, int i){d->cursor += i;}
229+char static inline peek(document* d){return peekAt(d, 0);}
230+char static inline get(document* d){char c = peek(d); skip(d, 1); return c;}
232+// Remove whitespace characters from the cursor while they are still whitespace
124void trim(document* d)
233void trim(document* d)
126− while (has(d, 1) && isspace(grab(d->body[*p]))
235+ while (isspace(peek(d)))
127− *p += 1;
236+ skip(d, 1);
239+// Find this character form the cursor onwards, if true adjust the cursor to that char, otherwise leave it at the end
240+bool find(document* d, char c)
242+ char* start = &d->body[d->cursor];
243+ char* end = memchr(start, c, d->length - d->cursor);
246+ d->cursor = d->length;
251+ d->cursor += end - start;
257+/////////////////////////////////////////////////////////////////////
132void node_alloc(node_buffer* b, int ask)
260void node_alloc(node_buffer* b, int ask)
@@ -145,7 +273,8 @@ void attr_alloc(attr_buffer* b, int ask)
146void lexeme(char* msg, document* d, str s)
274void lexeme(char* msg, document* d, str s)
148− printf("Lexeme: %s, %i:%i, %.*s\n", msg, s.start, s.length, s.length, &d->body[s.start]);
277+ printf("Lexeme: %s, %i:%i, %.*s\n", msg, s.start, s.length, s.length, &d->body[s.start]);
151int isName(char c)
280int isName(char c)
@@ -155,82 +284,72 @@ int isName(char c)
156// you now expect a name, perhaps preceeded by whitespace
285// you now expect a name, perhaps preceeded by whitespace
157// the name may be empty
286// the name may be empty
158−str parse_name(document* d, int* p)
287+str parse_name(document* d)
160− printf("Before trim: %i\n", *p);
289+ trim(d);
162− printf("After trim: %i %c\n", *p, d->body[*p]);
164− res.start = *p;
291+ res.start = d->cursor;
165− while (*p < d->bodylen && isName(d->body[*p]))
292+ while (isName(peek(d)))
166− *p += 1;
293+ get(d);
167− printf("After trim: %i\n", *p);
168− res.length = *p - res.start;
294+ res.length = d->cursor - res.start;
169 lexeme("parse_name", d, res);
295 lexeme("parse_name", d, res);
170 return res;
296 return res;
173−str parse_attrval(document* d, int* p)
299+str parse_attrval(document* d)
175− trim(d, p);
301+ trim(d);
177− if (*p < d->bodylen || d->body[*p] != '=') return mkStr(0,0);
303+ if (peek(d) != '=') return start_length(0,0);
178− trim(d, p);
304+ trim(d);
179− return parse_name(d, p);
305+ return parse_name(d);
183// seen a tag name, now looking for attributes terminated by >
309// seen a tag name, now looking for attributes terminated by >
184// puts the attributes it finds in the attribute buffer
310// puts the attributes it finds in the attribute buffer
185−void parse_attributes(document* s, int* p)
311+str parse_attributes(document* d)
188−
314+ res.start = d->attrs.used;
315+ // do attribute parsing here
316+ res.length = d->attrs.used - res.start;
191−void parse_content(document* d, int* p);
320+str parse_content(document* d);
194// Add a new entry into tag, am at a '<'
323// Add a new entry into tag, am at a '<'
195−void parse_tag(document* d, int* p)
324+void parse_tag(document* d)
197− printf("Before parse_tag %i\n", *p);
326+ char c = get(d);
198− assert(d->body[*p] == '<');
327+ assert(c == '<');
200 node_alloc(&d->nodes, 1);
329 node_alloc(&d->nodes, 1);
201 int me = d->nodes.used_back;
330 int me = d->nodes.used_back;
202 d->nodes.used_back++;
331 d->nodes.used_back++;
205− printf("After increment %i\n", *p);
206− d->nodes.nodes[me].name = parse_name(d, p);
333+ d->nodes.nodes[me].name = parse_name(d);
208− d->nodes.nodes[me].attrs.start = d->attrs.used;
209− parse_attributes(d, p);
334+ d->nodes.nodes[me].attrs = parse_attributes(d);
210− d->nodes.nodes[me].attrs.length = d->attrs.used;
212− if (d->bodylen - *p >= 2 &&
336+ c = peek(d);
213− (d->body[*p] == '/' || d->body[*p] == '?') &&
337+ if ((c == '/' || c == '?') && peekAt(d, 1) == '>')
214− d->body[*p + 1] == '>')
216− *p += 2;
339+ skip(d, 2);
340+ d->nodes.nodes[me].nodes = start_length(0, 0);
220− d->nodes.nodes[me].nodes.start = 42;
343+ d->nodes.nodes[me].nodes = parse_content(d);
221− parse_content(d, p);
222− d->nodes.nodes[me].nodes.length = 42;
224 if (d->error_message != NULL) return;
345 if (d->error_message != NULL) return;
225− if (d->bodylen - *p >= 2 &&
346+ if (peek(d) == '<' && peekAt(d, 1) == '/')
226− d->body[*p] == '<' &&
227− d->body[*p + 1] == '/')
229− *p += 2;
348+ skip(d, 2);
230− str close = parse_name(d, p);
349+ str close = parse_name(d);
231 lexeme("openning tag", d, d->nodes.nodes[me].name);
350 lexeme("openning tag", d, d->nodes.nodes[me].name);
232 lexeme("closing tag", d, close);
351 lexeme("closing tag", d, close);
233− trim(d, p);
352+ trim(d);
234 if (close.length == d->nodes.nodes[me].name.length &&
353 if (close.length == d->nodes.nodes[me].name.length &&
235 memcmp(&d->body[close.start], &d->body[d->nodes.nodes[me].name.start], close.length) == 0)
354 memcmp(&d->body[close.start], &d->body[d->nodes.nodes[me].name.start], close.length) == 0)
@@ -240,47 +359,38 @@ void parse_tag(document* d, int* p)
240 d->error_message = strdup("Weirdness when trying to close tags");
359 d->error_message = strdup("Weirdness when trying to close tags");
243−// Parser until </
362+// Parser until </, return the index of your node children
244−void parse_content(document* d, int* p)
363+str parse_content(document* d)
246 int before = d->nodes.used_back;
365 int before = d->nodes.used_back;
247 while (d->error_message == NULL)
366 while (d->error_message == NULL)
249 // only < can have any impact
368 // only < can have any impact
250− char* res = memchr(&d->body[*p], '<', d->bodylen - *p);
369+ if (!find(d, '<'))
251− printf("%i - %i = %i\n", d->bodylen, *p, d->bodylen - *p);
255− printf("break 0\n");
259− if (*p + 1 == d->bodylen)
261− // final character of string is <
262− printf("break 1\n");
265− else if (d->body[*p + 1] == '/')
373+ if (peekAt(d, 1) == '/')
267 // have found a </
375 // have found a </
268− printf("break 2\n");
273− printf("calling parse_tag\n");
380+ printf("parsing a tag\n");
274− parse_tag(d, p);
381+ parse_tag(d);
277 int diff = d->nodes.used_back - before;
384 int diff = d->nodes.used_back - before;
278 node_alloc(&d->nodes, diff);
385 node_alloc(&d->nodes, diff);
386+ str res = start_length(d->nodes.used_front, diff);
388+ printf("res %i %i\n", res.start, res.length);
280−// for (int i = 0; i < diff; i++)
389+ for (int i = 0; i < diff; i++)
281−// d->nodes.nodes[d->nodes.used_front + i] = d->nodes.nodes[d->nodes.size - d->nodes.used_back - i];
390+ d->nodes.nodes[d->nodes.used_front + i] = d->nodes.nodes[d->nodes.size - d->nodes.used_back - i];
282 d->nodes.used_front += diff;
391 d->nodes.used_front += diff;
283 d->nodes.used_back -= diff;
392 d->nodes.used_back -= diff;
286document* document_parse(char* s, int slen)
396document* document_parse(char* s, int slen)
@@ -289,9 +399,9 @@ document* document_parse(char* s, int slen)
290 document* d = malloc(sizeof(document));
400 document* d = malloc(sizeof(document));
291 d->body = s;
401 d->body = s;
292− d->bodylen = slen;
402+ d->cursor = 0;
293 d->error_message = NULL;
404 d->error_message = NULL;
295 d->attrs.size = 0;
405 d->attrs.size = 0;
296 d->attrs.used = 0;
406 d->attrs.used = 0;
297 d->attrs.attrs = NULL;
407 d->attrs.attrs = NULL;
@@ -300,15 +410,23 @@ document* document_parse(char* s, int slen)
300 d->nodes.used_front = 1;
410 d->nodes.used_front = 1;
301 d->nodes.nodes = malloc(sizeof(node) * 1000);
411 d->nodes.nodes = malloc(sizeof(node) * 1000);
303− d->nodes.nodes[0].name = mkStr(0, 0);
413+ d->nodes.nodes[0].name = start_length(0, 0);
304− d->nodes.nodes[0].outer = mkStr(0, slen);
414+ d->nodes.nodes[0].outer = start_length(0, slen);
305− d->nodes.nodes[0].inner = mkStr(0, slen);
415+ d->nodes.nodes[0].inner = start_length(0, slen);
306− d->nodes.nodes[0].attrs = mkStr(0, 0);
416+ d->nodes.nodes[0].attrs = start_length(0, 0);
308− parse_content(d, &p);
417+ d->nodes.nodes[0].nodes = parse_content(d);
419+ node* me = &d->nodes.nodes[0];
420+// printf("Got %i %i\n", me->nodes.start, me->nodes.length);
421+ assert(me->nodes.start == 1 && me->nodes.length == 1);
423+ me = &d->nodes.nodes[1];
424+// printf("Got %i %i\n", me->nodes.start, me->nodes.length);
425+ assert(me->nodes.length == 0);
309− if (p != slen && d->error_message == NULL)
427+ if (d->cursor < d->length && d->error_message == NULL)
311− printf("%i vs %i\n", p, slen);
429+ printf("%i vs %i\n", d->cursor, d->length);
312 d->error_message = strdup("Trailing junk at the end of the document");
430 d->error_message = strdup("Trailing junk at the end of the document");
314 return d;
432 return d;