@@ -225,6 +225,35 @@ node* node_nextChildBy(document* d, node* parent, node* prev, char* s, int slen)
228+/////////////////////////////////////////////////////////////////////
231+const char tag_name1 = 0x1;
232+const char tag_name = 0x2;
233+const char tag_space = 0x4;
235+char parse_table[256];
237+void init_parse_table()
239+ static bool done = 0;
241+ for (int i = 0; i < 256; i++)
243+ bool name1 = i == ':' || i == '_' || (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z');
244+ bool name = name1 || i == '-' || (i >= '0' && i <= '9');
245+ bool space = i == ' ' || i == '\t' || i == '\r' || i == '\n';
246+ parse_table[i] = (name1 ? tag_name1 : 0) | (name ? tag_name : 0) | (space ? tag_space : 0);
251+bool static inline is(char c, char tag) { return parse_table[c] & tag; }
252+bool static inline is_name1(char c) { return is(c, tag_name1); }
253+bool static inline is_name(char c) { return is(c, tag_name); }
254+bool static inline is_space(char c) { return is(c, tag_space); }
228/////////////////////////////////////////////////////////////////////
257/////////////////////////////////////////////////////////////////////
229// PARSER COMBINATORS
258// PARSER COMBINATORS
@@ -238,8 +267,6 @@ void static inline skip(document* d, int i){d->cursor += i;}
238char static inline peek(document* d){return peekAt(d, 0);}
267char static inline peek(document* d){return peekAt(d, 0);}
239char static inline get(document* d){char c = peek(d); skip(d, 1); return c;}
268char static inline get(document* d){char c = peek(d); skip(d, 1); return c;}
241−bool static inline is_space(char c){ return c == ' ' || c == '\t' || c == '\r' || c == '\n';}
243// Remove whitespace characters from the cursor while they are still whitespace
270// Remove whitespace characters from the cursor while they are still whitespace
244void static inline trim(document* d)
271void static inline trim(document* d)
@@ -286,15 +313,6 @@ void attr_alloc(attr_buffer* b, int ask)
286 b->attrs = buf2;
313 b->attrs = buf2;
289−int static inline isName(char c)
292− (c >= 'a' && c <= 'z') ||
293− (c >= 'A' && c <= 'Z') ||
294− (c >= '0' && c <= '9') ||
295− c == '_' || c == '-';
298// you now expect a name, perhaps preceeded by whitespace
316// you now expect a name, perhaps preceeded by whitespace
299// the name may be empty
317// the name may be empty
300str parse_name(document* d)
318str parse_name(document* d)
@@ -302,8 +320,11 @@ str parse_name(document* d)
304 res.start = d->cursor;
322 res.start = d->cursor;
323+ if (!is_name1(peek(d)))
324+ return start_length(d->cursor, 0);
305− while (isName(peek(d)))
326+ while (is_name(peek(d)))
306− get(d);
327+ skip(d, 1);
307 res.length = d->cursor - res.start;
328 res.length = d->cursor - res.start;
308 return res;
329 return res;
@@ -443,6 +464,7 @@ str parse_content(document* d)
443document* document_parse(char* s, int slen)
464document* document_parse(char* s, int slen)
445 if (slen == -1) slen = strlen(s);
466 if (slen == -1) slen = strlen(s);
447 document* d = malloc(sizeof(document));
469 document* d = malloc(sizeof(document));
448 d->body = s;
470 d->body = s;