2024-11-24 14:48 UTC

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0002090Hubbub[All Projects] Generalpublic2014-06-12 11:24
ReporterAchal 
Assigned ToJohn-Mark Bell 
PrioritynormalSeverityfeatureReproducibilityalways
StatusacknowledgedResolutionopen 
PlatformlinuxOSubuntuOS Version13.10
Product Version 
Target VersionFixed in Version 
Summary0002090: updating some tokeniser test to html5lib
Descriptioncdata.test
entities.test
numericEntities.test
test1.test
test2.test
test3.test
test4.test
unicodeChars.test

are the test suits which are updated to html5lib tests and passed on tokeniser2 after this patch
Additional InformationFROM TEST4.TEST
{"description":"Maximum non-BMP numeric entity",
"input":"",
"output":["ParseError", ["Character", "\uDBFF\uDFFF"]]},

and

FROM NUMERICENTITIES.TEST
{"description": "Invalid numeric entity character U+10FFFF",
"input": "",
"output": ["ParseError", ["Character", "\uFFFD"]]},

are two conflicting tests. So I used first one because it is in accordance with html5 specs.
TagsNo tags attached.
Fixed in CI build #
Reported in CI build #
Attached Files
  • diff file icon libhubbub-test.diff (293,757 bytes) 2014-03-09 14:48
  • diff file icon rewrite.diff (301,032 bytes) 2014-03-11 16:29
  • patch file icon 0001-Rewriting-whole-tokenizer-and-updating-its-tests.patch (255,232 bytes) 2014-03-11 17:00 -
    From 668aa257611e13522f85e1527c495a75a5061f10 Mon Sep 17 00:00:00 2001
    From: Achal-Aggarwal <theachalaggarwal@gmail.com>
    Date: Mon, 10 Mar 2014 21:49:38 +0530
    Subject: [PATCH 1/4] Rewriting whole tokenizer and updating its tests.
    
    ---
     src/tokeniser/tokeniser.c                 |  598 +++---
     test/data/tokeniser2/numericEntities.test |  188 +-
     test/data/tokeniser2/regression.test      |    4 +-
     test/data/tokeniser2/test1.test           |   28 +-
     test/data/tokeniser2/test2.test           |   24 +-
     test/data/tokeniser2/test3.test           | 3060 +++++++++++++++--------------
     test/data/tokeniser2/test4.test           |   79 +-
     test/data/tokeniser2/unicodeChars.test    |    8 -
     test/testutils.h                          |   19 +
     test/tokeniser2.c                         |    5 +-
     10 files changed, 2096 insertions(+), 1917 deletions(-)
    
    diff --git a/src/tokeniser/tokeniser.c b/src/tokeniser/tokeniser.c
    index a7e67a1..3eab8a7 100644
    --- a/src/tokeniser/tokeniser.c
    +++ b/src/tokeniser/tokeniser.c
    @@ -24,10 +24,10 @@
      * Table of mappings between Windows-1252 codepoints 128-159 and UCS4
      */
     static const uint32_t cp1252Table[32] = {
    -	0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
    -	0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFD, 0x017D, 0xFFFD,
    -	0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
    -	0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFD, 0x017E, 0x0178
    +	0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
    +	0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008F, 0x017D, 0x0090,
    +	0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
    +	0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178
     };
     
     /**
    @@ -71,6 +71,7 @@ typedef enum hubbub_tokeniser_state {
     	STATE_COMMENT,
     	STATE_COMMENT_END_DASH,
     	STATE_COMMENT_END,
    +	STATE_COMMENT_END_BANG,
     	STATE_MATCH_DOCTYPE,
     	STATE_DOCTYPE,
     	STATE_BEFORE_DOCTYPE_NAME,
    @@ -78,6 +79,7 @@ typedef enum hubbub_tokeniser_state {
     	STATE_AFTER_DOCTYPE_NAME,
     	STATE_MATCH_PUBLIC,
     	STATE_BEFORE_DOCTYPE_PUBLIC,
    +	STATE_BEFORE_DOCTYPE_PUBLIC_IDENTIFIER,
     	STATE_DOCTYPE_PUBLIC_DQ,
     	STATE_DOCTYPE_PUBLIC_SQ,
     	STATE_AFTER_DOCTYPE_PUBLIC,
    @@ -232,6 +234,8 @@ static hubbub_error hubbub_tokeniser_handle_after_doctype_name(
     		hubbub_tokeniser *tokeniser);
     static hubbub_error hubbub_tokeniser_handle_match_public(
     		hubbub_tokeniser *tokeniser);
    +static hubbub_error hubbub_tokeniser_handle_doctype_public_identifier(
    +		hubbub_tokeniser *tokeniser);
     static hubbub_error hubbub_tokeniser_handle_before_doctype_public(
     		hubbub_tokeniser *tokeniser);
     static hubbub_error hubbub_tokeniser_handle_doctype_public_dq(
    @@ -443,7 +447,7 @@ hubbub_error hubbub_tokeniser_run(hubbub_tokeniser *tokeniser)
     	if (tokeniser->paused == true)
     		return HUBBUB_PAUSED;
     
    -#if 0
    +#if 1
     #define state(x) \
     		case x: \
     			printf( #x "\n");
    @@ -528,6 +532,7 @@ hubbub_error hubbub_tokeniser_run(hubbub_tokeniser *tokeniser)
     		case STATE_COMMENT:
     		case STATE_COMMENT_END_DASH:
     		case STATE_COMMENT_END:
    +		case STATE_COMMENT_END_BANG:
     			cont = hubbub_tokeniser_handle_comment(tokeniser);
     			break;
     		state(STATE_MATCH_DOCTYPE)
    @@ -549,7 +554,6 @@ hubbub_error hubbub_tokeniser_run(hubbub_tokeniser *tokeniser)
     			cont = hubbub_tokeniser_handle_after_doctype_name(
     					tokeniser);
     			break;
    -
     		state(STATE_MATCH_PUBLIC)
     			cont = hubbub_tokeniser_handle_match_public(
     					tokeniser);
    @@ -558,6 +562,10 @@ hubbub_error hubbub_tokeniser_run(hubbub_tokeniser *tokeniser)
     			cont = hubbub_tokeniser_handle_before_doctype_public(
     					tokeniser);
     			break;
    +		state(STATE_BEFORE_DOCTYPE_PUBLIC_IDENTIFIER)
    +			cont = hubbub_tokeniser_handle_doctype_public_identifier(
    +					tokeniser);
    +			break;
     		state(STATE_DOCTYPE_PUBLIC_DQ)
     			cont = hubbub_tokeniser_handle_doctype_public_dq(
     					tokeniser);
    @@ -655,7 +663,6 @@ hubbub_error hubbub_tokeniser_run(hubbub_tokeniser *tokeniser)
     		(str).len += (length); \
     	} while (0)
     
    -
     /* this should always be called with an empty "chars" buffer */
     hubbub_error hubbub_tokeniser_handle_data(hubbub_tokeniser *tokeniser)
     {
    @@ -669,44 +676,12 @@ hubbub_error hubbub_tokeniser_handle_data(hubbub_tokeniser *tokeniser)
     					PARSERUTILS_OK) {
     		const uint8_t c = *cptr;
     
    -		if (c == '&' &&
    -				(tokeniser->content_model == HUBBUB_CONTENT_MODEL_PCDATA ||
    -				tokeniser->content_model == HUBBUB_CONTENT_MODEL_RCDATA) &&
    -				tokeniser->escape_flag == false) {
    -			tokeniser->state =
    -					STATE_CHARACTER_REFERENCE_DATA;
    +		if (c == '&') {
    +			tokeniser->state = STATE_CHARACTER_REFERENCE_DATA;
     			/* Don't eat the '&'; it'll be handled by entity
     			 * consumption */
     			break;
    -		} else if (c == '-' &&
    -				tokeniser->escape_flag == false &&
    -				(tokeniser->content_model ==
    -						HUBBUB_CONTENT_MODEL_RCDATA ||
    -				tokeniser->content_model ==
    -						HUBBUB_CONTENT_MODEL_CDATA) &&
    -				tokeniser->context.pending >= 3) {
    -			size_t ignore;
    -			error = parserutils_inputstream_peek(
    -					tokeniser->input,
    -					tokeniser->context.pending - 3,
    -					&cptr,
    -					&ignore);
    -
    -			assert(error == PARSERUTILS_OK);
    -
    -			if (strncmp((char *)cptr,
    -					"<!--", SLEN("<!--")) == 0) {
    -				tokeniser->escape_flag = true;
    -			}
    -
    -			tokeniser->context.pending += len;
    -		} else if (c == '<' && (tokeniser->content_model ==
    -						HUBBUB_CONTENT_MODEL_PCDATA ||
    -					((tokeniser->content_model ==
    -						HUBBUB_CONTENT_MODEL_RCDATA ||
    -					tokeniser->content_model ==
    -						HUBBUB_CONTENT_MODEL_CDATA) &&
    -				tokeniser->escape_flag == false))) {
    +		} else if (c == '<') {
     			if (tokeniser->context.pending > 0) {
     				/* Emit any pending characters */
     				emit_current_chars(tokeniser);
    @@ -716,39 +691,6 @@ hubbub_error hubbub_tokeniser_handle_data(hubbub_tokeniser *tokeniser)
     			tokeniser->context.pending = len;
     			tokeniser->state = STATE_TAG_OPEN;
     			break;
    -		} else if (c == '>' && tokeniser->escape_flag == true &&
    -				(tokeniser->content_model ==
    -						HUBBUB_CONTENT_MODEL_RCDATA ||
    -				tokeniser->content_model ==
    -						HUBBUB_CONTENT_MODEL_CDATA)) {
    -			/* no need to check that there are enough characters,
    -			 * since you can only run into this if the flag is
    -			 * true in the first place, which requires four
    -			 * characters. */
    -			error = parserutils_inputstream_peek(
    -					tokeniser->input,
    -					tokeniser->context.pending - 2,
    -					&cptr,
    -					&len);
    -
    -			assert(error == PARSERUTILS_OK);
    -
    -			if (strncmp((char *) cptr, "-->", SLEN("-->")) == 0) {
    -				tokeniser->escape_flag = false;
    -			}
    -
    -			tokeniser->context.pending += len;
    -		} else if (c == '\0') {
    -			if (tokeniser->context.pending > 0) {
    -				/* Emit any pending characters */
    -				emit_current_chars(tokeniser);
    -			}
    -
    -			/* Emit a replacement character */
    -			emit_character_token(tokeniser, &u_fffd_str);
    -
    -			/* Advance past NUL */
    -			parserutils_inputstream_advance(tokeniser->input, 1);
     		} else if (c == '\r') {
     			error = parserutils_inputstream_peek(
     					tokeniser->input,
    @@ -774,11 +716,14 @@ hubbub_error hubbub_tokeniser_handle_data(hubbub_tokeniser *tokeniser)
     			/* Advance over */
     			parserutils_inputstream_advance(tokeniser->input, 1);
     		} else {
    +			if (c == '\0') {
    +				/** \todo parse error */
    +			}
    +
     			/* Just collect into buffer */
     			tokeniser->context.pending += len;
     		}
     	}
    -
     	if (tokeniser->state != STATE_TAG_OPEN &&
     		(tokeniser->state != STATE_DATA || error == PARSERUTILS_EOF) &&
     			tokeniser->context.pending > 0) {
    @@ -879,7 +824,9 @@ hubbub_error hubbub_tokeniser_handle_tag_open(hubbub_tokeniser *tokeniser)
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    -			/* Return to data state with '<' still in "chars" */
    +			/** \todo parse error */
    +			/* Emit single '<' char  */
    +			emit_current_chars(tokeniser);
     			tokeniser->state = STATE_DATA;
     			return HUBBUB_OK;
     		} else {
    @@ -889,65 +836,54 @@ hubbub_error hubbub_tokeniser_handle_tag_open(hubbub_tokeniser *tokeniser)
     
     	c = *cptr;
     
    -	if (c == '/') {
    +	if (c == '!') {
    +		parserutils_inputstream_advance(tokeniser->input, SLEN("<!"));
    +
    +		tokeniser->context.pending = 0;
    +		tokeniser->state = STATE_MARKUP_DECLARATION_OPEN;
    +	} else if (c == '/'){
     		tokeniser->context.pending += len;
     
     		tokeniser->context.close_tag_match.match = false;
     		tokeniser->context.close_tag_match.count = 0;
     
     		tokeniser->state = STATE_CLOSE_TAG_OPEN;
    -	} else if (tokeniser->content_model == HUBBUB_CONTENT_MODEL_RCDATA ||
    -			tokeniser->content_model ==
    -					HUBBUB_CONTENT_MODEL_CDATA) {
    -		/* Return to data state with '<' still in "chars" */
    -		tokeniser->state = STATE_DATA;
    -	} else if (tokeniser->content_model == HUBBUB_CONTENT_MODEL_PCDATA) {
    -		if (c == '!') {
    -			parserutils_inputstream_advance(tokeniser->input,
    -					SLEN("<!"));
    -
    -			tokeniser->context.pending = 0;
    -			tokeniser->state = STATE_MARKUP_DECLARATION_OPEN;
    -		} else if ('A' <= c && c <= 'Z') {
    -			uint8_t lc = (c + 0x20);
    -
    -			START_BUF(ctag->name, &lc, len);
    -			ctag->n_attributes = 0;
    -			tokeniser->context.current_tag_type =
    -					HUBBUB_TOKEN_START_TAG;
    -
    -			tokeniser->context.pending += len;
    +	} else if ('A' <= c && c <= 'Z') {
    +		uint8_t lc = (c + 0x20);
     
    -			tokeniser->state = STATE_TAG_NAME;
    -		} else if ('a' <= c && c <= 'z') {
    -			START_BUF(ctag->name, cptr, len);
    -			ctag->n_attributes = 0;
    -			tokeniser->context.current_tag_type =
    -					HUBBUB_TOKEN_START_TAG;
    +		START_BUF(ctag->name, &lc, len);
    +		ctag->n_attributes = 0;
    +		tokeniser->context.current_tag_type =
    +				HUBBUB_TOKEN_START_TAG;
     
    -			tokeniser->context.pending += len;
    +		tokeniser->context.pending += len;
     
    -			tokeniser->state = STATE_TAG_NAME;
    -		} else if (c == '>') {
    -			/** \todo parse error */
    +		tokeniser->state = STATE_TAG_NAME;
    +	} else if ('a' <= c && c <= 'z') {
    +		START_BUF(ctag->name, cptr, len);
    +		ctag->n_attributes = 0;
    +		tokeniser->context.current_tag_type =
    +				HUBBUB_TOKEN_START_TAG;
     
    -			tokeniser->context.pending += len;
    -			tokeniser->state = STATE_DATA;
    -		} else if (c == '?') {
    -			/** \todo parse error */
    +		tokeniser->context.pending += len;
     
    -			/* Cursor still at "<", need to advance past it */
    +		tokeniser->state = STATE_TAG_NAME;
    +	} else if (c == '?'){
    +		/** \todo parse error */
    +		/* Cursor still at "<", need to advance past it */
     			parserutils_inputstream_advance(
     					tokeniser->input, SLEN("<"));
     			tokeniser->context.pending = 0;
     
     			tokeniser->state = STATE_BOGUS_COMMENT;
    -		} else {
    -			/* Return to data state with '<' still in "chars" */
    -			tokeniser->state = STATE_DATA;
    -		}
    +	} else {
    +		/** \todo parse error */
    +		/* Emit single '<' char  */
    +		emit_current_chars(tokeniser);
    +		tokeniser->state = STATE_DATA;
     	}
     
    +
     	return HUBBUB_OK;
     }
     
    @@ -955,8 +891,6 @@ hubbub_error hubbub_tokeniser_handle_tag_open(hubbub_tokeniser *tokeniser)
     /* this state never stays in this state for more than one character */
     hubbub_error hubbub_tokeniser_handle_close_tag_open(hubbub_tokeniser *tokeniser)
     {
    -	hubbub_tokeniser_context *ctx = &tokeniser->context;
    -
     	size_t len;
     	const uint8_t *cptr;
     	parserutils_error error;
    @@ -966,131 +900,65 @@ hubbub_error hubbub_tokeniser_handle_close_tag_open(hubbub_tokeniser *tokeniser)
     /*	assert(tokeniser->context.chars.ptr[0] == '<'); */
     /*	assert(tokeniser->context.chars.ptr[1] == '/'); */
     
    -	/**\todo fragment case */
    -
    -	if (tokeniser->content_model == HUBBUB_CONTENT_MODEL_RCDATA ||
    -			tokeniser->content_model ==
    -					HUBBUB_CONTENT_MODEL_CDATA) {
    -		uint8_t *start_tag_name =
    -			tokeniser->context.last_start_tag_name;
    -		size_t start_tag_len =
    -			tokeniser->context.last_start_tag_len;
    -
    -		while ((error = parserutils_inputstream_peek(tokeniser->input,
    -					ctx->pending +
    -						ctx->close_tag_match.count,
    -					&cptr,
    -					&len)) == PARSERUTILS_OK) {
    -			c = *cptr;
    -
    -			if ((start_tag_name[ctx->close_tag_match.count] & ~0x20)
    -					!= (c & ~0x20)) {
    -				break;
    -			}
    -
    -			ctx->close_tag_match.count += len;
    -
    -			if (ctx->close_tag_match.count == start_tag_len) {
    -				ctx->close_tag_match.match = true;
    -				break;
    -			}
    -		}
    -
    -		if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) {
    -			return hubbub_error_from_parserutils_error(error);
    -		}
    -
    -		if (ctx->close_tag_match.match == true) {
    -			error = parserutils_inputstream_peek(
    -			 		tokeniser->input,
    -			 		ctx->pending +
    -				 		ctx->close_tag_match.count,
    -					&cptr,
    -			 		&len);
    -
    -			if (error != PARSERUTILS_OK && 
    -					error != PARSERUTILS_EOF) {
    -				return hubbub_error_from_parserutils_error(
    -						error);
    -			} else if (error != PARSERUTILS_EOF) {
    -				c = *cptr;
    -
    -				if (c != '\t' && c != '\n' && c != '\f' &&
    -						c != ' ' && c != '>' &&
    -						c != '/') {
    -					ctx->close_tag_match.match = false;
    -				}
    -			}
    -		}
    -	}
    -
    -	if (ctx->close_tag_match.match == false &&
    -			tokeniser->content_model !=
    -					HUBBUB_CONTENT_MODEL_PCDATA) {
    -		/* We should emit "</" here, but instead we leave it in the
    -		 * buffer so the data state emits it with any characters
    -		 * following it */
    -		tokeniser->state = STATE_DATA;
    -	} else {
    -		error = parserutils_inputstream_peek(tokeniser->input,
    -				tokeniser->context.pending, &cptr, &len);
    +	error = parserutils_inputstream_peek(tokeniser->input, 
    +			tokeniser->context.pending, &cptr, &len);
     
    +	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
     			/** \todo parse error */
    -
    -			/* Return to data state with "</" pending */
    +			/* Emit '</' chars  */
    +			emit_current_chars(tokeniser);
     			tokeniser->state = STATE_DATA;
     			return HUBBUB_OK;
    -		} else if (error != PARSERUTILS_OK) {
    +		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
    +	}
     
    -		c = *cptr;
    +	c = *cptr;
     
    -		if ('A' <= c && c <= 'Z') {
    -			uint8_t lc = (c + 0x20);
    -			START_BUF(tokeniser->context.current_tag.name,
    -					&lc, len);
    -			tokeniser->context.current_tag.n_attributes = 0;
    +	if ('A' <= c && c <= 'Z') {
    +		uint8_t lc = (c + 0x20);
    +		START_BUF(tokeniser->context.current_tag.name,
    +				&lc, len);
    +		tokeniser->context.current_tag.n_attributes = 0;
     
    -			tokeniser->context.current_tag_type =
    -					HUBBUB_TOKEN_END_TAG;
    +		tokeniser->context.current_tag_type = HUBBUB_TOKEN_END_TAG;
     
    -			tokeniser->context.pending += len;
    +		tokeniser->context.pending += len;
     
    -			tokeniser->state = STATE_TAG_NAME;
    -		} else if ('a' <= c && c <= 'z') {
    -			START_BUF(tokeniser->context.current_tag.name,
    -					cptr, len);
    -			tokeniser->context.current_tag.n_attributes = 0;
    +		tokeniser->state = STATE_TAG_NAME;
    +	} else if ('a' <= c && c <= 'z') {
    +		START_BUF(tokeniser->context.current_tag.name,
    +				cptr, len);
    +		tokeniser->context.current_tag.n_attributes = 0;
     
    -			tokeniser->context.current_tag_type =
    -					HUBBUB_TOKEN_END_TAG;
    +		tokeniser->context.current_tag_type = HUBBUB_TOKEN_END_TAG;
     
    -			tokeniser->context.pending += len;
    +		tokeniser->context.pending += len;
     
    -			tokeniser->state = STATE_TAG_NAME;
    -		} else if (c == '>') {
    -			/* Cursor still at "</", need to collect ">" */
    -			tokeniser->context.pending += len;
    +		tokeniser->state = STATE_TAG_NAME;
    +	} else if (c == '>') {
    +		/** \todo parse error */
     
    -			/* Now need to advance past "</>" */
    -			parserutils_inputstream_advance(tokeniser->input,
    -					tokeniser->context.pending);
    -			tokeniser->context.pending = 0;
    +		/* Cursor still at "</", need to collect ">" */
    +		tokeniser->context.pending += len;
     
    -			/** \todo parse error */
    -			tokeniser->state = STATE_DATA;
    -		} else {
    -			/** \todo parse error */
    +		/* Now need to advance past "</>" */
    +		parserutils_inputstream_advance(tokeniser->input,
    +				tokeniser->context.pending);
    +		tokeniser->context.pending = 0;
     
    -			/* Cursor still at "</", need to advance past it */
    -			parserutils_inputstream_advance(tokeniser->input,
    -					tokeniser->context.pending);
    -			tokeniser->context.pending = 0;
    +		tokeniser->state = STATE_DATA;
    +	} else {
    +		/** \todo parse error */
     
    -			tokeniser->state = STATE_BOGUS_COMMENT;
    -		}
    +		/* Cursor still at "</", need to advance past it */
    +		parserutils_inputstream_advance(tokeniser->input,
    +				tokeniser->context.pending);
    +		tokeniser->context.pending = 0;
    +
    +		tokeniser->state = STATE_BOGUS_COMMENT;
     	}
     
     	return HUBBUB_OK;
    @@ -1117,8 +985,13 @@ hubbub_error hubbub_tokeniser_handle_tag_name(hubbub_tokeniser *tokeniser)
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
    -			return emit_current_tag(tokeniser);
    +
    +			// skips all pending charachters
    +			parserutils_inputstream_advance(
    +					tokeniser->input, tokeniser->context.pending);
    +			return HUBBUB_OK;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
    @@ -1129,20 +1002,20 @@ hubbub_error hubbub_tokeniser_handle_tag_name(hubbub_tokeniser *tokeniser)
     	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') {
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_BEFORE_ATTRIBUTE_NAME;
    +	} else if (c == '/') {
    +		tokeniser->context.pending += len;
    +		tokeniser->state = STATE_SELF_CLOSING_START_TAG;
     	} else if (c == '>') {
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_DATA;
     		return emit_current_tag(tokeniser);
    -	} else if (c == '\0') {
    -		COLLECT(ctag->name, u_fffd, sizeof(u_fffd));
    -		tokeniser->context.pending += len;
    -	} else if (c == '/') {
    -		tokeniser->context.pending += len;
    -		tokeniser->state = STATE_SELF_CLOSING_START_TAG;
     	} else if ('A' <= c && c <= 'Z') {
     		uint8_t lc = (c + 0x20);
     		COLLECT(ctag->name, &lc, len);
     		tokeniser->context.pending += len;
    +	} else if (c == '\0') {
    +		COLLECT(ctag->name, u_fffd, sizeof(u_fffd));
    +		tokeniser->context.pending += len;
     	} else {
     		COLLECT(ctag->name, cptr, len);
     		tokeniser->context.pending += len;
    @@ -1166,8 +1039,13 @@ hubbub_error hubbub_tokeniser_handle_before_attribute_name(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
    -			return emit_current_tag(tokeniser);
    +
    +			// skips all pending charachters
    +			parserutils_inputstream_advance(
    +					tokeniser->input, tokeniser->context.pending);
    +			return HUBBUB_OK;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
    @@ -1178,13 +1056,13 @@ hubbub_error hubbub_tokeniser_handle_before_attribute_name(
     	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') {
     		/* pass over in silence */
     		tokeniser->context.pending += len;
    +	} else if (c == '/') {
    +		tokeniser->context.pending += len;
    +		tokeniser->state = STATE_SELF_CLOSING_START_TAG;
     	} else if (c == '>') {
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_DATA;
     		return emit_current_tag(tokeniser);
    -	} else if (c == '/') {
    -		tokeniser->context.pending += len;
    -		tokeniser->state = STATE_SELF_CLOSING_START_TAG;
     	} else {
     		hubbub_attribute *attr;
     
    @@ -1239,8 +1117,13 @@ hubbub_error hubbub_tokeniser_handle_attribute_name(hubbub_tokeniser *tokeniser)
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
    -			return emit_current_tag(tokeniser);
    +
    +			// skips all pending charachters
    +			parserutils_inputstream_advance(
    +					tokeniser->input, tokeniser->context.pending);
    +			return HUBBUB_OK;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
    @@ -1271,6 +1154,10 @@ hubbub_error hubbub_tokeniser_handle_attribute_name(hubbub_tokeniser *tokeniser)
     				&lc, len);
     		tokeniser->context.pending += len;
     	} else {
    +		if (c == '"' || c == '\'' || c == '<') {
    +			/** \todo parse error */
    +		}
    +
     		COLLECT(ctag->attributes[ctag->n_attributes - 1].name,
     				cptr, len);
     		tokeniser->context.pending += len;
    @@ -1294,13 +1181,21 @@ hubbub_error hubbub_tokeniser_handle_after_attribute_name(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
    -			return emit_current_tag(tokeniser);
    +
    +			// skips all pending charachters
    +			parserutils_inputstream_advance(
    +					tokeniser->input, tokeniser->context.pending);
    +			return HUBBUB_OK;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
     	}
     
    +	/** \todo Check for the existence of attribute name in the attributes list,
    +	 * if there then igonre this one and its value if any */
    +
     	c = *cptr;
     
     	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') {
    @@ -1319,7 +1214,7 @@ hubbub_error hubbub_tokeniser_handle_after_attribute_name(
     	} else {
     		hubbub_attribute *attr;
     
    -		if (c == '"' || c == '\'') {
    +		if (c == '"' || c == '\'' || c =='<') {
     			/** \todo parse error */
     		}
     
    @@ -1335,6 +1230,7 @@ hubbub_error hubbub_tokeniser_handle_after_attribute_name(
     			uint8_t lc = (c + 0x20);
     			START_BUF(attr[ctag->n_attributes].name, &lc, len);
     		} else if (c == '\0') {
    +			/** \todo parse error */
     			START_BUF(attr[ctag->n_attributes].name,
     					u_fffd, sizeof(u_fffd));
     		} else {
    @@ -1372,7 +1268,11 @@ hubbub_error hubbub_tokeniser_handle_before_attribute_value(
     		if (error == PARSERUTILS_EOF) {
     			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
    -			return emit_current_tag(tokeniser);
    +
    +			// skips all pending charachters
    +			parserutils_inputstream_advance(
    +					tokeniser->input, tokeniser->context.pending);
    +			return HUBBUB_OK;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
    @@ -1398,12 +1298,14 @@ hubbub_error hubbub_tokeniser_handle_before_attribute_value(
     		tokeniser->state = STATE_DATA;
     		return emit_current_tag(tokeniser);
     	} else if (c == '\0') {
    +		/** \todo parse error */
    +
     		START_BUF(ctag->attributes[ctag->n_attributes - 1].value,
     				u_fffd, sizeof(u_fffd));
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_ATTRIBUTE_VALUE_UQ;
     	} else {
    -		if (c == '=') {
    +		if (c == '=' || c == '=' || c == '`') {
     			/** \todo parse error */
     		}
     
    @@ -1432,8 +1334,13 @@ hubbub_error hubbub_tokeniser_handle_attribute_value_dq(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
    -			return emit_current_tag(tokeniser);
    +
    +			// skips all pending charachters
    +			parserutils_inputstream_advance(
    +					tokeniser->input, tokeniser->context.pending);
    +			return HUBBUB_OK;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
    @@ -1450,6 +1357,7 @@ hubbub_error hubbub_tokeniser_handle_attribute_value_dq(
     		tokeniser->context.allowed_char = '"';
     		/* Don't eat the '&'; it'll be handled by entity consumption */
     	} else if (c == '\0') {
    +		/** \todo parse error */
     		COLLECT_MS(ctag->attributes[ctag->n_attributes - 1].value,
     				u_fffd, sizeof(u_fffd));
     		tokeniser->context.pending += len;
    @@ -1494,8 +1402,13 @@ hubbub_error hubbub_tokeniser_handle_attribute_value_sq(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
    -			return emit_current_tag(tokeniser);
    +
    +			// skips all pending charachters
    +			parserutils_inputstream_advance(
    +					tokeniser->input, tokeniser->context.pending);
    +			return HUBBUB_OK;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
    @@ -1556,8 +1469,13 @@ hubbub_error hubbub_tokeniser_handle_attribute_value_uq(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
    -			return emit_current_tag(tokeniser);
    +
    +			// skips all pending charachters
    +			parserutils_inputstream_advance(
    +					tokeniser->input, tokeniser->context.pending);
    +			return HUBBUB_OK;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
    @@ -1574,6 +1492,7 @@ hubbub_error hubbub_tokeniser_handle_attribute_value_uq(
     	} else if (c == '&') {
     		tokeniser->context.prev_state = tokeniser->state;
     		tokeniser->state = STATE_CHARACTER_REFERENCE_IN_ATTRIBUTE_VALUE;
    +		tokeniser->context.allowed_char = '>';
     		/* Don't eat the '&'; it'll be handled by entity consumption */
     	} else if (c == '>') {
     		tokeniser->context.pending += len;
    @@ -1584,7 +1503,7 @@ hubbub_error hubbub_tokeniser_handle_attribute_value_uq(
     				u_fffd, sizeof(u_fffd));
     		tokeniser->context.pending += len;
     	} else {
    -		if (c == '"' || c == '\'' || c == '=') {
    +		if (c == '"' || c == '\'' || c == '=' || c == '<' || c == '`') {
     			/** \todo parse error */
     		}
     
    @@ -1666,8 +1585,13 @@ hubbub_error hubbub_tokeniser_handle_after_attribute_value_q(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
    -			return emit_current_tag(tokeniser);
    +
    +			// skips all pending charachters
    +			parserutils_inputstream_advance(
    +					tokeniser->input, tokeniser->context.pending);
    +			return HUBBUB_OK;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
    @@ -1675,7 +1599,7 @@ hubbub_error hubbub_tokeniser_handle_after_attribute_value_q(
     
     	c = *cptr;
     
    -	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') {
    +	if (c == '\t' || c == '\n' || c == '\f' || c == ' ') {
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_BEFORE_ATTRIBUTE_NAME;
     	} else if (c == '>') {
    @@ -1708,8 +1632,13 @@ hubbub_error hubbub_tokeniser_handle_self_closing_start_tag(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
    -			return emit_current_tag(tokeniser);
    +
    +			// skips all pending charachters
    +			parserutils_inputstream_advance(
    +					tokeniser->input, tokeniser->context.pending);
    +			return HUBBUB_OK;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
    @@ -1724,6 +1653,7 @@ hubbub_error hubbub_tokeniser_handle_self_closing_start_tag(
     		tokeniser->context.current_tag.self_closing = true;
     		return emit_current_tag(tokeniser);
     	} else {
    +		/** \todo parse error */
     		/* Reprocess character in before attribute name state */
     		tokeniser->state = STATE_BEFORE_ATTRIBUTE_NAME;
     	}
    @@ -1809,6 +1739,7 @@ hubbub_error hubbub_tokeniser_handle_markup_declaration_open(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_BOGUS_COMMENT;
     			return HUBBUB_OK;
     		} else {
    @@ -1826,6 +1757,7 @@ hubbub_error hubbub_tokeniser_handle_markup_declaration_open(
     		tokeniser->context.match_doctype.count = len;
     		tokeniser->state = STATE_MATCH_DOCTYPE;
     	} else if (tokeniser->process_cdata_section == true && c == '[') {
    +		// ALSO CHECKS FOR adjusted current node AND element not in html namespace
     		tokeniser->context.pending = len;
     		tokeniser->context.match_cdata.count = len;
     		tokeniser->state = STATE_MATCH_CDATA;
    @@ -1836,7 +1768,7 @@ hubbub_error hubbub_tokeniser_handle_markup_declaration_open(
     	return HUBBUB_OK;
     }
     
    -
    +/* to match -- and start an empty comment */
     hubbub_error hubbub_tokeniser_handle_match_comment(hubbub_tokeniser *tokeniser)
     {
     	size_t len;
    @@ -1882,8 +1814,9 @@ hubbub_error hubbub_tokeniser_handle_comment(hubbub_tokeniser *tokeniser)
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
    -			return emit_current_comment(tokeniser);
    +			return emit_current_comment(tokeniser);;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
    @@ -1893,12 +1826,16 @@ hubbub_error hubbub_tokeniser_handle_comment(hubbub_tokeniser *tokeniser)
     
     	if (c == '>' && (tokeniser->state == STATE_COMMENT_START_DASH ||
     			tokeniser->state == STATE_COMMENT_START ||
    -			tokeniser->state == STATE_COMMENT_END)) {
    +			tokeniser->state == STATE_COMMENT_END ||
    +			tokeniser->state == STATE_COMMENT_END_BANG)) {
     		tokeniser->context.pending += len;
     
     		/** \todo parse error if state != COMMENT_END */
     		tokeniser->state = STATE_DATA;
     		return emit_current_comment(tokeniser);
    +	} else if (c == '!' && tokeniser->state == STATE_COMMENT_END) {
    +		tokeniser->context.pending += len;
    +		tokeniser->state = STATE_COMMENT_END_BANG;
     	} else if (c == '-') {
     		if (tokeniser->state == STATE_COMMENT_START) {
     			tokeniser->state = STATE_COMMENT_START_DASH;
    @@ -1909,12 +1846,23 @@ hubbub_error hubbub_tokeniser_handle_comment(hubbub_tokeniser *tokeniser)
     		} else if (tokeniser->state == STATE_COMMENT_END_DASH) {
     			tokeniser->state = STATE_COMMENT_END;
     		} else if (tokeniser->state == STATE_COMMENT_END) {
    +			/** \todo parse error */
     			error = parserutils_buffer_append(tokeniser->buffer,
     					(uint8_t *) "-", SLEN("-"));
     			if (error != PARSERUTILS_OK) {
     				return hubbub_error_from_parserutils_error(
     						error);
     			}
    +		} else if (tokeniser->state == STATE_COMMENT_END_BANG) {
    +			/** \todo parse error */
    +			error = parserutils_buffer_append(tokeniser->buffer,
    +					(uint8_t *) "--!", SLEN("--!"));
    +			if (error != PARSERUTILS_OK) {
    +				return hubbub_error_from_parserutils_error(
    +						error);
    +			}
    +
    +			tokeniser->state = STATE_COMMENT_END_DASH;
     		}
     
     		tokeniser->context.pending += len;
    @@ -1934,9 +1882,17 @@ hubbub_error hubbub_tokeniser_handle_comment(hubbub_tokeniser *tokeniser)
     				return hubbub_error_from_parserutils_error(
     						error);
     			}
    +		} else if (tokeniser->state == STATE_COMMENT_END_BANG) {
    +			error = parserutils_buffer_append(tokeniser->buffer,
    +					(uint8_t *) "--!", SLEN("--!"));
    +			if (error != PARSERUTILS_OK) {
    +				return hubbub_error_from_parserutils_error(
    +						error);
    +			}
     		}
     
     		if (c == '\0') {
    +			/** \todo parse error */
     			error = parserutils_buffer_append(tokeniser->buffer,
     					u_fffd, sizeof(u_fffd));
     			if (error != PARSERUTILS_OK) {
    @@ -1984,7 +1940,7 @@ hubbub_error hubbub_tokeniser_handle_comment(hubbub_tokeniser *tokeniser)
     
     #define DOCTYPE		"DOCTYPE"
     #define DOCTYPE_LEN	(SLEN(DOCTYPE) - 1)
    -
    +/* checks for DOCTYPE in*/
     hubbub_error hubbub_tokeniser_handle_match_doctype(hubbub_tokeniser *tokeniser)
     {
     	size_t len;
    @@ -2053,8 +2009,10 @@ hubbub_error hubbub_tokeniser_handle_doctype(hubbub_tokeniser *tokeniser)
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    -			tokeniser->state = STATE_BEFORE_DOCTYPE_NAME;
    -			return HUBBUB_OK;
    +			/** \todo parse error */
    +			/* Emit current doctype, force-quirks on */
    +			tokeniser->state = STATE_DATA;
    +			return emit_current_doctype(tokeniser, true);
     		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
    @@ -2062,8 +2020,10 @@ hubbub_error hubbub_tokeniser_handle_doctype(hubbub_tokeniser *tokeniser)
     
     	c = *cptr;
     
    -	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') {
    +	if (c == '\t' || c == '\n' || c == '\f' || c == ' ') {
     		tokeniser->context.pending += len;
    +	} else {
    +		/** \todo parse error */
     	}
     
     	tokeniser->state = STATE_BEFORE_DOCTYPE_NAME;
    @@ -2106,6 +2066,7 @@ hubbub_error hubbub_tokeniser_handle_before_doctype_name(
     		return emit_current_doctype(tokeniser, true);
     	} else {
     		if (c == '\0') {
    +			/** \todo parse error */
     			START_BUF(cdoc->name, u_fffd, sizeof(u_fffd));
     		} else if ('A' <= c && c <= 'Z') {
     			uint8_t lc = c + 0x20;
    @@ -2135,6 +2096,7 @@ hubbub_error hubbub_tokeniser_handle_doctype_name(hubbub_tokeniser *tokeniser)
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
     			return emit_current_doctype(tokeniser, true);
     		} else {
    @@ -2144,7 +2106,7 @@ hubbub_error hubbub_tokeniser_handle_doctype_name(hubbub_tokeniser *tokeniser)
     
     	c = *cptr;
     
    -	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') {
    +	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c =='\r') {
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_AFTER_DOCTYPE_NAME;
     	} else if (c == '>') {
    @@ -2152,6 +2114,7 @@ hubbub_error hubbub_tokeniser_handle_doctype_name(hubbub_tokeniser *tokeniser)
     		tokeniser->state = STATE_DATA;
     		return emit_current_doctype(tokeniser, false);
     	} else if (c == '\0') {
    +		/** \todo parse error */
     		COLLECT(cdoc->name, u_fffd, sizeof(u_fffd));
     		tokeniser->context.pending += len;
     	} else if ('A' <= c && c <= 'Z') {
    @@ -2179,6 +2142,7 @@ hubbub_error hubbub_tokeniser_handle_after_doctype_name(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
     			return emit_current_doctype(tokeniser, true);
     		} else {
    @@ -2189,7 +2153,7 @@ hubbub_error hubbub_tokeniser_handle_after_doctype_name(
     	c = *cptr;
     	tokeniser->context.pending += len;
     
    -	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') {
    +	if (c == '\t' || c == '\n' || c == '\f' || c == ' ') {
     		/* pass over in silence */
     	} else if (c == '>') {
     		tokeniser->state = STATE_DATA;
    @@ -2201,6 +2165,7 @@ hubbub_error hubbub_tokeniser_handle_after_doctype_name(
     		tokeniser->context.match_doctype.count = 1;
     		tokeniser->state = STATE_MATCH_SYSTEM;
     	} else {
    +		/** \todo parse error */
     		tokeniser->state = STATE_BOGUS_DOCTYPE;
     		tokeniser->context.current_doctype.force_quirks = true;
     	}
    @@ -2255,6 +2220,7 @@ hubbub_error hubbub_tokeniser_handle_match_public(hubbub_tokeniser *tokeniser)
     #undef PUBLIC
     #undef PUBLIC_LEN
     
    +// same as after public keyword state
     hubbub_error hubbub_tokeniser_handle_before_doctype_public(
     		hubbub_tokeniser *tokeniser)
     {
    @@ -2269,6 +2235,7 @@ hubbub_error hubbub_tokeniser_handle_before_doctype_public(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
     			return emit_current_doctype(tokeniser, true);
     		} else {
    @@ -2279,20 +2246,74 @@ hubbub_error hubbub_tokeniser_handle_before_doctype_public(
     	c = *cptr;
     	tokeniser->context.pending += len;
     
    -	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') {
    -		/* pass over in silence */
    +	if (c == '\t' || c == '\n' || c == '\f' || c == ' ') {
    +		tokeniser->state = STATE_BEFORE_DOCTYPE_PUBLIC_IDENTIFIER;
    +	} else if (c == '"') {
    +		/** \todo parse error */
    +		cdoc->public_missing = false;
    +		cdoc->public_id.len = 0;
    +		tokeniser->state = STATE_DOCTYPE_PUBLIC_DQ;
    +	} else if (c == '\'') {
    +		/** \todo parse error */
    +		cdoc->public_missing = false;
    +		cdoc->public_id.len = 0;
    +		tokeniser->state = STATE_DOCTYPE_PUBLIC_SQ;
    +	} else if (c == '>') {
    +		/** \todo parse error */
    +		tokeniser->state = STATE_DATA;
    +		return emit_current_doctype(tokeniser, true);
    +	} else {
    +		/** \todo parse error */
    +		cdoc->force_quirks = true;
    +		tokeniser->state = STATE_BOGUS_DOCTYPE;
    +	}
    +
    +	return HUBBUB_OK;
    +}
    +
    +hubbub_error hubbub_tokeniser_handle_doctype_public_identifier(
    +		hubbub_tokeniser *tokeniser)
    +{
    +	hubbub_doctype *cdoc = &tokeniser->context.current_doctype;
    +	size_t len;
    +	const uint8_t *cptr;
    +	parserutils_error error;
    +	uint8_t c;
    +
    +	error = parserutils_inputstream_peek(tokeniser->input,
    +			tokeniser->context.pending, &cptr, &len);
    +
    +	if (error != PARSERUTILS_OK) {
    +		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
    +			tokeniser->state = STATE_DATA;
    +			return emit_current_doctype(tokeniser, true);
    +		} else {
    +			return hubbub_error_from_parserutils_error(error);
    +		}
    +	}
    +
    +	c = *cptr;
    +	tokeniser->context.pending += len;
    +
    +	if (c == '\t' || c == '\n' || c == '\f' || c == ' ') {
    +		/** ignore the charachter */
     	} else if (c == '"') {
    +		/** \todo parse error */
     		cdoc->public_missing = false;
     		cdoc->public_id.len = 0;
     		tokeniser->state = STATE_DOCTYPE_PUBLIC_DQ;
     	} else if (c == '\'') {
    +		/** \todo parse error */
     		cdoc->public_missing = false;
     		cdoc->public_id.len = 0;
     		tokeniser->state = STATE_DOCTYPE_PUBLIC_SQ;
     	} else if (c == '>') {
    +		/** \todo parse error */
     		tokeniser->state = STATE_DATA;
     		return emit_current_doctype(tokeniser, true);
     	} else {
    +		/** \todo parse error */
     		cdoc->force_quirks = true;
     		tokeniser->state = STATE_BOGUS_DOCTYPE;
     	}
    @@ -2314,6 +2335,7 @@ hubbub_error hubbub_tokeniser_handle_doctype_public_dq(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
     			return emit_current_doctype(tokeniser, true);
     		} else {
    @@ -2327,10 +2349,12 @@ hubbub_error hubbub_tokeniser_handle_doctype_public_dq(
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_AFTER_DOCTYPE_PUBLIC;
     	} else if (c == '>') {
    +		/** \todo parse error */
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_DATA;
     		return emit_current_doctype(tokeniser, true);
     	} else if (c == '\0') {
    +		/** \todo parse error */
     		COLLECT_MS(cdoc->public_id, u_fffd, sizeof(u_fffd));
     		tokeniser->context.pending += len;
     	} else if (c == '\r') {
    @@ -2371,6 +2395,7 @@ hubbub_error hubbub_tokeniser_handle_doctype_public_sq(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
     			return emit_current_doctype(tokeniser, true);
     		} else {
    @@ -2384,10 +2409,12 @@ hubbub_error hubbub_tokeniser_handle_doctype_public_sq(
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_AFTER_DOCTYPE_PUBLIC;
     	} else if (c == '>') {
    +		/** \todo parse error */
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_DATA;
     		return emit_current_doctype(tokeniser, true);
     	} else if (c == '\0') {
    +		/** \todo parse error */
     		COLLECT_MS(cdoc->public_id, u_fffd, sizeof(u_fffd));
     		tokeniser->context.pending += len;
     	} else if (c == '\r') {
    @@ -2413,7 +2440,7 @@ hubbub_error hubbub_tokeniser_handle_doctype_public_sq(
     	return HUBBUB_OK;
     }
     
    -
    +// after doctype public state and between doctype public & sysyem date are overlapping
     hubbub_error hubbub_tokeniser_handle_after_doctype_public(
     		hubbub_tokeniser *tokeniser)
     {
    @@ -2428,6 +2455,7 @@ hubbub_error hubbub_tokeniser_handle_after_doctype_public(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
     			return emit_current_doctype(tokeniser, true);
     		} else {
    @@ -2438,7 +2466,7 @@ hubbub_error hubbub_tokeniser_handle_after_doctype_public(
     	c = *cptr;
     	tokeniser->context.pending += len;
     
    -	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') {
    +	if (c == '\t' || c == '\n' || c == '\f' || c == ' ') {
     		/* pass over in silence */
     	} else if (c == '"') {
     		cdoc->system_missing = false;
    @@ -2510,6 +2538,8 @@ hubbub_error hubbub_tokeniser_handle_match_system(hubbub_tokeniser *tokeniser)
     #undef SYSTEM
     #undef SYSTEM_LEN
     
    +// same as after doctype system keyword state
    +// overlapping with before DOCTYPE system identifier state
     hubbub_error hubbub_tokeniser_handle_before_doctype_system(
     		hubbub_tokeniser *tokeniser)
     {
    @@ -2524,6 +2554,7 @@ hubbub_error hubbub_tokeniser_handle_before_doctype_system(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
     			return emit_current_doctype(tokeniser, true);
     		} else {
    @@ -2534,22 +2565,26 @@ hubbub_error hubbub_tokeniser_handle_before_doctype_system(
     	c = *cptr;
     	tokeniser->context.pending += len;
     
    -	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') {
    +	if (c == '\t' || c == '\n' || c == '\f' || c == ' ') {
     		/* pass over */
     	} else if (c == '"') {
    +		/** \todo parse error if this is not the second call for this state */
     		cdoc->system_missing = false;
     		cdoc->system_id.len = 0;
     
     		tokeniser->state = STATE_DOCTYPE_SYSTEM_DQ;
     	} else if (c == '\'') {
    +		/** \todo parse error if this is not the second call for this state */
     		cdoc->system_missing = false;
     		cdoc->system_id.len = 0;
     
     		tokeniser->state = STATE_DOCTYPE_SYSTEM_SQ;
     	} else if (c == '>') {
    +		/** \todo parse error */
     		tokeniser->state = STATE_DATA;
     		return emit_current_doctype(tokeniser, true);
     	} else {
    +		/** \todo parse error */
     		cdoc->force_quirks = true;
     		tokeniser->state = STATE_BOGUS_DOCTYPE;
     	}
    @@ -2571,6 +2606,7 @@ hubbub_error hubbub_tokeniser_handle_doctype_system_dq(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
     			return emit_current_doctype(tokeniser, true);
     		} else {
    @@ -2584,10 +2620,12 @@ hubbub_error hubbub_tokeniser_handle_doctype_system_dq(
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_AFTER_DOCTYPE_SYSTEM;
     	} else if (c == '>') {
    +		/** \todo parse error */
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_DATA;
     		return emit_current_doctype(tokeniser, true);
     	} else if (c == '\0') {
    +		/** \todo parse error */
     		COLLECT_MS(cdoc->system_id, u_fffd, sizeof(u_fffd));
     		tokeniser->context.pending += len;
     	} else if (c == '\r') {
    @@ -2627,6 +2665,7 @@ hubbub_error hubbub_tokeniser_handle_doctype_system_sq(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
     			return emit_current_doctype(tokeniser, true);
     		} else {
    @@ -2640,10 +2679,12 @@ hubbub_error hubbub_tokeniser_handle_doctype_system_sq(
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_AFTER_DOCTYPE_SYSTEM;
     	} else if (c == '>') {
    +		/** \todo parse error */
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_DATA;
     		return emit_current_doctype(tokeniser, true);
     	} else if (c == '\0') {
    +		/** \todo parse error */
     		COLLECT_MS(cdoc->system_id, u_fffd, sizeof(u_fffd));
     		tokeniser->context.pending += len;
     	} else if (c == '\r') {
    @@ -2682,6 +2723,7 @@ hubbub_error hubbub_tokeniser_handle_after_doctype_system(
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
     			tokeniser->state = STATE_DATA;
     			return emit_current_doctype(tokeniser, true);
     		} else {
    @@ -2692,12 +2734,13 @@ hubbub_error hubbub_tokeniser_handle_after_doctype_system(
     	c = *cptr;
     	tokeniser->context.pending += len;
     
    -	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') {
    +	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c =='\r') {
     		/* pass over in silence */
     	} else if (c == '>') {
     		tokeniser->state = STATE_DATA;
     		return emit_current_doctype(tokeniser, false);
     	} else {
    +		/** \todo parse error */
     		tokeniser->state = STATE_BOGUS_DOCTYPE;
     	}
     
    @@ -2998,7 +3041,7 @@ hubbub_error hubbub_tokeniser_handle_numbered_entity(
     			break;
     		}
     
    -		if (ctx->match_entity.codepoint >= 0x10FFFF) {
    +		if (ctx->match_entity.codepoint > 0x10FFFF) {
     			ctx->match_entity.overflow = true;
     		}
     	}
    @@ -3011,27 +3054,34 @@ hubbub_error hubbub_tokeniser_handle_numbered_entity(
     	if (error != PARSERUTILS_EOF && *cptr == ';') {
     		ctx->match_entity.length += len;
     	}
    +	else{
    +		/** \todo parse error */
    +	}
     
     	/* Had data, so calculate final codepoint */
     	if (ctx->match_entity.had_data) {
     		uint32_t cp = ctx->match_entity.codepoint;
     
    -		if (0x80 <= cp && cp <= 0x9F) {
    +		if (cp == 0x00) {
    +			cp = 0xFFFD;
    +		} else if (0x80 <= cp && cp <= 0x9F) {
     			cp = cp1252Table[cp - 0x80];
    -		} else if (cp == 0x0D) {
    -			cp = 0x000A;
     		} else if (ctx->match_entity.overflow || 
    -				cp <= 0x0008 || cp == 0x000B ||
    -				(0x000E <= cp && cp <= 0x001F) ||
    -				(0x007F <= cp && cp <= 0x009F) ||
    -				(0xD800 <= cp && cp <= 0xDFFF) ||
    -				(0xFDD0 <= cp && cp <= 0xFDEF) ||
    -				(cp & 0xFFFE) == 0xFFFE) {
    +				(0xD800 <= cp && cp <= 0xDFFF)) {
     			/* the check for cp > 0x10FFFF per spec is performed
     			 * in the loop above to avoid overflow */
     			cp = 0xFFFD;
     		}
     
    +		if ((0x0001 <= cp && cp <= 0x0008) || 
    +			(0x000D <= cp && cp <= 0x001F) ||
    +			(0x007F <= cp && cp <= 0x009F) ||
    +			(0xFDD0 <= cp && cp <= 0xFDEF) ||
    +			cp == 0x000B || (cp & 0xFFFE) == 0xFFFE ||
    +			(cp & 0xFFFF) == 0xFFFF) {
    +			/** \todo parse error */
    +		}
    +
     		ctx->match_entity.codepoint = cp;
     	}
     
    diff --git a/test/data/tokeniser2/numericEntities.test b/test/data/tokeniser2/numericEntities.test
    index 78a8a13..db5f609 100644
    --- a/test/data/tokeniser2/numericEntities.test
    +++ b/test/data/tokeniser2/numericEntities.test
    @@ -6,115 +6,115 @@
     
     {"description": "Invalid numeric entity character U+0001",
     "input": "&#x0001;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0001"]]},
     
     {"description": "Invalid numeric entity character U+0002",
     "input": "&#x0002;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0002"]]},
     
     {"description": "Invalid numeric entity character U+0003",
     "input": "&#x0003;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0003"]]},
     
     {"description": "Invalid numeric entity character U+0004",
     "input": "&#x0004;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0004"]]},
     
     {"description": "Invalid numeric entity character U+0005",
     "input": "&#x0005;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0005"]]},
     
     {"description": "Invalid numeric entity character U+0006",
     "input": "&#x0006;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0006"]]},
     
     {"description": "Invalid numeric entity character U+0007",
     "input": "&#x0007;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0007"]]},
     
     {"description": "Invalid numeric entity character U+0008",
     "input": "&#x0008;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0008"]]},
     
     {"description": "Invalid numeric entity character U+000B",
     "input": "&#x000b;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u000b"]]},
     
     {"description": "Invalid numeric entity character U+000E",
     "input": "&#x000e;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u000e"]]},
     
     {"description": "Invalid numeric entity character U+000F",
     "input": "&#x000f;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u000f"]]},
     
     {"description": "Invalid numeric entity character U+0010",
     "input": "&#x0010;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0010"]]},
     
     {"description": "Invalid numeric entity character U+0011",
     "input": "&#x0011;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0011"]]},
     
     {"description": "Invalid numeric entity character U+0012",
     "input": "&#x0012;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0012"]]},
     
     {"description": "Invalid numeric entity character U+0013",
     "input": "&#x0013;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0013"]]},
     
     {"description": "Invalid numeric entity character U+0014",
     "input": "&#x0014;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0014"]]},
     
     {"description": "Invalid numeric entity character U+0015",
     "input": "&#x0015;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0015"]]},
     
     {"description": "Invalid numeric entity character U+0016",
     "input": "&#x0016;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0016"]]},
     
     {"description": "Invalid numeric entity character U+0017",
     "input": "&#x0017;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0017"]]},
     
     {"description": "Invalid numeric entity character U+0018",
     "input": "&#x0018;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0018"]]},
     
     {"description": "Invalid numeric entity character U+0019",
     "input": "&#x0019;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u0019"]]},
     
     {"description": "Invalid numeric entity character U+001A",
     "input": "&#x001a;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u001a"]]},
     
     {"description": "Invalid numeric entity character U+001B",
     "input": "&#x001b;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u001b"]]},
     
     {"description": "Invalid numeric entity character U+001C",
     "input": "&#x001c;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u001c"]]},
     
     {"description": "Invalid numeric entity character U+001D",
     "input": "&#x001d;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u001d"]]},
     
     {"description": "Invalid numeric entity character U+001E",
     "input": "&#x001e;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u001e"]]},
     
     {"description": "Invalid numeric entity character U+001F",
     "input": "&#x001f;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u001f"]]},
     
     {"description": "Invalid numeric entity character U+007F",
     "input": "&#x007f;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\u007f"]]},
     
     {"description": "Invalid numeric entity character U+D800",
     "input": "&#xd800;",
    @@ -126,267 +126,267 @@
     
     {"description": "Invalid numeric entity character U+FDD0",
     "input": "&#xfdd0;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdd0"]]},
     
     {"description": "Invalid numeric entity character U+FDD1",
     "input": "&#xfdd1;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdd1"]]},
     
     {"description": "Invalid numeric entity character U+FDD2",
     "input": "&#xfdd2;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdd2"]]},
     
     {"description": "Invalid numeric entity character U+FDD3",
     "input": "&#xfdd3;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdd3"]]},
     
     {"description": "Invalid numeric entity character U+FDD4",
     "input": "&#xfdd4;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdd4"]]},
     
     {"description": "Invalid numeric entity character U+FDD5",
     "input": "&#xfdd5;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdd5"]]},
     
     {"description": "Invalid numeric entity character U+FDD6",
     "input": "&#xfdd6;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdd6"]]},
     
     {"description": "Invalid numeric entity character U+FDD7",
     "input": "&#xfdd7;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdd7"]]},
     
     {"description": "Invalid numeric entity character U+FDD8",
     "input": "&#xfdd8;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdd8"]]},
     
     {"description": "Invalid numeric entity character U+FDD9",
     "input": "&#xfdd9;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdd9"]]},
     
     {"description": "Invalid numeric entity character U+FDDA",
     "input": "&#xfdda;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdda"]]},
     
     {"description": "Invalid numeric entity character U+FDDB",
     "input": "&#xfddb;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufddb"]]},
     
     {"description": "Invalid numeric entity character U+FDDC",
     "input": "&#xfddc;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufddc"]]},
     
     {"description": "Invalid numeric entity character U+FDDD",
     "input": "&#xfddd;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufddd"]]},
     
     {"description": "Invalid numeric entity character U+FDDE",
     "input": "&#xfdde;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdde"]]},
     
     {"description": "Invalid numeric entity character U+FDDF",
     "input": "&#xfddf;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufddf"]]},
     
     {"description": "Invalid numeric entity character U+FDE0",
     "input": "&#xfde0;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufde0"]]},
     
     {"description": "Invalid numeric entity character U+FDE1",
     "input": "&#xfde1;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufde1"]]},
     
     {"description": "Invalid numeric entity character U+FDE2",
     "input": "&#xfde2;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufde2"]]},
     
     {"description": "Invalid numeric entity character U+FDE3",
     "input": "&#xfde3;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufde3"]]},
     
     {"description": "Invalid numeric entity character U+FDE4",
     "input": "&#xfde4;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufde4"]]},
     
     {"description": "Invalid numeric entity character U+FDE5",
     "input": "&#xfde5;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufde5"]]},
     
     {"description": "Invalid numeric entity character U+FDE6",
     "input": "&#xfde6;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufde6"]]},
     
     {"description": "Invalid numeric entity character U+FDE7",
     "input": "&#xfde7;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufde7"]]},
     
     {"description": "Invalid numeric entity character U+FDE8",
     "input": "&#xfde8;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufde8"]]},
     
     {"description": "Invalid numeric entity character U+FDE9",
     "input": "&#xfde9;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufde9"]]},
     
     {"description": "Invalid numeric entity character U+FDEA",
     "input": "&#xfdea;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdea"]]},
     
     {"description": "Invalid numeric entity character U+FDEB",
     "input": "&#xfdeb;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdeb"]]},
     
     {"description": "Invalid numeric entity character U+FDEC",
     "input": "&#xfdec;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdec"]]},
     
     {"description": "Invalid numeric entity character U+FDED",
     "input": "&#xfded;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufded"]]},
     
     {"description": "Invalid numeric entity character U+FDEE",
     "input": "&#xfdee;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdee"]]},
     
     {"description": "Invalid numeric entity character U+FDEF",
     "input": "&#xfdef;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufdef"]]},
     
     {"description": "Invalid numeric entity character U+FFFE",
     "input": "&#xfffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\ufffe"]]},
     
     {"description": "Invalid numeric entity character U+FFFF",
     "input": "&#xffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uffff"]]},
     
     {"description": "Invalid numeric entity character U+1FFFE",
     "input": "&#x1fffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD83F\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+1FFFF",
     "input": "&#x1ffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD83F\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+2FFFE",
     "input": "&#x2fffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD87F\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+2FFFF",
     "input": "&#x2ffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD87F\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+3FFFE",
     "input": "&#x3fffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD8BF\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+3FFFF",
     "input": "&#x3ffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD8BF\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+4FFFE",
     "input": "&#x4fffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD8FF\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+4FFFF",
     "input": "&#x4ffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD8FF\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+5FFFE",
     "input": "&#x5fffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD93F\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+5FFFF",
     "input": "&#x5ffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD93F\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+6FFFE",
     "input": "&#x6fffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD97F\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+6FFFF",
     "input": "&#x6ffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD97F\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+7FFFE",
     "input": "&#x7fffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD9BF\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+7FFFF",
     "input": "&#x7ffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD9BF\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+8FFFE",
     "input": "&#x8fffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD9FF\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+8FFFF",
     "input": "&#x8ffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uD9FF\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+9FFFE",
     "input": "&#x9fffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDA3F\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+9FFFF",
     "input": "&#x9ffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDA3F\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+AFFFE",
     "input": "&#xafffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDA7F\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+AFFFF",
     "input": "&#xaffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDA7F\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+BFFFE",
     "input": "&#xbfffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDABF\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+BFFFF",
     "input": "&#xbffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDABF\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+CFFFE",
     "input": "&#xcfffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDAFF\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+CFFFF",
     "input": "&#xcffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDAFF\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+DFFFE",
     "input": "&#xdfffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDB3F\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+DFFFF",
     "input": "&#xdffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDB3F\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+EFFFE",
     "input": "&#xefffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDB7F\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+EFFFF",
     "input": "&#xeffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDB7F\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+FFFFE",
     "input": "&#xffffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDBBF\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+FFFFF",
     "input": "&#xfffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDBBF\uDFFF"]]},
     
     {"description": "Invalid numeric entity character U+10FFFE",
     "input": "&#x10fffe;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDBFF\uDFFE"]]},
     
     {"description": "Invalid numeric entity character U+10FFFF",
     "input": "&#x10ffff;",
    -"output": ["ParseError", ["Character", "\uFFFD"]]},
    +"output": ["ParseError", ["Character", "\uDBFF\uDFFF"]]},
     
     {"description": "Valid numeric entity character U+0009",
     "input": "&#x0009;",
    diff --git a/test/data/tokeniser2/regression.test b/test/data/tokeniser2/regression.test
    index ae3e66a..5bffa74 100644
    --- a/test/data/tokeniser2/regression.test
    +++ b/test/data/tokeniser2/regression.test
    @@ -2,11 +2,11 @@
     
     {"description":"CR in double-quoted attribute value",
     "input":"<foo bar=\"\r\u2022xyz\"",
    -"output":[["StartTag", "foo", {"bar":"\n\u2022xyz"}]]},
    +"output":["ParseError"]},
     
     {"description":"CR in single-quoted attribute value",
     "input":"<foo bar='\r\u2022xyz'",
    -"output":[["StartTag", "foo", {"bar":"\n\u2022xyz"}]]},
    +"output":["ParseError"]},
     
     {"description":"CR in comment",
     "input":"<!--\r\u2022xyz-->",
    diff --git a/test/data/tokeniser2/test1.test b/test/data/tokeniser2/test1.test
    index 9431863..b97b2cb 100644
    --- a/test/data/tokeniser2/test1.test
    +++ b/test/data/tokeniser2/test1.test
    @@ -115,7 +115,7 @@
     
     {"description":"Unfinished entity",
     "input":"&f",
    -"output":["ParseError", ["Character", "&f"]]},
    +"output":[["Character", "&f"]]},
     
     {"description":"Ampersand, number sign",
     "input":"&#",
    @@ -143,11 +143,11 @@
     
     {"description":"Partial entity match at end of file",
     "input":"I'm &no",
    -"output":[["Character","I'm "], "ParseError", ["Character", "&no"]]},
    +"output":[["Character","I'm &no"]]},
     
     {"description":"Non-ASCII character reference name",
     "input":"&\u00AC;",
    -"output":["ParseError", ["Character", "&\u00AC;"]]},
    +"output":[["Character", "&\u00AC;"]]},
     
     {"description":"ASCII decimal entity",
     "input":"&#0036;",
    @@ -163,22 +163,34 @@
     
     {"description":"Entity in attribute without semicolon ending in x",
     "input":"<h a='&notx'>",
    -"output":["ParseError", ["StartTag", "h", {"a":"&notx"}]]},
    +"output":[["StartTag", "h", {"a":"&notx"}]]},
     
     {"description":"Entity in attribute without semicolon ending in 1",
     "input":"<h a='&not1'>",
    -"output":["ParseError", ["StartTag", "h", {"a":"&not1"}]]},
    +"output":[["StartTag", "h", {"a":"&not1"}]]},
     
     {"description":"Entity in attribute without semicolon ending in i",
     "input":"<h a='&noti'>",
    -"output":["ParseError", ["StartTag", "h", {"a":"&noti"}]]},
    +"output":[["StartTag", "h", {"a":"&noti"}]]},
     
     {"description":"Entity in attribute without semicolon",
     "input":"<h a='&COPY'>",
     "output":["ParseError", ["StartTag", "h", {"a":"\u00A9"}]]},
     
     {"description":"Unquoted attribute ending in ampersand",
    - "input":"<s o=& t",
    - "output":["ParseError",["StartTag","s",{"o":"&","t":""}]]}
    +"input":"<s o=& t>",
    +"output":[["StartTag","s",{"o":"&","t":""}]]},
    +
    +{"description":"Unquoted attribute at end of tag with final character of &, with tag followed by characters",
    +"input":"<a a=a&>foo",
    +"output":[["StartTag", "a", {"a":"a&"}], ["Character", "foo"]]},
    +
    +{"description":"plaintext element",
    + "input":"<plaintext>foobar",
    + "output":[["StartTag","plaintext",{}], ["Character","foobar"]]},
    +
    +{"description":"Open angled bracket in unquoted attribute value state",
    + "input":"<a a=f<>",
    + "output":["ParseError", ["StartTag", "a", {"a":"f<"}]]}
     
     ]}
    diff --git a/test/data/tokeniser2/test2.test b/test/data/tokeniser2/test2.test
    index 6d6f6ff..87a8eba 100644
    --- a/test/data/tokeniser2/test2.test
    +++ b/test/data/tokeniser2/test2.test
    @@ -2,7 +2,7 @@
     
     {"description":"DOCTYPE without name",
     "input":"<!DOCTYPE>",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"DOCTYPE without space before name",
     "input":"<!DOCTYPEhtml>",
    @@ -82,7 +82,7 @@
     
     {"description":"Entity without a name",
     "input":"&;",
    -"output":["ParseError", ["Character", "&;"]]},
    +"output":[["Character", "&;"]]},
     
     {"description":"Unescaped ampersand in attribute value",
     "input":"<h a='&'>",
    @@ -134,7 +134,7 @@
     
     {"description":"Null Byte Replacement",
     "input":"\u0000",
    -"output":["ParseError", ["Character", "\ufffd"]]},
    +"output":["ParseError", ["Character", "\u0000"]]},
     
     {"description":"Comment with dash",
     "input":"<!---x",
    @@ -158,6 +158,22 @@
     
     {"description":"Single-quote after attribute name",
     "input":"<h a '>",
    -"output":["ParseError", ["StartTag", "h", {"a":"", "'":""}]]}
    +"output":["ParseError", ["StartTag", "h", {"a":"", "'":""}]]},
    +
    +{"description":"Empty end tag with following characters",
    +"input":"a</>bc",
    +"output":[["Character", "a"], "ParseError", ["Character", "bc"]]},
    +
    +{"description":"Empty end tag with following tag",
    +"input":"a</><b>c",
    +"output":[["Character", "a"], "ParseError", ["StartTag", "b", {}], ["Character", "c"]]},
    +
    +{"description":"Empty end tag with following comment",
    +"input":"a</><!--b-->c",
    +"output":[["Character", "a"], "ParseError", ["Comment", "b"], ["Character", "c"]]},
    +
    +{"description":"Empty end tag with following end tag",
    +"input":"a</></b>c",
    +"output":[["Character", "a"], "ParseError", ["EndTag", "b"], ["Character", "c"]]}
     
     ]}
    diff --git a/test/data/tokeniser2/test3.test b/test/data/tokeniser2/test3.test
    index 593fc93..8fc529a 100644
    --- a/test/data/tokeniser2/test3.test
    +++ b/test/data/tokeniser2/test3.test
    @@ -4,10 +4,6 @@
     "input":"",
     "output":[]},
     
    -{"description":"\\u0000",
    -"input":"\u0000",
    -"output":["ParseError", ["Character", "\uFFFD"]]},
    -
     {"description":"\\u0009",
     "input":"\u0009",
     "output":[["Character", "\u0009"]]},
    @@ -86,7 +82,7 @@
     
     {"description":"<\\u0000",
     "input":"<\u0000",
    -"output":["ParseError", "ParseError", ["Character", "<\uFFFD"]]},
    +"output":["ParseError", ["Character", "<"], "ParseError", ["Character", "\u0000"]]},
     
     {"description":"<\\u0009",
     "input":"<\u0009",
    @@ -114,7 +110,7 @@
     
     {"description":"<!\\u0000",
     "input":"<!\u0000",
    -"output":["ParseError", "ParseError", ["Comment", "\uFFFD"]]},
    +"output":["ParseError", ["Comment", "\uFFFD"]]},
     
     {"description":"<!\\u0009",
     "input":"<!\u0009",
    @@ -522,7 +518,7 @@
     
     {"description":"<!----\\u0000",
     "input":"<!----\u0000",
    -"output":["ParseError", "ParseError", "ParseError", ["Comment", "--\uFFFD"]]},
    +"output":["ParseError", "ParseError", ["Comment", "--\uFFFD"]]},
     
     {"description":"<!----\\u0009",
     "input":"<!----\u0009",
    @@ -544,10 +540,62 @@
     "input":"<!---- ",
     "output":["ParseError", "ParseError", ["Comment", "-- "]]},
     
    +{"description":"<!---- -",
    +"input":"<!---- -",
    +"output":["ParseError", "ParseError", ["Comment", "-- "]]},
    +
    +{"description":"<!---- --",
    +"input":"<!---- --",
    +"output":["ParseError", "ParseError", ["Comment", "-- "]]},
    +
    +{"description":"<!---- -->",
    +"input":"<!---- -->",
    +"output":["ParseError", ["Comment", "-- "]]},
    +
    +{"description":"<!----  -->",
    +"input":"<!----  -->",
    +"output":["ParseError", ["Comment", "--  "]]},
    +
    +{"description":"<!---- a-->",
    +"input":"<!---- a-->",
    +"output":["ParseError", ["Comment", "-- a"]]},
    +
     {"description":"<!----!",
     "input":"<!----!",
    +"output":["ParseError", "ParseError", ["Comment", ""]]},
    +
    +{"description":"<!----!>",
    +"input":"<!----!>",
    +"output":["ParseError", ["Comment", ""]]},
    +
    +{"description":"<!----!a",
    +"input":"<!----!a",
    +"output":["ParseError", "ParseError", ["Comment", "--!a"]]},
    +
    +{"description":"<!----!a-",
    +"input":"<!----!a-",
    +"output":["ParseError", "ParseError", ["Comment", "--!a"]]},
    +
    +{"description":"<!----!a--",
    +"input":"<!----!a--",
    +"output":["ParseError", "ParseError", ["Comment", "--!a"]]},
    +
    +{"description":"<!----!a-->",
    +"input":"<!----!a-->",
    +"output":["ParseError", ["Comment", "--!a"]]},
    +
    +{"description":"<!----!-",
    +"input":"<!----!-",
     "output":["ParseError", "ParseError", ["Comment", "--!"]]},
     
    +{"description":"<!----!--",
    +"input":"<!----!--",
    +"output":["ParseError", "ParseError", ["Comment", "--!"]]},
    +
    +{"description":"<!----!-->",
    +"input":"<!----!-->",
    +"output":["ParseError", ["Comment", "--!"]]},
    +
     {"description":"<!----\"",
     "input":"<!----\"",
     "output":["ParseError", "ParseError", ["Comment", "--\""]]},
    @@ -866,7 +914,7 @@
     
     {"description":"<!DOCTYPE",
     "input":"<!DOCTYPE",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"<!DOCTYPE\\u0000",
     "input":"<!DOCTYPE\u0000",
    @@ -878,11 +926,11 @@
     
     {"description":"<!DOCTYPE\\u0009",
     "input":"<!DOCTYPE\u0009",
    -"output":["ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"<!DOCTYPE\\u000A",
     "input":"<!DOCTYPE\u000A",
    -"output":["ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"<!DOCTYPE\\u000B",
     "input":"<!DOCTYPE\u000B",
    @@ -890,11 +938,11 @@
     
     {"description":"<!DOCTYPE\\u000C",
     "input":"<!DOCTYPE\u000C",
    -"output":["ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"<!DOCTYPE\\u000D",
     "input":"<!DOCTYPE\u000D",
    -"output":["ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"<!DOCTYPE\\u001F",
     "input":"<!DOCTYPE\u001F",
    @@ -902,7 +950,7 @@
     
     {"description":"<!DOCTYPE ",
     "input":"<!DOCTYPE ",
    -"output":["ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"<!DOCTYPE \\u0000",
     "input":"<!DOCTYPE \u0000",
    @@ -914,11 +962,11 @@
     
     {"description":"<!DOCTYPE \\u0009",
     "input":"<!DOCTYPE \u0009",
    -"output":["ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"<!DOCTYPE \\u000A",
     "input":"<!DOCTYPE \u000A",
    -"output":["ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"<!DOCTYPE \\u000B",
     "input":"<!DOCTYPE \u000B",
    @@ -926,11 +974,11 @@
     
     {"description":"<!DOCTYPE \\u000C",
     "input":"<!DOCTYPE \u000C",
    -"output":["ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"<!DOCTYPE \\u000D",
     "input":"<!DOCTYPE \u000D",
    -"output":["ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"<!DOCTYPE \\u001F",
     "input":"<!DOCTYPE \u001F",
    @@ -938,7 +986,7 @@
     
     {"description":"<!DOCTYPE  ",
     "input":"<!DOCTYPE  ",
    -"output":["ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"<!DOCTYPE !",
     "input":"<!DOCTYPE !",
    @@ -986,7 +1034,7 @@
     
     {"description":"<!DOCTYPE >",
     "input":"<!DOCTYPE >",
    -"output":["ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"<!DOCTYPE ?",
     "input":"<!DOCTYPE ?",
    @@ -1062,7 +1110,7 @@
     
     {"description":"<!DOCTYPE a \\u0000",
     "input":"<!DOCTYPE a \u0000",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
     
     {"description":"<!DOCTYPE a \\u0008",
     "input":"<!DOCTYPE a \u0008",
    @@ -1166,7 +1214,7 @@
     
     {"description":"<!DOCTYPE a PUBLIC\\u0000",
     "input":"<!DOCTYPE a PUBLIC\u0000",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\\u0008",
     "input":"<!DOCTYPE a PUBLIC\u0008",
    @@ -1206,135 +1254,135 @@
     
     {"description":"<!DOCTYPE a PUBLIC\"",
     "input":"<!DOCTYPE a PUBLIC\"",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"\\u0000",
     "input":"<!DOCTYPE a PUBLIC\"\u0000",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"\\u0009",
     "input":"<!DOCTYPE a PUBLIC\"\u0009",
    -"output":["ParseError", ["DOCTYPE", "a", "\u0009", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"\\u000A",
     "input":"<!DOCTYPE a PUBLIC\"\u000A",
    -"output":["ParseError", ["DOCTYPE", "a", "\u000A", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"\\u000B",
     "input":"<!DOCTYPE a PUBLIC\"\u000B",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"\\u000C",
     "input":"<!DOCTYPE a PUBLIC\"\u000C",
    -"output":["ParseError", ["DOCTYPE", "a", "\u000C", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\" ",
     "input":"<!DOCTYPE a PUBLIC\" ",
    -"output":["ParseError", ["DOCTYPE", "a", " ", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"!",
     "input":"<!DOCTYPE a PUBLIC\"!",
    -"output":["ParseError", ["DOCTYPE", "a", "!", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"\"",
     "input":"<!DOCTYPE a PUBLIC\"\"",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"#",
     "input":"<!DOCTYPE a PUBLIC\"#",
    -"output":["ParseError", ["DOCTYPE", "a", "#", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "#", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"&",
     "input":"<!DOCTYPE a PUBLIC\"&",
    -"output":["ParseError", ["DOCTYPE", "a", "&", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"'",
     "input":"<!DOCTYPE a PUBLIC\"'",
    -"output":["ParseError", ["DOCTYPE", "a", "'", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "'", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"-",
     "input":"<!DOCTYPE a PUBLIC\"-",
    -"output":["ParseError", ["DOCTYPE", "a", "-", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"/",
     "input":"<!DOCTYPE a PUBLIC\"/",
    -"output":["ParseError", ["DOCTYPE", "a", "/", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"0",
     "input":"<!DOCTYPE a PUBLIC\"0",
    -"output":["ParseError", ["DOCTYPE", "a", "0", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"1",
     "input":"<!DOCTYPE a PUBLIC\"1",
    -"output":["ParseError", ["DOCTYPE", "a", "1", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"9",
     "input":"<!DOCTYPE a PUBLIC\"9",
    -"output":["ParseError", ["DOCTYPE", "a", "9", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"<",
     "input":"<!DOCTYPE a PUBLIC\"<",
    -"output":["ParseError", ["DOCTYPE", "a", "<", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"=",
     "input":"<!DOCTYPE a PUBLIC\"=",
    -"output":["ParseError", ["DOCTYPE", "a", "=", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\">",
     "input":"<!DOCTYPE a PUBLIC\">",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"?",
     "input":"<!DOCTYPE a PUBLIC\"?",
    -"output":["ParseError", ["DOCTYPE", "a", "?", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"@",
     "input":"<!DOCTYPE a PUBLIC\"@",
    -"output":["ParseError", ["DOCTYPE", "a", "@", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"A",
     "input":"<!DOCTYPE a PUBLIC\"A",
    -"output":["ParseError", ["DOCTYPE", "a", "A", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"B",
     "input":"<!DOCTYPE a PUBLIC\"B",
    -"output":["ParseError", ["DOCTYPE", "a", "B", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"Y",
     "input":"<!DOCTYPE a PUBLIC\"Y",
    -"output":["ParseError", ["DOCTYPE", "a", "Y", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"Z",
     "input":"<!DOCTYPE a PUBLIC\"Z",
    -"output":["ParseError", ["DOCTYPE", "a", "Z", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"`",
     "input":"<!DOCTYPE a PUBLIC\"`",
    -"output":["ParseError", ["DOCTYPE", "a", "`", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"a",
     "input":"<!DOCTYPE a PUBLIC\"a",
    -"output":["ParseError", ["DOCTYPE", "a", "a", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"b",
     "input":"<!DOCTYPE a PUBLIC\"b",
    -"output":["ParseError", ["DOCTYPE", "a", "b", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"y",
     "input":"<!DOCTYPE a PUBLIC\"y",
    -"output":["ParseError", ["DOCTYPE", "a", "y", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"z",
     "input":"<!DOCTYPE a PUBLIC\"z",
    -"output":["ParseError", ["DOCTYPE", "a", "z", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"{",
     "input":"<!DOCTYPE a PUBLIC\"{",
    -"output":["ParseError", ["DOCTYPE", "a", "{", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC\"\\uDBC0\\uDC00",
     "input":"<!DOCTYPE a PUBLIC\"\uDBC0\uDC00",
    -"output":["ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC#",
     "input":"<!DOCTYPE a PUBLIC#",
    @@ -1346,47 +1394,47 @@
     
     {"description":"<!DOCTYPE a PUBLIC'",
     "input":"<!DOCTYPE a PUBLIC'",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'\\u0000",
     "input":"<!DOCTYPE a PUBLIC'\u0000",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'\\u0009",
     "input":"<!DOCTYPE a PUBLIC'\u0009",
    -"output":["ParseError", ["DOCTYPE", "a", "\u0009", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'\\u000A",
     "input":"<!DOCTYPE a PUBLIC'\u000A",
    -"output":["ParseError", ["DOCTYPE", "a", "\u000A", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'\\u000B",
     "input":"<!DOCTYPE a PUBLIC'\u000B",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'\\u000C",
     "input":"<!DOCTYPE a PUBLIC'\u000C",
    -"output":["ParseError", ["DOCTYPE", "a", "\u000C", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC' ",
     "input":"<!DOCTYPE a PUBLIC' ",
    -"output":["ParseError", ["DOCTYPE", "a", " ", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'!",
     "input":"<!DOCTYPE a PUBLIC'!",
    -"output":["ParseError", ["DOCTYPE", "a", "!", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'\"",
     "input":"<!DOCTYPE a PUBLIC'\"",
    -"output":["ParseError", ["DOCTYPE", "a", "\"", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\"", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'&",
     "input":"<!DOCTYPE a PUBLIC'&",
    -"output":["ParseError", ["DOCTYPE", "a", "&", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''",
     "input":"<!DOCTYPE a PUBLIC''",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''\\u0000",
     "input":"<!DOCTYPE a PUBLIC''\u0000",
    @@ -1394,231 +1442,231 @@
     
     {"description":"<!DOCTYPE a PUBLIC''\\u0008",
     "input":"<!DOCTYPE a PUBLIC''\u0008",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''\\u0009",
     "input":"<!DOCTYPE a PUBLIC''\u0009",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''\\u000A",
     "input":"<!DOCTYPE a PUBLIC''\u000A",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''\\u000B",
     "input":"<!DOCTYPE a PUBLIC''\u000B",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''\\u000C",
     "input":"<!DOCTYPE a PUBLIC''\u000C",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''\\u000D",
     "input":"<!DOCTYPE a PUBLIC''\u000D",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''\\u001F",
     "input":"<!DOCTYPE a PUBLIC''\u001F",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'' ",
     "input":"<!DOCTYPE a PUBLIC'' ",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''!",
     "input":"<!DOCTYPE a PUBLIC''!",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''\"",
     "input":"<!DOCTYPE a PUBLIC''\"",
    -"output":["ParseError", ["DOCTYPE", "a", "", "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''#",
     "input":"<!DOCTYPE a PUBLIC''#",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''&",
     "input":"<!DOCTYPE a PUBLIC''&",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'''",
     "input":"<!DOCTYPE a PUBLIC'''",
    -"output":["ParseError", ["DOCTYPE", "a", "", "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''(",
     "input":"<!DOCTYPE a PUBLIC''(",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''-",
     "input":"<!DOCTYPE a PUBLIC''-",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''/",
     "input":"<!DOCTYPE a PUBLIC''/",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''0",
     "input":"<!DOCTYPE a PUBLIC''0",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''1",
     "input":"<!DOCTYPE a PUBLIC''1",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''9",
     "input":"<!DOCTYPE a PUBLIC''9",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''<",
     "input":"<!DOCTYPE a PUBLIC''<",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''=",
     "input":"<!DOCTYPE a PUBLIC''=",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''>",
     "input":"<!DOCTYPE a PUBLIC''>",
    -"output":[["DOCTYPE", "a", "", null, true]]},
    +"output":["ParseError", ["DOCTYPE", "a", "", null, true]]},
     
     {"description":"<!DOCTYPE a PUBLIC''?",
     "input":"<!DOCTYPE a PUBLIC''?",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''@",
     "input":"<!DOCTYPE a PUBLIC''@",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''A",
     "input":"<!DOCTYPE a PUBLIC''A",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''B",
     "input":"<!DOCTYPE a PUBLIC''B",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''Y",
     "input":"<!DOCTYPE a PUBLIC''Y",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''Z",
     "input":"<!DOCTYPE a PUBLIC''Z",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''`",
     "input":"<!DOCTYPE a PUBLIC''`",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''a",
     "input":"<!DOCTYPE a PUBLIC''a",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''b",
     "input":"<!DOCTYPE a PUBLIC''b",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''y",
     "input":"<!DOCTYPE a PUBLIC''y",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''z",
     "input":"<!DOCTYPE a PUBLIC''z",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''{",
     "input":"<!DOCTYPE a PUBLIC''{",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC''\\uDBC0\\uDC00",
     "input":"<!DOCTYPE a PUBLIC''\uDBC0\uDC00",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'(",
     "input":"<!DOCTYPE a PUBLIC'(",
    -"output":["ParseError", ["DOCTYPE", "a", "(", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "(", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'-",
     "input":"<!DOCTYPE a PUBLIC'-",
    -"output":["ParseError", ["DOCTYPE", "a", "-", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'/",
     "input":"<!DOCTYPE a PUBLIC'/",
    -"output":["ParseError", ["DOCTYPE", "a", "/", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'0",
     "input":"<!DOCTYPE a PUBLIC'0",
    -"output":["ParseError", ["DOCTYPE", "a", "0", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'1",
     "input":"<!DOCTYPE a PUBLIC'1",
    -"output":["ParseError", ["DOCTYPE", "a", "1", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'9",
     "input":"<!DOCTYPE a PUBLIC'9",
    -"output":["ParseError", ["DOCTYPE", "a", "9", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'<",
     "input":"<!DOCTYPE a PUBLIC'<",
    -"output":["ParseError", ["DOCTYPE", "a", "<", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'=",
     "input":"<!DOCTYPE a PUBLIC'=",
    -"output":["ParseError", ["DOCTYPE", "a", "=", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'>",
     "input":"<!DOCTYPE a PUBLIC'>",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'?",
     "input":"<!DOCTYPE a PUBLIC'?",
    -"output":["ParseError", ["DOCTYPE", "a", "?", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'@",
     "input":"<!DOCTYPE a PUBLIC'@",
    -"output":["ParseError", ["DOCTYPE", "a", "@", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'A",
     "input":"<!DOCTYPE a PUBLIC'A",
    -"output":["ParseError", ["DOCTYPE", "a", "A", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'B",
     "input":"<!DOCTYPE a PUBLIC'B",
    -"output":["ParseError", ["DOCTYPE", "a", "B", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'Y",
     "input":"<!DOCTYPE a PUBLIC'Y",
    -"output":["ParseError", ["DOCTYPE", "a", "Y", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'Z",
     "input":"<!DOCTYPE a PUBLIC'Z",
    -"output":["ParseError", ["DOCTYPE", "a", "Z", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'`",
     "input":"<!DOCTYPE a PUBLIC'`",
    -"output":["ParseError", ["DOCTYPE", "a", "`", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'a",
     "input":"<!DOCTYPE a PUBLIC'a",
    -"output":["ParseError", ["DOCTYPE", "a", "a", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'b",
     "input":"<!DOCTYPE a PUBLIC'b",
    -"output":["ParseError", ["DOCTYPE", "a", "b", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'y",
     "input":"<!DOCTYPE a PUBLIC'y",
    -"output":["ParseError", ["DOCTYPE", "a", "y", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'z",
     "input":"<!DOCTYPE a PUBLIC'z",
    -"output":["ParseError", ["DOCTYPE", "a", "z", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'{",
     "input":"<!DOCTYPE a PUBLIC'{",
    -"output":["ParseError", ["DOCTYPE", "a", "{", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC'\\uDBC0\\uDC00",
     "input":"<!DOCTYPE a PUBLIC'\uDBC0\uDC00",
    -"output":["ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]},
     
     {"description":"<!DOCTYPE a PUBLIC(",
     "input":"<!DOCTYPE a PUBLIC(",
    @@ -1714,7 +1762,7 @@
     
     {"description":"<!DOCTYPE a SYSTEM\\u0000",
     "input":"<!DOCTYPE a SYSTEM\u0000",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\\u0008",
     "input":"<!DOCTYPE a SYSTEM\u0008",
    @@ -1754,135 +1802,135 @@
     
     {"description":"<!DOCTYPE a SYSTEM\"",
     "input":"<!DOCTYPE a SYSTEM\"",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"\\u0000",
     "input":"<!DOCTYPE a SYSTEM\"\u0000",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"\\u0009",
     "input":"<!DOCTYPE a SYSTEM\"\u0009",
    -"output":["ParseError", ["DOCTYPE", "a", null, "\u0009", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"\\u000A",
     "input":"<!DOCTYPE a SYSTEM\"\u000A",
    -"output":["ParseError", ["DOCTYPE", "a", null, "\u000A", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"\\u000B",
     "input":"<!DOCTYPE a SYSTEM\"\u000B",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"\\u000C",
     "input":"<!DOCTYPE a SYSTEM\"\u000C",
    -"output":["ParseError", ["DOCTYPE", "a", null, "\u000C", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\" ",
     "input":"<!DOCTYPE a SYSTEM\" ",
    -"output":["ParseError", ["DOCTYPE", "a", null, " ", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"!",
     "input":"<!DOCTYPE a SYSTEM\"!",
    -"output":["ParseError", ["DOCTYPE", "a", null, "!", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"\"",
     "input":"<!DOCTYPE a SYSTEM\"\"",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"#",
     "input":"<!DOCTYPE a SYSTEM\"#",
    -"output":["ParseError", ["DOCTYPE", "a", null, "#", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "#", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"&",
     "input":"<!DOCTYPE a SYSTEM\"&",
    -"output":["ParseError", ["DOCTYPE", "a", null, "&", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"'",
     "input":"<!DOCTYPE a SYSTEM\"'",
    -"output":["ParseError", ["DOCTYPE", "a", null, "'", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "'", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"-",
     "input":"<!DOCTYPE a SYSTEM\"-",
    -"output":["ParseError", ["DOCTYPE", "a", null, "-", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"/",
     "input":"<!DOCTYPE a SYSTEM\"/",
    -"output":["ParseError", ["DOCTYPE", "a", null, "/", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"0",
     "input":"<!DOCTYPE a SYSTEM\"0",
    -"output":["ParseError", ["DOCTYPE", "a", null, "0", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"1",
     "input":"<!DOCTYPE a SYSTEM\"1",
    -"output":["ParseError", ["DOCTYPE", "a", null, "1", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"9",
     "input":"<!DOCTYPE a SYSTEM\"9",
    -"output":["ParseError", ["DOCTYPE", "a", null, "9", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"<",
     "input":"<!DOCTYPE a SYSTEM\"<",
    -"output":["ParseError", ["DOCTYPE", "a", null, "<", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"=",
     "input":"<!DOCTYPE a SYSTEM\"=",
    -"output":["ParseError", ["DOCTYPE", "a", null, "=", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\">",
     "input":"<!DOCTYPE a SYSTEM\">",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"?",
     "input":"<!DOCTYPE a SYSTEM\"?",
    -"output":["ParseError", ["DOCTYPE", "a", null, "?", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"@",
     "input":"<!DOCTYPE a SYSTEM\"@",
    -"output":["ParseError", ["DOCTYPE", "a", null, "@", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"A",
     "input":"<!DOCTYPE a SYSTEM\"A",
    -"output":["ParseError", ["DOCTYPE", "a", null, "A", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"B",
     "input":"<!DOCTYPE a SYSTEM\"B",
    -"output":["ParseError", ["DOCTYPE", "a", null, "B", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"Y",
     "input":"<!DOCTYPE a SYSTEM\"Y",
    -"output":["ParseError", ["DOCTYPE", "a", null, "Y", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"Z",
     "input":"<!DOCTYPE a SYSTEM\"Z",
    -"output":["ParseError", ["DOCTYPE", "a", null, "Z", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"`",
     "input":"<!DOCTYPE a SYSTEM\"`",
    -"output":["ParseError", ["DOCTYPE", "a", null, "`", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"a",
     "input":"<!DOCTYPE a SYSTEM\"a",
    -"output":["ParseError", ["DOCTYPE", "a", null, "a", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"b",
     "input":"<!DOCTYPE a SYSTEM\"b",
    -"output":["ParseError", ["DOCTYPE", "a", null, "b", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"y",
     "input":"<!DOCTYPE a SYSTEM\"y",
    -"output":["ParseError", ["DOCTYPE", "a", null, "y", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"z",
     "input":"<!DOCTYPE a SYSTEM\"z",
    -"output":["ParseError", ["DOCTYPE", "a", null, "z", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"{",
     "input":"<!DOCTYPE a SYSTEM\"{",
    -"output":["ParseError", ["DOCTYPE", "a", null, "{", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM\"\\uDBC0\\uDC00",
     "input":"<!DOCTYPE a SYSTEM\"\uDBC0\uDC00",
    -"output":["ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM#",
     "input":"<!DOCTYPE a SYSTEM#",
    @@ -1894,47 +1942,47 @@
     
     {"description":"<!DOCTYPE a SYSTEM'",
     "input":"<!DOCTYPE a SYSTEM'",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'\\u0000",
     "input":"<!DOCTYPE a SYSTEM'\u0000",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'\\u0009",
     "input":"<!DOCTYPE a SYSTEM'\u0009",
    -"output":["ParseError", ["DOCTYPE", "a", null, "\u0009", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'\\u000A",
     "input":"<!DOCTYPE a SYSTEM'\u000A",
    -"output":["ParseError", ["DOCTYPE", "a", null, "\u000A", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'\\u000B",
     "input":"<!DOCTYPE a SYSTEM'\u000B",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'\\u000C",
     "input":"<!DOCTYPE a SYSTEM'\u000C",
    -"output":["ParseError", ["DOCTYPE", "a", null, "\u000C", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM' ",
     "input":"<!DOCTYPE a SYSTEM' ",
    -"output":["ParseError", ["DOCTYPE", "a", null, " ", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'!",
     "input":"<!DOCTYPE a SYSTEM'!",
    -"output":["ParseError", ["DOCTYPE", "a", null, "!", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'\"",
     "input":"<!DOCTYPE a SYSTEM'\"",
    -"output":["ParseError", ["DOCTYPE", "a", null, "\"", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\"", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'&",
     "input":"<!DOCTYPE a SYSTEM'&",
    -"output":["ParseError", ["DOCTYPE", "a", null, "&", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM''",
     "input":"<!DOCTYPE a SYSTEM''",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM''\\u0000",
     "input":"<!DOCTYPE a SYSTEM''\u0000",
    @@ -1942,223 +1990,223 @@
     
     {"description":"<!DOCTYPE a SYSTEM''\\u0008",
     "input":"<!DOCTYPE a SYSTEM''\u0008",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''\\u0009",
     "input":"<!DOCTYPE a SYSTEM''\u0009",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM''\\u000A",
     "input":"<!DOCTYPE a SYSTEM''\u000A",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM''\\u000B",
     "input":"<!DOCTYPE a SYSTEM''\u000B",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''\\u000C",
     "input":"<!DOCTYPE a SYSTEM''\u000C",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM''\\u000D",
     "input":"<!DOCTYPE a SYSTEM''\u000D",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM''\\u001F",
     "input":"<!DOCTYPE a SYSTEM''\u001F",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM'' ",
     "input":"<!DOCTYPE a SYSTEM'' ",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM''!",
     "input":"<!DOCTYPE a SYSTEM''!",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''\"",
     "input":"<!DOCTYPE a SYSTEM''\"",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''&",
     "input":"<!DOCTYPE a SYSTEM''&",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM'''",
     "input":"<!DOCTYPE a SYSTEM'''",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''-",
     "input":"<!DOCTYPE a SYSTEM''-",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''/",
     "input":"<!DOCTYPE a SYSTEM''/",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''0",
     "input":"<!DOCTYPE a SYSTEM''0",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''1",
     "input":"<!DOCTYPE a SYSTEM''1",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''9",
     "input":"<!DOCTYPE a SYSTEM''9",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''<",
     "input":"<!DOCTYPE a SYSTEM''<",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''=",
     "input":"<!DOCTYPE a SYSTEM''=",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''>",
     "input":"<!DOCTYPE a SYSTEM''>",
    -"output":[["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''?",
     "input":"<!DOCTYPE a SYSTEM''?",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''@",
     "input":"<!DOCTYPE a SYSTEM''@",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''A",
     "input":"<!DOCTYPE a SYSTEM''A",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''B",
     "input":"<!DOCTYPE a SYSTEM''B",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''Y",
     "input":"<!DOCTYPE a SYSTEM''Y",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''Z",
     "input":"<!DOCTYPE a SYSTEM''Z",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''`",
     "input":"<!DOCTYPE a SYSTEM''`",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''a",
     "input":"<!DOCTYPE a SYSTEM''a",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''b",
     "input":"<!DOCTYPE a SYSTEM''b",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''y",
     "input":"<!DOCTYPE a SYSTEM''y",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''z",
     "input":"<!DOCTYPE a SYSTEM''z",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''{",
     "input":"<!DOCTYPE a SYSTEM''{",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM''\\uDBC0\\uDC00",
     "input":"<!DOCTYPE a SYSTEM''\uDBC0\uDC00",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPE a SYSTEM'(",
     "input":"<!DOCTYPE a SYSTEM'(",
    -"output":["ParseError", ["DOCTYPE", "a", null, "(", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "(", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'-",
     "input":"<!DOCTYPE a SYSTEM'-",
    -"output":["ParseError", ["DOCTYPE", "a", null, "-", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'/",
     "input":"<!DOCTYPE a SYSTEM'/",
    -"output":["ParseError", ["DOCTYPE", "a", null, "/", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'0",
     "input":"<!DOCTYPE a SYSTEM'0",
    -"output":["ParseError", ["DOCTYPE", "a", null, "0", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'1",
     "input":"<!DOCTYPE a SYSTEM'1",
    -"output":["ParseError", ["DOCTYPE", "a", null, "1", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'9",
     "input":"<!DOCTYPE a SYSTEM'9",
    -"output":["ParseError", ["DOCTYPE", "a", null, "9", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'<",
     "input":"<!DOCTYPE a SYSTEM'<",
    -"output":["ParseError", ["DOCTYPE", "a", null, "<", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'=",
     "input":"<!DOCTYPE a SYSTEM'=",
    -"output":["ParseError", ["DOCTYPE", "a", null, "=", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'>",
     "input":"<!DOCTYPE a SYSTEM'>",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'?",
     "input":"<!DOCTYPE a SYSTEM'?",
    -"output":["ParseError", ["DOCTYPE", "a", null, "?", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'@",
     "input":"<!DOCTYPE a SYSTEM'@",
    -"output":["ParseError", ["DOCTYPE", "a", null, "@", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'A",
     "input":"<!DOCTYPE a SYSTEM'A",
    -"output":["ParseError", ["DOCTYPE", "a", null, "A", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'B",
     "input":"<!DOCTYPE a SYSTEM'B",
    -"output":["ParseError", ["DOCTYPE", "a", null, "B", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'Y",
     "input":"<!DOCTYPE a SYSTEM'Y",
    -"output":["ParseError", ["DOCTYPE", "a", null, "Y", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'Z",
     "input":"<!DOCTYPE a SYSTEM'Z",
    -"output":["ParseError", ["DOCTYPE", "a", null, "Z", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'`",
     "input":"<!DOCTYPE a SYSTEM'`",
    -"output":["ParseError", ["DOCTYPE", "a", null, "`", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'a",
     "input":"<!DOCTYPE a SYSTEM'a",
    -"output":["ParseError", ["DOCTYPE", "a", null, "a", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'b",
     "input":"<!DOCTYPE a SYSTEM'b",
    -"output":["ParseError", ["DOCTYPE", "a", null, "b", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'y",
     "input":"<!DOCTYPE a SYSTEM'y",
    -"output":["ParseError", ["DOCTYPE", "a", null, "y", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'z",
     "input":"<!DOCTYPE a SYSTEM'z",
    -"output":["ParseError", ["DOCTYPE", "a", null, "z", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'{",
     "input":"<!DOCTYPE a SYSTEM'{",
    -"output":["ParseError", ["DOCTYPE", "a", null, "{", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM'\\uDBC0\\uDC00",
     "input":"<!DOCTYPE a SYSTEM'\uDBC0\uDC00",
    -"output":["ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]},
     
     {"description":"<!DOCTYPE a SYSTEM(",
     "input":"<!DOCTYPE a SYSTEM(",
    @@ -2266,7 +2314,7 @@
     
     {"description":"<!DOCTYPE a a\\u0000",
     "input":"<!DOCTYPE a a\u0000",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
    +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
     
     {"description":"<!DOCTYPE a a\\u0009",
     "input":"<!DOCTYPE a a\u0009",
    @@ -2578,7 +2626,7 @@
     
     {"description":"<!DOCTYPE>",
     "input":"<!DOCTYPE>",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "", null, null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", null, null, null, false]]},
     
     {"description":"<!DOCTYPE?",
     "input":"<!DOCTYPE?",
    @@ -2650,7 +2698,7 @@
     
     {"description":"<!DOCTYPEa \\u0000",
     "input":"<!DOCTYPEa \u0000",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
     
     {"description":"<!DOCTYPEa \\u0008",
     "input":"<!DOCTYPEa \u0008",
    @@ -2754,7 +2802,7 @@
     
     {"description":"<!DOCTYPEa PUBLIC\\u0000",
     "input":"<!DOCTYPEa PUBLIC\u0000",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\\u0008",
     "input":"<!DOCTYPEa PUBLIC\u0008",
    @@ -2794,135 +2842,135 @@
     
     {"description":"<!DOCTYPEa PUBLIC\"",
     "input":"<!DOCTYPEa PUBLIC\"",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"\\u0000",
     "input":"<!DOCTYPEa PUBLIC\"\u0000",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"\\u0009",
     "input":"<!DOCTYPEa PUBLIC\"\u0009",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"\\u000A",
     "input":"<!DOCTYPEa PUBLIC\"\u000A",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"\\u000B",
     "input":"<!DOCTYPEa PUBLIC\"\u000B",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"\\u000C",
     "input":"<!DOCTYPEa PUBLIC\"\u000C",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\" ",
     "input":"<!DOCTYPEa PUBLIC\" ",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"!",
     "input":"<!DOCTYPEa PUBLIC\"!",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"\"",
     "input":"<!DOCTYPEa PUBLIC\"\"",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"#",
     "input":"<!DOCTYPEa PUBLIC\"#",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "#", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "#", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"&",
     "input":"<!DOCTYPEa PUBLIC\"&",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"'",
     "input":"<!DOCTYPEa PUBLIC\"'",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "'", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "'", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"-",
     "input":"<!DOCTYPEa PUBLIC\"-",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"/",
     "input":"<!DOCTYPEa PUBLIC\"/",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"0",
     "input":"<!DOCTYPEa PUBLIC\"0",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"1",
     "input":"<!DOCTYPEa PUBLIC\"1",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"9",
     "input":"<!DOCTYPEa PUBLIC\"9",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"<",
     "input":"<!DOCTYPEa PUBLIC\"<",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"=",
     "input":"<!DOCTYPEa PUBLIC\"=",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\">",
     "input":"<!DOCTYPEa PUBLIC\">",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"?",
     "input":"<!DOCTYPEa PUBLIC\"?",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"@",
     "input":"<!DOCTYPEa PUBLIC\"@",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"A",
     "input":"<!DOCTYPEa PUBLIC\"A",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"B",
     "input":"<!DOCTYPEa PUBLIC\"B",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"Y",
     "input":"<!DOCTYPEa PUBLIC\"Y",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"Z",
     "input":"<!DOCTYPEa PUBLIC\"Z",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"`",
     "input":"<!DOCTYPEa PUBLIC\"`",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"a",
     "input":"<!DOCTYPEa PUBLIC\"a",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"b",
     "input":"<!DOCTYPEa PUBLIC\"b",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"y",
     "input":"<!DOCTYPEa PUBLIC\"y",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"z",
     "input":"<!DOCTYPEa PUBLIC\"z",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"{",
     "input":"<!DOCTYPEa PUBLIC\"{",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC\"\\uDBC0\\uDC00",
     "input":"<!DOCTYPEa PUBLIC\"\uDBC0\uDC00",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC#",
     "input":"<!DOCTYPEa PUBLIC#",
    @@ -2934,47 +2982,47 @@
     
     {"description":"<!DOCTYPEa PUBLIC'",
     "input":"<!DOCTYPEa PUBLIC'",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'\\u0000",
     "input":"<!DOCTYPEa PUBLIC'\u0000",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'\\u0009",
     "input":"<!DOCTYPEa PUBLIC'\u0009",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'\\u000A",
     "input":"<!DOCTYPEa PUBLIC'\u000A",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'\\u000B",
     "input":"<!DOCTYPEa PUBLIC'\u000B",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'\\u000C",
     "input":"<!DOCTYPEa PUBLIC'\u000C",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC' ",
     "input":"<!DOCTYPEa PUBLIC' ",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'!",
     "input":"<!DOCTYPEa PUBLIC'!",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'\"",
     "input":"<!DOCTYPEa PUBLIC'\"",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\"", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\"", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'&",
     "input":"<!DOCTYPEa PUBLIC'&",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''",
     "input":"<!DOCTYPEa PUBLIC''",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''\\u0000",
     "input":"<!DOCTYPEa PUBLIC''\u0000",
    @@ -2982,231 +3030,231 @@
     
     {"description":"<!DOCTYPEa PUBLIC''\\u0008",
     "input":"<!DOCTYPEa PUBLIC''\u0008",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''\\u0009",
     "input":"<!DOCTYPEa PUBLIC''\u0009",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''\\u000A",
     "input":"<!DOCTYPEa PUBLIC''\u000A",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''\\u000B",
     "input":"<!DOCTYPEa PUBLIC''\u000B",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''\\u000C",
     "input":"<!DOCTYPEa PUBLIC''\u000C",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''\\u000D",
     "input":"<!DOCTYPEa PUBLIC''\u000D",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''\\u001F",
     "input":"<!DOCTYPEa PUBLIC''\u001F",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'' ",
     "input":"<!DOCTYPEa PUBLIC'' ",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''!",
     "input":"<!DOCTYPEa PUBLIC''!",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''\"",
     "input":"<!DOCTYPEa PUBLIC''\"",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''#",
     "input":"<!DOCTYPEa PUBLIC''#",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''&",
     "input":"<!DOCTYPEa PUBLIC''&",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'''",
     "input":"<!DOCTYPEa PUBLIC'''",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''(",
     "input":"<!DOCTYPEa PUBLIC''(",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''-",
     "input":"<!DOCTYPEa PUBLIC''-",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''/",
     "input":"<!DOCTYPEa PUBLIC''/",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''0",
     "input":"<!DOCTYPEa PUBLIC''0",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''1",
     "input":"<!DOCTYPEa PUBLIC''1",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''9",
     "input":"<!DOCTYPEa PUBLIC''9",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''<",
     "input":"<!DOCTYPEa PUBLIC''<",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''=",
     "input":"<!DOCTYPEa PUBLIC''=",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''>",
     "input":"<!DOCTYPEa PUBLIC''>",
    -"output":["ParseError", ["DOCTYPE", "a", "", null, true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, true]]},
     
     {"description":"<!DOCTYPEa PUBLIC''?",
     "input":"<!DOCTYPEa PUBLIC''?",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''@",
     "input":"<!DOCTYPEa PUBLIC''@",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''A",
     "input":"<!DOCTYPEa PUBLIC''A",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''B",
     "input":"<!DOCTYPEa PUBLIC''B",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''Y",
     "input":"<!DOCTYPEa PUBLIC''Y",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''Z",
     "input":"<!DOCTYPEa PUBLIC''Z",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''`",
     "input":"<!DOCTYPEa PUBLIC''`",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''a",
     "input":"<!DOCTYPEa PUBLIC''a",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''b",
     "input":"<!DOCTYPEa PUBLIC''b",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''y",
     "input":"<!DOCTYPEa PUBLIC''y",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''z",
     "input":"<!DOCTYPEa PUBLIC''z",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''{",
     "input":"<!DOCTYPEa PUBLIC''{",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC''\\uDBC0\\uDC00",
     "input":"<!DOCTYPEa PUBLIC''\uDBC0\uDC00",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'(",
     "input":"<!DOCTYPEa PUBLIC'(",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "(", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "(", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'-",
     "input":"<!DOCTYPEa PUBLIC'-",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'/",
     "input":"<!DOCTYPEa PUBLIC'/",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'0",
     "input":"<!DOCTYPEa PUBLIC'0",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'1",
     "input":"<!DOCTYPEa PUBLIC'1",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'9",
     "input":"<!DOCTYPEa PUBLIC'9",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'<",
     "input":"<!DOCTYPEa PUBLIC'<",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'=",
     "input":"<!DOCTYPEa PUBLIC'=",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'>",
     "input":"<!DOCTYPEa PUBLIC'>",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'?",
     "input":"<!DOCTYPEa PUBLIC'?",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'@",
     "input":"<!DOCTYPEa PUBLIC'@",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'A",
     "input":"<!DOCTYPEa PUBLIC'A",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'B",
     "input":"<!DOCTYPEa PUBLIC'B",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'Y",
     "input":"<!DOCTYPEa PUBLIC'Y",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'Z",
     "input":"<!DOCTYPEa PUBLIC'Z",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'`",
     "input":"<!DOCTYPEa PUBLIC'`",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'a",
     "input":"<!DOCTYPEa PUBLIC'a",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'b",
     "input":"<!DOCTYPEa PUBLIC'b",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'y",
     "input":"<!DOCTYPEa PUBLIC'y",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'z",
     "input":"<!DOCTYPEa PUBLIC'z",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'{",
     "input":"<!DOCTYPEa PUBLIC'{",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC'\\uDBC0\\uDC00",
     "input":"<!DOCTYPEa PUBLIC'\uDBC0\uDC00",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]},
     
     {"description":"<!DOCTYPEa PUBLIC(",
     "input":"<!DOCTYPEa PUBLIC(",
    @@ -3302,7 +3350,7 @@
     
     {"description":"<!DOCTYPEa SYSTEM\\u0000",
     "input":"<!DOCTYPEa SYSTEM\u0000",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\\u0008",
     "input":"<!DOCTYPEa SYSTEM\u0008",
    @@ -3342,135 +3390,135 @@
     
     {"description":"<!DOCTYPEa SYSTEM\"",
     "input":"<!DOCTYPEa SYSTEM\"",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"\\u0000",
     "input":"<!DOCTYPEa SYSTEM\"\u0000",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"\\u0009",
     "input":"<!DOCTYPEa SYSTEM\"\u0009",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"\\u000A",
     "input":"<!DOCTYPEa SYSTEM\"\u000A",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"\\u000B",
     "input":"<!DOCTYPEa SYSTEM\"\u000B",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"\\u000C",
     "input":"<!DOCTYPEa SYSTEM\"\u000C",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\" ",
     "input":"<!DOCTYPEa SYSTEM\" ",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"!",
     "input":"<!DOCTYPEa SYSTEM\"!",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"\"",
     "input":"<!DOCTYPEa SYSTEM\"\"",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"#",
     "input":"<!DOCTYPEa SYSTEM\"#",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "#", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "#", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"&",
     "input":"<!DOCTYPEa SYSTEM\"&",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"'",
     "input":"<!DOCTYPEa SYSTEM\"'",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "'", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "'", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"-",
     "input":"<!DOCTYPEa SYSTEM\"-",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"/",
     "input":"<!DOCTYPEa SYSTEM\"/",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"0",
     "input":"<!DOCTYPEa SYSTEM\"0",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"1",
     "input":"<!DOCTYPEa SYSTEM\"1",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"9",
     "input":"<!DOCTYPEa SYSTEM\"9",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"<",
     "input":"<!DOCTYPEa SYSTEM\"<",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"=",
     "input":"<!DOCTYPEa SYSTEM\"=",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\">",
     "input":"<!DOCTYPEa SYSTEM\">",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"?",
     "input":"<!DOCTYPEa SYSTEM\"?",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"@",
     "input":"<!DOCTYPEa SYSTEM\"@",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"A",
     "input":"<!DOCTYPEa SYSTEM\"A",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"B",
     "input":"<!DOCTYPEa SYSTEM\"B",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"Y",
     "input":"<!DOCTYPEa SYSTEM\"Y",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"Z",
     "input":"<!DOCTYPEa SYSTEM\"Z",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"`",
     "input":"<!DOCTYPEa SYSTEM\"`",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"a",
     "input":"<!DOCTYPEa SYSTEM\"a",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"b",
     "input":"<!DOCTYPEa SYSTEM\"b",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"y",
     "input":"<!DOCTYPEa SYSTEM\"y",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"z",
     "input":"<!DOCTYPEa SYSTEM\"z",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"{",
     "input":"<!DOCTYPEa SYSTEM\"{",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM\"\\uDBC0\\uDC00",
     "input":"<!DOCTYPEa SYSTEM\"\uDBC0\uDC00",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM#",
     "input":"<!DOCTYPEa SYSTEM#",
    @@ -3482,47 +3530,47 @@
     
     {"description":"<!DOCTYPEa SYSTEM'",
     "input":"<!DOCTYPEa SYSTEM'",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'\\u0000",
     "input":"<!DOCTYPEa SYSTEM'\u0000",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'\\u0009",
     "input":"<!DOCTYPEa SYSTEM'\u0009",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'\\u000A",
     "input":"<!DOCTYPEa SYSTEM'\u000A",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'\\u000B",
     "input":"<!DOCTYPEa SYSTEM'\u000B",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'\\u000C",
     "input":"<!DOCTYPEa SYSTEM'\u000C",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM' ",
     "input":"<!DOCTYPEa SYSTEM' ",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'!",
     "input":"<!DOCTYPEa SYSTEM'!",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'\"",
     "input":"<!DOCTYPEa SYSTEM'\"",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\"", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\"", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'&",
     "input":"<!DOCTYPEa SYSTEM'&",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM''",
     "input":"<!DOCTYPEa SYSTEM''",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM''\\u0000",
     "input":"<!DOCTYPEa SYSTEM''\u0000",
    @@ -3530,223 +3578,223 @@
     
     {"description":"<!DOCTYPEa SYSTEM''\\u0008",
     "input":"<!DOCTYPEa SYSTEM''\u0008",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''\\u0009",
     "input":"<!DOCTYPEa SYSTEM''\u0009",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM''\\u000A",
     "input":"<!DOCTYPEa SYSTEM''\u000A",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM''\\u000B",
     "input":"<!DOCTYPEa SYSTEM''\u000B",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''\\u000C",
     "input":"<!DOCTYPEa SYSTEM''\u000C",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM''\\u000D",
     "input":"<!DOCTYPEa SYSTEM''\u000D",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM''\\u001F",
     "input":"<!DOCTYPEa SYSTEM''\u001F",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM'' ",
     "input":"<!DOCTYPEa SYSTEM'' ",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM''!",
     "input":"<!DOCTYPEa SYSTEM''!",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''\"",
     "input":"<!DOCTYPEa SYSTEM''\"",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''&",
     "input":"<!DOCTYPEa SYSTEM''&",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM'''",
     "input":"<!DOCTYPEa SYSTEM'''",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''-",
     "input":"<!DOCTYPEa SYSTEM''-",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''/",
     "input":"<!DOCTYPEa SYSTEM''/",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''0",
     "input":"<!DOCTYPEa SYSTEM''0",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''1",
     "input":"<!DOCTYPEa SYSTEM''1",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''9",
     "input":"<!DOCTYPEa SYSTEM''9",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''<",
     "input":"<!DOCTYPEa SYSTEM''<",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''=",
     "input":"<!DOCTYPEa SYSTEM''=",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''>",
     "input":"<!DOCTYPEa SYSTEM''>",
    -"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''?",
     "input":"<!DOCTYPEa SYSTEM''?",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''@",
     "input":"<!DOCTYPEa SYSTEM''@",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''A",
     "input":"<!DOCTYPEa SYSTEM''A",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''B",
     "input":"<!DOCTYPEa SYSTEM''B",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''Y",
     "input":"<!DOCTYPEa SYSTEM''Y",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''Z",
     "input":"<!DOCTYPEa SYSTEM''Z",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''`",
     "input":"<!DOCTYPEa SYSTEM''`",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''a",
     "input":"<!DOCTYPEa SYSTEM''a",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''b",
     "input":"<!DOCTYPEa SYSTEM''b",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''y",
     "input":"<!DOCTYPEa SYSTEM''y",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''z",
     "input":"<!DOCTYPEa SYSTEM''z",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''{",
     "input":"<!DOCTYPEa SYSTEM''{",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM''\\uDBC0\\uDC00",
     "input":"<!DOCTYPEa SYSTEM''\uDBC0\uDC00",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
     
     {"description":"<!DOCTYPEa SYSTEM'(",
     "input":"<!DOCTYPEa SYSTEM'(",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "(", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "(", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'-",
     "input":"<!DOCTYPEa SYSTEM'-",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'/",
     "input":"<!DOCTYPEa SYSTEM'/",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'0",
     "input":"<!DOCTYPEa SYSTEM'0",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'1",
     "input":"<!DOCTYPEa SYSTEM'1",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'9",
     "input":"<!DOCTYPEa SYSTEM'9",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'<",
     "input":"<!DOCTYPEa SYSTEM'<",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'=",
     "input":"<!DOCTYPEa SYSTEM'=",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'>",
     "input":"<!DOCTYPEa SYSTEM'>",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'?",
     "input":"<!DOCTYPEa SYSTEM'?",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'@",
     "input":"<!DOCTYPEa SYSTEM'@",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'A",
     "input":"<!DOCTYPEa SYSTEM'A",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'B",
     "input":"<!DOCTYPEa SYSTEM'B",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'Y",
     "input":"<!DOCTYPEa SYSTEM'Y",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'Z",
     "input":"<!DOCTYPEa SYSTEM'Z",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'`",
     "input":"<!DOCTYPEa SYSTEM'`",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'a",
     "input":"<!DOCTYPEa SYSTEM'a",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'b",
     "input":"<!DOCTYPEa SYSTEM'b",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'y",
     "input":"<!DOCTYPEa SYSTEM'y",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'z",
     "input":"<!DOCTYPEa SYSTEM'z",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'{",
     "input":"<!DOCTYPEa SYSTEM'{",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM'\\uDBC0\\uDC00",
     "input":"<!DOCTYPEa SYSTEM'\uDBC0\uDC00",
    -"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]},
    +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]},
     
     {"description":"<!DOCTYPEa SYSTEM(",
     "input":"<!DOCTYPEa SYSTEM(",
    @@ -3854,7 +3902,7 @@
     
     {"description":"<!DOCTYPEa a\\u0000",
     "input":"<!DOCTYPEa a\u0000",
    -"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
    +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
     
     {"description":"<!DOCTYPEa a\\u0009",
     "input":"<!DOCTYPEa a\u0009",
    @@ -4182,7 +4230,7 @@
     
     {"description":"</\\u0000",
     "input":"</\u0000",
    -"output":["ParseError", "ParseError", ["Comment", "\uFFFD"]]},
    +"output":["ParseError", ["Comment", "\uFFFD"]]},
     
     {"description":"</\\u0009",
     "input":"</\u0009",
    @@ -4260,21 +4308,21 @@
     "input":"</@",
     "output":["ParseError", ["Comment", "@"]]},
     
    -{"description":"</A",
    -"input":"</A",
    -"output":["ParseError", ["EndTag", "a"]]},
    +{"description":"</A>",
    +"input":"</A>",
    +"output":[["EndTag", "a"]]},
     
    -{"description":"</B",
    -"input":"</B",
    -"output":["ParseError", ["EndTag", "b"]]},
    +{"description":"</B>",
    +"input":"</B>",
    +"output":[["EndTag", "b"]]},
     
    -{"description":"</Y",
    -"input":"</Y",
    -"output":["ParseError", ["EndTag", "y"]]},
    +{"description":"</Y>",
    +"input":"</Y>",
    +"output":[["EndTag", "y"]]},
     
    -{"description":"</Z",
    -"input":"</Z",
    -"output":["ParseError", ["EndTag", "z"]]},
    +{"description":"</Z>",
    +"input":"</Z>",
    +"output":[["EndTag", "z"]]},
     
     {"description":"</[",
     "input":"</[",
    @@ -4284,21 +4332,21 @@
     "input":"</`",
     "output":["ParseError", ["Comment", "`"]]},
     
    -{"description":"</a",
    -"input":"</a",
    -"output":["ParseError", ["EndTag", "a"]]},
    +{"description":"</a>",
    +"input":"</a>",
    +"output":[["EndTag", "a"]]},
     
    -{"description":"</b",
    -"input":"</b",
    -"output":["ParseError", ["EndTag", "b"]]},
    +{"description":"</b>",
    +"input":"</b>",
    +"output":[["EndTag", "b"]]},
     
    -{"description":"</y",
    -"input":"</y",
    -"output":["ParseError", ["EndTag", "y"]]},
    +{"description":"</y>",
    +"input":"</y>",
    +"output":[["EndTag", "y"]]},
     
    -{"description":"</z",
    -"input":"</z",
    -"output":["ParseError", ["EndTag", "z"]]},
    +{"description":"</z>",
    +"input":"</z>",
    +"output":[["EndTag", "z"]]},
     
     {"description":"</{",
     "input":"</{",
    @@ -4338,7 +4386,7 @@
     
     {"description":"<?\\u0000",
     "input":"<?\u0000",
    -"output":["ParseError", "ParseError", ["Comment", "?\uFFFD"]]},
    +"output":["ParseError", ["Comment", "?\uFFFD"]]},
     
     {"description":"<?\\u0009",
     "input":"<?\u0009",
    @@ -4464,21 +4512,21 @@
     "input":"<@",
     "output":["ParseError", ["Character", "<@"]]},
     
    -{"description":"<A",
    -"input":"<A",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<A>",
    +"input":"<A>",
    +"output":[["StartTag", "a", {}]]},
     
    -{"description":"<B",
    -"input":"<B",
    -"output":["ParseError", ["StartTag", "b", {}]]},
    +{"description":"<B>",
    +"input":"<B>",
    +"output":[["StartTag", "b", {}]]},
     
    -{"description":"<Y",
    -"input":"<Y",
    -"output":["ParseError", ["StartTag", "y", {}]]},
    +{"description":"<Y>",
    +"input":"<Y>",
    +"output":[["StartTag", "y", {}]]},
     
    -{"description":"<Z",
    -"input":"<Z",
    -"output":["ParseError", ["StartTag", "z", {}]]},
    +{"description":"<Z>",
    +"input":"<Z>",
    +"output":[["StartTag", "z", {}]]},
     
     {"description":"<[",
     "input":"<[",
    @@ -4488,1445 +4536,1445 @@
     "input":"<`",
     "output":["ParseError", ["Character", "<`"]]},
     
    -{"description":"<a",
    -"input":"<a",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a>",
    +"input":"<a>",
    +"output":[["StartTag", "a", {}]]},
     
    -{"description":"<a\\u0000",
    -"input":"<a\u0000",
    -"output":["ParseError", "ParseError", ["StartTag", "a\uFFFD", {}]]},
    +{"description":"<a\\u0000>",
    +"input":"<a\u0000>",
    +"output":["ParseError", ["StartTag", "a\uFFFD", {}]]},
     
    -{"description":"<a\\u0008",
    -"input":"<a\u0008",
    -"output":["ParseError", "ParseError", ["StartTag", "a\u0008", {}]]},
    +{"description":"<a\\u0008>",
    +"input":"<a\u0008>",
    +"output":["ParseError", ["StartTag", "a\u0008", {}]]},
     
    -{"description":"<a\\u0009",
    -"input":"<a\u0009",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a\\u0009>",
    +"input":"<a\u0009>",
    +"output":[["StartTag", "a", {}]]},
     
    -{"description":"<a\\u000A",
    -"input":"<a\u000A",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a\\u000A>",
    +"input":"<a\u000A>",
    +"output":[["StartTag", "a", {}]]},
     
    -{"description":"<a\\u000B",
    -"input":"<a\u000B",
    -"output":["ParseError", "ParseError", ["StartTag", "a\u000B", {}]]},
    +{"description":"<a\\u000B>",
    +"input":"<a\u000B>",
    +"output":["ParseError", ["StartTag", "a\u000B", {}]]},
     
    -{"description":"<a\\u000C",
    -"input":"<a\u000C",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a\\u000C>",
    +"input":"<a\u000C>",
    +"output":[["StartTag", "a", {}]]},
     
    -{"description":"<a\\u000D",
    -"input":"<a\u000D",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a\\u000D>",
    +"input":"<a\u000D>",
    +"output":[["StartTag", "a", {}]]},
     
    -{"description":"<a\\u001F",
    -"input":"<a\u001F",
    -"output":["ParseError", "ParseError", ["StartTag", "a\u001F", {}]]},
    +{"description":"<a\\u001F>",
    +"input":"<a\u001F>",
    +"output":["ParseError", ["StartTag", "a\u001F", {}]]},
     
    -{"description":"<a ",
    -"input":"<a ",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a >",
    +"input":"<a >",
    +"output":[["StartTag", "a", {}]]},
     
    -{"description":"<a \\u0000",
    -"input":"<a \u0000",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"\uFFFD":""}]]},
    +{"description":"<a \\u0000>",
    +"input":"<a \u0000>",
    +"output":["ParseError", ["StartTag", "a", {"\uFFFD":""}]]},
     
    -{"description":"<a \\u0008",
    -"input":"<a \u0008",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"\u0008":""}]]},
    +{"description":"<a \\u0008>",
    +"input":"<a \u0008>",
    +"output":["ParseError", ["StartTag", "a", {"\u0008":""}]]},
     
    -{"description":"<a \\u0009",
    -"input":"<a \u0009",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a \\u0009>",
    +"input":"<a \u0009>",
    +"output":[["StartTag", "a", {}]]},
     
    -{"description":"<a \\u000A",
    -"input":"<a \u000A",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a \\u000A>",
    +"input":"<a \u000A>",
    +"output":[["StartTag", "a", {}]]},
     
    -{"description":"<a \\u000B",
    -"input":"<a \u000B",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"\u000B":""}]]},
    +{"description":"<a \\u000B>",
    +"input":"<a \u000B>",
    +"output":["ParseError", ["StartTag", "a", {"\u000B":""}]]},
     
    -{"description":"<a \\u000C",
    -"input":"<a \u000C",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a \\u000C>",
    +"input":"<a \u000C>",
    +"output":[["StartTag", "a", {}]]},
     
    -{"description":"<a \\u000D",
    -"input":"<a \u000D",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a \\u000D>",
    +"input":"<a \u000D>",
    +"output":[["StartTag", "a", {}]]},
     
    -{"description":"<a \\u001F",
    -"input":"<a \u001F",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"\u001F":""}]]},
    +{"description":"<a \\u001F>",
    +"input":"<a \u001F>",
    +"output":["ParseError", ["StartTag", "a", {"\u001F":""}]]},
     
    -{"description":"<a  ",
    -"input":"<a  ",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a  >",
    +"input":"<a  >",
    +"output":[["StartTag", "a", {}]]},
     
    -{"description":"<a !",
    -"input":"<a !",
    -"output":["ParseError", ["StartTag", "a", {"!":""}]]},
    +{"description":"<a !>",
    +"input":"<a !>",
    +"output":[["StartTag", "a", {"!":""}]]},
     
    -{"description":"<a \"",
    -"input":"<a \"",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"\"":""}]]},
    +{"description":"<a \">",
    +"input":"<a \">",
    +"output":["ParseError", ["StartTag", "a", {"\"":""}]]},
     
    -{"description":"<a #",
    -"input":"<a #",
    -"output":["ParseError", ["StartTag", "a", {"#":""}]]},
    +{"description":"<a #>",
    +"input":"<a #>",
    +"output":[["StartTag", "a", {"#":""}]]},
     
    -{"description":"<a &",
    -"input":"<a &",
    -"output":["ParseError", ["StartTag", "a", {"&":""}]]},
    +{"description":"<a &>",
    +"input":"<a &>",
    +"output":[["StartTag", "a", {"&":""}]]},
     
    -{"description":"<a '",
    -"input":"<a '",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"'":""}]]},
    +{"description":"<a '>",
    +"input":"<a '>",
    +"output":["ParseError", ["StartTag", "a", {"'":""}]]},
     
    -{"description":"<a (",
    -"input":"<a (",
    -"output":["ParseError", ["StartTag", "a", {"(":""}]]},
    +{"description":"<a (>",
    +"input":"<a (>",
    +"output":[["StartTag", "a", {"(":""}]]},
     
    -{"description":"<a -",
    -"input":"<a -",
    -"output":["ParseError", ["StartTag", "a", {"-":""}]]},
    +{"description":"<a ->",
    +"input":"<a ->",
    +"output":[["StartTag", "a", {"-":""}]]},
     
    -{"description":"<a .",
    -"input":"<a .",
    -"output":["ParseError", ["StartTag", "a", {".":""}]]},
    +{"description":"<a .>",
    +"input":"<a .>",
    +"output":[["StartTag", "a", {".":""}]]},
     
    -{"description":"<a /",
    -"input":"<a /",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a />",
    +"input":"<a />",
    +"output":[["StartTag", "a", {}, true]]},
     
    -{"description":"<a 0",
    -"input":"<a 0",
    -"output":["ParseError", ["StartTag", "a", {"0":""}]]},
    +{"description":"<a 0>",
    +"input":"<a 0>",
    +"output":[["StartTag", "a", {"0":""}]]},
     
    -{"description":"<a 1",
    -"input":"<a 1",
    -"output":["ParseError", ["StartTag", "a", {"1":""}]]},
    +{"description":"<a 1>",
    +"input":"<a 1>",
    +"output":[["StartTag", "a", {"1":""}]]},
     
    -{"description":"<a 9",
    -"input":"<a 9",
    -"output":["ParseError", ["StartTag", "a", {"9":""}]]},
    +{"description":"<a 9>",
    +"input":"<a 9>",
    +"output":[["StartTag", "a", {"9":""}]]},
     
    -{"description":"<a <",
    -"input":"<a <",
    +{"description":"<a <>",
    +"input":"<a <>",
     "output":["ParseError", ["StartTag", "a", {"<":""}]]},
     
    -{"description":"<a =",
    -"input":"<a =",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"=":""}]]},
    +{"description":"<a =>",
    +"input":"<a =>",
    +"output":["ParseError", ["StartTag", "a", {"=":""}]]},
     
     {"description":"<a >",
     "input":"<a >",
     "output":[["StartTag", "a", {}]]},
     
    -{"description":"<a ?",
    -"input":"<a ?",
    -"output":["ParseError", ["StartTag", "a", {"?":""}]]},
    +{"description":"<a ?>",
    +"input":"<a ?>",
    +"output":[["StartTag", "a", {"?":""}]]},
     
    -{"description":"<a @",
    -"input":"<a @",
    -"output":["ParseError", ["StartTag", "a", {"@":""}]]},
    +{"description":"<a @>",
    +"input":"<a @>",
    +"output":[["StartTag", "a", {"@":""}]]},
     
    -{"description":"<a A",
    -"input":"<a A",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a A>",
    +"input":"<a A>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a B",
    -"input":"<a B",
    -"output":["ParseError", ["StartTag", "a", {"b":""}]]},
    +{"description":"<a B>",
    +"input":"<a B>",
    +"output":[["StartTag", "a", {"b":""}]]},
     
    -{"description":"<a Y",
    -"input":"<a Y",
    -"output":["ParseError", ["StartTag", "a", {"y":""}]]},
    +{"description":"<a Y>",
    +"input":"<a Y>",
    +"output":[["StartTag", "a", {"y":""}]]},
     
    -{"description":"<a Z",
    -"input":"<a Z",
    -"output":["ParseError", ["StartTag", "a", {"z":""}]]},
    +{"description":"<a Z>",
    +"input":"<a Z>",
    +"output":[["StartTag", "a", {"z":""}]]},
     
    -{"description":"<a [",
    -"input":"<a [",
    -"output":["ParseError", ["StartTag", "a", {"[":""}]]},
    +{"description":"<a [>",
    +"input":"<a [>",
    +"output":[["StartTag", "a", {"[":""}]]},
     
    -{"description":"<a `",
    -"input":"<a `",
    -"output":["ParseError", ["StartTag", "a", {"`":""}]]},
    +{"description":"<a `>",
    +"input":"<a `>",
    +"output":[["StartTag", "a", {"`":""}]]},
     
    -{"description":"<a a",
    -"input":"<a a",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a>",
    +"input":"<a a>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a\\u0000",
    -"input":"<a a\u0000",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a\uFFFD":""}]]},
    +{"description":"<a a\\u0000>",
    +"input":"<a a\u0000>",
    +"output":["ParseError", ["StartTag", "a", {"a\uFFFD":""}]]},
     
    -{"description":"<a a\\u0008",
    -"input":"<a a\u0008",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a\u0008":""}]]},
    +{"description":"<a a\\u0008>",
    +"input":"<a a\u0008>",
    +"output":["ParseError", ["StartTag", "a", {"a\u0008":""}]]},
     
    -{"description":"<a a\\u0009",
    -"input":"<a a\u0009",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a\\u0009>",
    +"input":"<a a\u0009>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a\\u000A",
    -"input":"<a a\u000A",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a\\u000A>",
    +"input":"<a a\u000A>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a\\u000B",
    -"input":"<a a\u000B",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a\u000B":""}]]},
    +{"description":"<a a\\u000B>",
    +"input":"<a a\u000B>",
    +"output":["ParseError", ["StartTag", "a", {"a\u000B":""}]]},
     
    -{"description":"<a a\\u000C",
    -"input":"<a a\u000C",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a\\u000C>",
    +"input":"<a a\u000C>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a\\u000D",
    -"input":"<a a\u000D",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a\\u000D>",
    +"input":"<a a\u000D>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a\\u001F",
    -"input":"<a a\u001F",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a\u001F":""}]]},
    +{"description":"<a a\\u001F>",
    +"input":"<a a\u001F>",
    +"output":["ParseError", ["StartTag", "a", {"a\u001F":""}]]},
     
    -{"description":"<a a ",
    -"input":"<a a ",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a >",
    +"input":"<a a >",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a \\u0000",
    -"input":"<a a \u0000",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\uFFFD":""}]]},
    +{"description":"<a a \\u0000>",
    +"input":"<a a \u0000>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "\uFFFD":""}]]},
     
    -{"description":"<a a \\u0008",
    -"input":"<a a \u0008",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u0008":""}]]},
    +{"description":"<a a \\u0008>",
    +"input":"<a a \u0008>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "\u0008":""}]]},
     
    -{"description":"<a a \\u0009",
    -"input":"<a a \u0009",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a \\u0009>",
    +"input":"<a a \u0009>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a \\u000A",
    -"input":"<a a \u000A",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a \\u000A>",
    +"input":"<a a \u000A>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a \\u000B",
    -"input":"<a a \u000B",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u000B":""}]]},
    +{"description":"<a a \\u000B>",
    +"input":"<a a \u000B>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "\u000B":""}]]},
     
    -{"description":"<a a \\u000C",
    -"input":"<a a \u000C",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a \\u000C>",
    +"input":"<a a \u000C>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a \\u000D",
    -"input":"<a a \u000D",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a \\u000D>",
    +"input":"<a a \u000D>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a \\u001F",
    -"input":"<a a \u001F",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u001F":""}]]},
    +{"description":"<a a \\u001F>",
    +"input":"<a a \u001F>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "\u001F":""}]]},
     
    -{"description":"<a a  ",
    -"input":"<a a  ",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a  >",
    +"input":"<a a  >",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a !",
    -"input":"<a a !",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "!":""}]]},
    +{"description":"<a a !>",
    +"input":"<a a !>",
    +"output":[["StartTag", "a", {"a":"", "!":""}]]},
     
    -{"description":"<a a \"",
    -"input":"<a a \"",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\"":""}]]},
    +{"description":"<a a \">",
    +"input":"<a a \">",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "\"":""}]]},
     
    -{"description":"<a a #",
    -"input":"<a a #",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "#":""}]]},
    +{"description":"<a a #>",
    +"input":"<a a #>",
    +"output":[["StartTag", "a", {"a":"", "#":""}]]},
     
    -{"description":"<a a &",
    -"input":"<a a &",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "&":""}]]},
    +{"description":"<a a &>",
    +"input":"<a a &>",
    +"output":[["StartTag", "a", {"a":"", "&":""}]]},
     
    -{"description":"<a a '",
    -"input":"<a a '",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "'":""}]]},
    +{"description":"<a a '>",
    +"input":"<a a '>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "'":""}]]},
     
    -{"description":"<a a (",
    -"input":"<a a (",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "(":""}]]},
    +{"description":"<a a (>",
    +"input":"<a a (>",
    +"output":[["StartTag", "a", {"a":"", "(":""}]]},
     
    -{"description":"<a a -",
    -"input":"<a a -",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "-":""}]]},
    +{"description":"<a a ->",
    +"input":"<a a ->",
    +"output":[["StartTag", "a", {"a":"", "-":""}]]},
     
    -{"description":"<a a .",
    -"input":"<a a .",
    -"output":["ParseError", ["StartTag", "a", {"a":"", ".":""}]]},
    +{"description":"<a a .>",
    +"input":"<a a .>",
    +"output":[["StartTag", "a", {"a":"", ".":""}]]},
     
    -{"description":"<a a /",
    -"input":"<a a /",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a />",
    +"input":"<a a />",
    +"output":[["StartTag", "a", {"a":""}, true]]},
     
    -{"description":"<a a 0",
    -"input":"<a a 0",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "0":""}]]},
    +{"description":"<a a 0>",
    +"input":"<a a 0>",
    +"output":[["StartTag", "a", {"a":"", "0":""}]]},
     
    -{"description":"<a a 1",
    -"input":"<a a 1",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "1":""}]]},
    +{"description":"<a a 1>",
    +"input":"<a a 1>",
    +"output":[["StartTag", "a", {"a":"", "1":""}]]},
     
    -{"description":"<a a 9",
    -"input":"<a a 9",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "9":""}]]},
    +{"description":"<a a 9>",
    +"input":"<a a 9>",
    +"output":[["StartTag", "a", {"a":"", "9":""}]]},
     
    -{"description":"<a a <",
    -"input":"<a a <",
    +{"description":"<a a <>",
    +"input":"<a a <>",
     "output":["ParseError", ["StartTag", "a", {"a":"", "<":""}]]},
     
    -{"description":"<a a =",
    -"input":"<a a =",
    +{"description":"<a a =>",
    +"input":"<a a =>",
     "output":["ParseError", ["StartTag", "a", {"a":""}]]},
     
     {"description":"<a a >",
     "input":"<a a >",
     "output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a ?",
    -"input":"<a a ?",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "?":""}]]},
    +{"description":"<a a ?>",
    +"input":"<a a ?>",
    +"output":[["StartTag", "a", {"a":"", "?":""}]]},
     
    -{"description":"<a a @",
    -"input":"<a a @",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "@":""}]]},
    +{"description":"<a a @>",
    +"input":"<a a @>",
    +"output":[["StartTag", "a", {"a":"", "@":""}]]},
     
    -{"description":"<a a A",
    -"input":"<a a A",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a A>",
    +"input":"<a a A>",
    +"output":["ParseError", ["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a B",
    -"input":"<a a B",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "b":""}]]},
    +{"description":"<a a B>",
    +"input":"<a a B>",
    +"output":[["StartTag", "a", {"a":"", "b":""}]]},
     
    -{"description":"<a a Y",
    -"input":"<a a Y",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "y":""}]]},
    +{"description":"<a a Y>",
    +"input":"<a a Y>",
    +"output":[["StartTag", "a", {"a":"", "y":""}]]},
     
    -{"description":"<a a Z",
    -"input":"<a a Z",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "z":""}]]},
    +{"description":"<a a Z>",
    +"input":"<a a Z>",
    +"output":[["StartTag", "a", {"a":"", "z":""}]]},
     
    -{"description":"<a a [",
    -"input":"<a a [",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "[":""}]]},
    +{"description":"<a a [>",
    +"input":"<a a [>",
    +"output":[["StartTag", "a", {"a":"", "[":""}]]},
     
    -{"description":"<a a `",
    -"input":"<a a `",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "`":""}]]},
    +{"description":"<a a `>",
    +"input":"<a a `>",
    +"output":[["StartTag", "a", {"a":"", "`":""}]]},
     
    -{"description":"<a a a",
    -"input":"<a a a",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a a>",
    +"input":"<a a a>",
    +"output":["ParseError", ["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a b",
    -"input":"<a a b",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "b":""}]]},
    +{"description":"<a a b>",
    +"input":"<a a b>",
    +"output":[["StartTag", "a", {"a":"", "b":""}]]},
     
    -{"description":"<a a y",
    -"input":"<a a y",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "y":""}]]},
    +{"description":"<a a y>",
    +"input":"<a a y>",
    +"output":[["StartTag", "a", {"a":"", "y":""}]]},
     
    -{"description":"<a a z",
    -"input":"<a a z",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "z":""}]]},
    +{"description":"<a a z>",
    +"input":"<a a z>",
    +"output":[["StartTag", "a", {"a":"", "z":""}]]},
     
    -{"description":"<a a {",
    -"input":"<a a {",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "{":""}]]},
    +{"description":"<a a {>",
    +"input":"<a a {>",
    +"output":[["StartTag", "a", {"a":"", "{":""}]]},
     
    -{"description":"<a a \\uDBC0\\uDC00",
    -"input":"<a a \uDBC0\uDC00",
    -"output":["ParseError", ["StartTag", "a", {"a":"", "\uDBC0\uDC00":""}]]},
    +{"description":"<a a \\uDBC0\\uDC00>",
    +"input":"<a a \uDBC0\uDC00>",
    +"output":[["StartTag", "a", {"a":"", "\uDBC0\uDC00":""}]]},
     
    -{"description":"<a a!",
    -"input":"<a a!",
    -"output":["ParseError", ["StartTag", "a", {"a!":""}]]},
    +{"description":"<a a!>",
    +"input":"<a a!>",
    +"output":[["StartTag", "a", {"a!":""}]]},
     
    -{"description":"<a a\"",
    -"input":"<a a\"",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a\"":""}]]},
    +{"description":"<a a\">",
    +"input":"<a a\">",
    +"output":["ParseError", ["StartTag", "a", {"a\"":""}]]},
     
    -{"description":"<a a#",
    -"input":"<a a#",
    -"output":["ParseError", ["StartTag", "a", {"a#":""}]]},
    +{"description":"<a a#>",
    +"input":"<a a#>",
    +"output":[["StartTag", "a", {"a#":""}]]},
     
    -{"description":"<a a&",
    -"input":"<a a&",
    -"output":["ParseError", ["StartTag", "a", {"a&":""}]]},
    +{"description":"<a a&>",
    +"input":"<a a&>",
    +"output":[["StartTag", "a", {"a&":""}]]},
     
    -{"description":"<a a'",
    -"input":"<a a'",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a'":""}]]},
    +{"description":"<a a'>",
    +"input":"<a a'>",
    +"output":["ParseError", ["StartTag", "a", {"a'":""}]]},
     
    -{"description":"<a a(",
    -"input":"<a a(",
    -"output":["ParseError", ["StartTag", "a", {"a(":""}]]},
    +{"description":"<a a(>",
    +"input":"<a a(>",
    +"output":[["StartTag", "a", {"a(":""}]]},
     
    -{"description":"<a a-",
    -"input":"<a a-",
    -"output":["ParseError", ["StartTag", "a", {"a-":""}]]},
    +{"description":"<a a->",
    +"input":"<a a->",
    +"output":[["StartTag", "a", {"a-":""}]]},
     
    -{"description":"<a a.",
    -"input":"<a a.",
    -"output":["ParseError", ["StartTag", "a", {"a.":""}]]},
    +{"description":"<a a.>",
    +"input":"<a a.>",
    +"output":[["StartTag", "a", {"a.":""}]]},
     
    -{"description":"<a a/",
    -"input":"<a a/",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a/>",
    +"input":"<a a/>",
    +"output":[["StartTag", "a", {"a":""}, true]]},
     
    -{"description":"<a a0",
    -"input":"<a a0",
    -"output":["ParseError", ["StartTag", "a", {"a0":""}]]},
    +{"description":"<a a0>",
    +"input":"<a a0>",
    +"output":[["StartTag", "a", {"a0":""}]]},
     
    -{"description":"<a a1",
    -"input":"<a a1",
    -"output":["ParseError", ["StartTag", "a", {"a1":""}]]},
    +{"description":"<a a1>",
    +"input":"<a a1>",
    +"output":[["StartTag", "a", {"a1":""}]]},
     
    -{"description":"<a a9",
    -"input":"<a a9",
    -"output":["ParseError", ["StartTag", "a", {"a9":""}]]},
    +{"description":"<a a9>",
    +"input":"<a a9>",
    +"output":[["StartTag", "a", {"a9":""}]]},
     
    -{"description":"<a a<",
    -"input":"<a a<",
    +{"description":"<a a<>",
    +"input":"<a a<>",
     "output":["ParseError", ["StartTag", "a", {"a<":""}]]},
     
    -{"description":"<a a=",
    -"input":"<a a=",
    +{"description":"<a a=>",
    +"input":"<a a=>",
     "output":["ParseError", ["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=\\u0000",
    -"input":"<a a=\u0000",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"\uFFFD"}]]},
    +{"description":"<a a=\\u0000>",
    +"input":"<a a=\u0000>",
    +"output":["ParseError", ["StartTag", "a", {"a":"\uFFFD"}]]},
     
    -{"description":"<a a=\\u0008",
    -"input":"<a a=\u0008",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"\u0008"}]]},
    +{"description":"<a a=\\u0008>",
    +"input":"<a a=\u0008>",
    +"output":["ParseError", ["StartTag", "a", {"a":"\u0008"}]]},
     
    -{"description":"<a a=\\u0009",
    -"input":"<a a=\u0009",
    +{"description":"<a a=\\u0009>",
    +"input":"<a a=\u0009>",
     "output":["ParseError", ["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=\\u000A",
    -"input":"<a a=\u000A",
    +{"description":"<a a=\\u000A>",
    +"input":"<a a=\u000A>",
     "output":["ParseError", ["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=\\u000B",
    -"input":"<a a=\u000B",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"\u000B"}]]},
    +{"description":"<a a=\\u000B>",
    +"input":"<a a=\u000B>",
    +"output":["ParseError", ["StartTag", "a", {"a":"\u000B"}]]},
     
    -{"description":"<a a=\\u000C",
    -"input":"<a a=\u000C",
    +{"description":"<a a=\\u000C>",
    +"input":"<a a=\u000C>",
     "output":["ParseError", ["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=\\u000D",
    -"input":"<a a=\u000D",
    +{"description":"<a a=\\u000D>",
    +"input":"<a a=\u000D>",
     "output":["ParseError", ["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=\\u001F",
    -"input":"<a a=\u001F",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"\u001F"}]]},
    +{"description":"<a a=\\u001F>",
    +"input":"<a a=\u001F>",
    +"output":["ParseError", ["StartTag", "a", {"a":"\u001F"}]]},
     
    -{"description":"<a a= ",
    -"input":"<a a= ",
    +{"description":"<a a= >",
    +"input":"<a a= >",
     "output":["ParseError", ["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=!",
    -"input":"<a a=!",
    -"output":["ParseError", ["StartTag", "a", {"a":"!"}]]},
    +{"description":"<a a=!>",
    +"input":"<a a=!>",
    +"output":[["StartTag", "a", {"a":"!"}]]},
     
    -{"description":"<a a=\"",
    -"input":"<a a=\"",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a=\"\">",
    +"input":"<a a=\"\">",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=\"\\u0000",
    -"input":"<a a=\"\u0000",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"\uFFFD"}]]},
    +{"description":"<a a=\"\\u0000\">",
    +"input":"<a a=\"\u0000\">",
    +"output":["ParseError", ["StartTag", "a", {"a":"\uFFFD"}]]},
     
    -{"description":"<a a=\"\\u0009",
    -"input":"<a a=\"\u0009",
    -"output":["ParseError", ["StartTag", "a", {"a":"\u0009"}]]},
    +{"description":"<a a=\"\\u0009\">",
    +"input":"<a a=\"\u0009\">",
    +"output":[["StartTag", "a", {"a":"\u0009"}]]},
     
    -{"description":"<a a=\"\\u000A",
    -"input":"<a a=\"\u000A",
    -"output":["ParseError", ["StartTag", "a", {"a":"\u000A"}]]},
    +{"description":"<a a=\"\\u000A\">",
    +"input":"<a a=\"\u000A\">",
    +"output":[["StartTag", "a", {"a":"\u000A"}]]},
     
    -{"description":"<a a=\"\\u000B",
    -"input":"<a a=\"\u000B",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"\u000B"}]]},
    +{"description":"<a a=\"\\u000B\">",
    +"input":"<a a=\"\u000B\">",
    +"output":["ParseError", ["StartTag", "a", {"a":"\u000B"}]]},
     
    -{"description":"<a a=\"\\u000C",
    -"input":"<a a=\"\u000C",
    -"output":["ParseError", ["StartTag", "a", {"a":"\u000C"}]]},
    +{"description":"<a a=\"\\u000C\">",
    +"input":"<a a=\"\u000C\">",
    +"output":[["StartTag", "a", {"a":"\u000C"}]]},
     
    -{"description":"<a a=\" ",
    -"input":"<a a=\" ",
    -"output":["ParseError", ["StartTag", "a", {"a":" "}]]},
    +{"description":"<a a=\" \">",
    +"input":"<a a=\" \">",
    +"output":[["StartTag", "a", {"a":" "}]]},
     
    -{"description":"<a a=\"!",
    -"input":"<a a=\"!",
    -"output":["ParseError", ["StartTag", "a", {"a":"!"}]]},
    +{"description":"<a a=\"!\">",
    +"input":"<a a=\"!\">",
    +"output":[["StartTag", "a", {"a":"!"}]]},
     
    -{"description":"<a a=\"\"",
    -"input":"<a a=\"\"",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a=\"\">",
    +"input":"<a a=\"\">",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=\"#",
    -"input":"<a a=\"#",
    -"output":["ParseError", ["StartTag", "a", {"a":"#"}]]},
    +{"description":"<a a=\"#\">",
    +"input":"<a a=\"#\">",
    +"output":[["StartTag", "a", {"a":"#"}]]},
     
    -{"description":"<a a=\"%",
    -"input":"<a a=\"%",
    -"output":["ParseError", ["StartTag", "a", {"a":"%"}]]},
    +{"description":"<a a=\"%\">",
    +"input":"<a a=\"%\">",
    +"output":[["StartTag", "a", {"a":"%"}]]},
     
    -{"description":"<a a=\"&",
    -"input":"<a a=\"&",
    -"output":["ParseError", ["StartTag", "a", {"a":"&"}]]},
    +{"description":"<a a=\"&\">",
    +"input":"<a a=\"&\">",
    +"output":[["StartTag", "a", {"a":"&"}]]},
     
    -{"description":"<a a=\"'",
    -"input":"<a a=\"'",
    -"output":["ParseError", ["StartTag", "a", {"a":"'"}]]},
    +{"description":"<a a=\"'\">",
    +"input":"<a a=\"'\">",
    +"output":[["StartTag", "a", {"a":"'"}]]},
     
    -{"description":"<a a=\"-",
    -"input":"<a a=\"-",
    -"output":["ParseError", ["StartTag", "a", {"a":"-"}]]},
    +{"description":"<a a=\"-\">",
    +"input":"<a a=\"-\">",
    +"output":[["StartTag", "a", {"a":"-"}]]},
     
    -{"description":"<a a=\"/",
    -"input":"<a a=\"/",
    -"output":["ParseError", ["StartTag", "a", {"a":"/"}]]},
    +{"description":"<a a=\"/\">",
    +"input":"<a a=\"/\">",
    +"output":[["StartTag", "a", {"a":"/"}]]},
     
    -{"description":"<a a=\"0",
    -"input":"<a a=\"0",
    -"output":["ParseError", ["StartTag", "a", {"a":"0"}]]},
    +{"description":"<a a=\"0\">",
    +"input":"<a a=\"0\">",
    +"output":[["StartTag", "a", {"a":"0"}]]},
     
    -{"description":"<a a=\"1",
    -"input":"<a a=\"1",
    -"output":["ParseError", ["StartTag", "a", {"a":"1"}]]},
    +{"description":"<a a=\"1\">",
    +"input":"<a a=\"1\">",
    +"output":[["StartTag", "a", {"a":"1"}]]},
     
    -{"description":"<a a=\"9",
    -"input":"<a a=\"9",
    -"output":["ParseError", ["StartTag", "a", {"a":"9"}]]},
    +{"description":"<a a=\"9\">",
    +"input":"<a a=\"9\">",
    +"output":[["StartTag", "a", {"a":"9"}]]},
     
    -{"description":"<a a=\"<",
    -"input":"<a a=\"<",
    -"output":["ParseError", ["StartTag", "a", {"a":"<"}]]},
    +{"description":"<a a=\"<\">",
    +"input":"<a a=\"<\">",
    +"output":[["StartTag", "a", {"a":"<"}]]},
     
    -{"description":"<a a=\"=",
    -"input":"<a a=\"=",
    -"output":["ParseError", ["StartTag", "a", {"a":"="}]]},
    +{"description":"<a a=\"=\">",
    +"input":"<a a=\"=\">",
    +"output":[["StartTag", "a", {"a":"="}]]},
     
    -{"description":"<a a=\">",
    -"input":"<a a=\">",
    -"output":["ParseError", ["StartTag", "a", {"a":">"}]]},
    +{"description":"<a a=\">\">",
    +"input":"<a a=\">\">",
    +"output":[["StartTag", "a", {"a":">"}]]},
     
    -{"description":"<a a=\"?",
    -"input":"<a a=\"?",
    -"output":["ParseError", ["StartTag", "a", {"a":"?"}]]},
    +{"description":"<a a=\"?\">",
    +"input":"<a a=\"?\">",
    +"output":[["StartTag", "a", {"a":"?"}]]},
     
    -{"description":"<a a=\"@",
    -"input":"<a a=\"@",
    -"output":["ParseError", ["StartTag", "a", {"a":"@"}]]},
    +{"description":"<a a=\"@\">",
    +"input":"<a a=\"@\">",
    +"output":[["StartTag", "a", {"a":"@"}]]},
     
    -{"description":"<a a=\"A",
    -"input":"<a a=\"A",
    -"output":["ParseError", ["StartTag", "a", {"a":"A"}]]},
    +{"description":"<a a=\"A\">",
    +"input":"<a a=\"A\">",
    +"output":[["StartTag", "a", {"a":"A"}]]},
     
    -{"description":"<a a=\"B",
    -"input":"<a a=\"B",
    -"output":["ParseError", ["StartTag", "a", {"a":"B"}]]},
    +{"description":"<a a=\"B\">",
    +"input":"<a a=\"B\">",
    +"output":[["StartTag", "a", {"a":"B"}]]},
     
    -{"description":"<a a=\"Y",
    -"input":"<a a=\"Y",
    -"output":["ParseError", ["StartTag", "a", {"a":"Y"}]]},
    +{"description":"<a a=\"Y\">",
    +"input":"<a a=\"Y\">",
    +"output":[["StartTag", "a", {"a":"Y"}]]},
     
    -{"description":"<a a=\"Z",
    -"input":"<a a=\"Z",
    -"output":["ParseError", ["StartTag", "a", {"a":"Z"}]]},
    +{"description":"<a a=\"Z\">",
    +"input":"<a a=\"Z\">",
    +"output":[["StartTag", "a", {"a":"Z"}]]},
     
    -{"description":"<a a=\"`",
    -"input":"<a a=\"`",
    -"output":["ParseError", ["StartTag", "a", {"a":"`"}]]},
    +{"description":"<a a=\"`\">",
    +"input":"<a a=\"`\">",
    +"output":[["StartTag", "a", {"a":"`"}]]},
     
    -{"description":"<a a=\"a",
    -"input":"<a a=\"a",
    -"output":["ParseError", ["StartTag", "a", {"a":"a"}]]},
    +{"description":"<a a=\"a\">",
    +"input":"<a a=\"a\">",
    +"output":[["StartTag", "a", {"a":"a"}]]},
     
    -{"description":"<a a=\"b",
    -"input":"<a a=\"b",
    -"output":["ParseError", ["StartTag", "a", {"a":"b"}]]},
    +{"description":"<a a=\"b\">",
    +"input":"<a a=\"b\">",
    +"output":[["StartTag", "a", {"a":"b"}]]},
     
    -{"description":"<a a=\"y",
    -"input":"<a a=\"y",
    -"output":["ParseError", ["StartTag", "a", {"a":"y"}]]},
    +{"description":"<a a=\"y\">",
    +"input":"<a a=\"y\">",
    +"output":[["StartTag", "a", {"a":"y"}]]},
     
    -{"description":"<a a=\"z",
    -"input":"<a a=\"z",
    -"output":["ParseError", ["StartTag", "a", {"a":"z"}]]},
    +{"description":"<a a=\"z\">",
    +"input":"<a a=\"z\">",
    +"output":[["StartTag", "a", {"a":"z"}]]},
     
    -{"description":"<a a=\"{",
    -"input":"<a a=\"{",
    -"output":["ParseError", ["StartTag", "a", {"a":"{"}]]},
    +{"description":"<a a=\"{\">",
    +"input":"<a a=\"{\">",
    +"output":[["StartTag", "a", {"a":"{"}]]},
     
    -{"description":"<a a=\"\\uDBC0\\uDC00",
    -"input":"<a a=\"\uDBC0\uDC00",
    -"output":["ParseError", ["StartTag", "a", {"a":"\uDBC0\uDC00"}]]},
    +{"description":"<a a=\"\\uDBC0\\uDC00\">",
    +"input":"<a a=\"\uDBC0\uDC00\">",
    +"output":[["StartTag", "a", {"a":"\uDBC0\uDC00"}]]},
     
    -{"description":"<a a=#",
    -"input":"<a a=#",
    -"output":["ParseError", ["StartTag", "a", {"a":"#"}]]},
    +{"description":"<a a=#>",
    +"input":"<a a=#>",
    +"output":[["StartTag", "a", {"a":"#"}]]},
     
    -{"description":"<a a=%",
    -"input":"<a a=%",
    -"output":["ParseError", ["StartTag", "a", {"a":"%"}]]},
    +{"description":"<a a=%>",
    +"input":"<a a=%>",
    +"output":[["StartTag", "a", {"a":"%"}]]},
     
    -{"description":"<a a=&",
    -"input":"<a a=&",
    -"output":["ParseError", ["StartTag", "a", {"a":"&"}]]},
    +{"description":"<a a=&>",
    +"input":"<a a=&>",
    +"output":[["StartTag", "a", {"a":"&"}]]},
     
    -{"description":"<a a='",
    -"input":"<a a='",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a=''>",
    +"input":"<a a=''>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a='\\u0000",
    -"input":"<a a='\u0000",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"\uFFFD"}]]},
    +{"description":"<a a='\\u0000'>",
    +"input":"<a a='\u0000'>",
    +"output":["ParseError", ["StartTag", "a", {"a":"\uFFFD"}]]},
     
    -{"description":"<a a='\\u0009",
    -"input":"<a a='\u0009",
    -"output":["ParseError", ["StartTag", "a", {"a":"\u0009"}]]},
    +{"description":"<a a='\\u0009'>",
    +"input":"<a a='\u0009'>",
    +"output":[["StartTag", "a", {"a":"\u0009"}]]},
     
    -{"description":"<a a='\\u000A",
    -"input":"<a a='\u000A",
    -"output":["ParseError", ["StartTag", "a", {"a":"\u000A"}]]},
    +{"description":"<a a='\\u000A'>",
    +"input":"<a a='\u000A'>",
    +"output":[["StartTag", "a", {"a":"\u000A"}]]},
     
    -{"description":"<a a='\\u000B",
    -"input":"<a a='\u000B",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"\u000B"}]]},
    +{"description":"<a a='\\u000B'>",
    +"input":"<a a='\u000B'>",
    +"output":["ParseError", ["StartTag", "a", {"a":"\u000B"}]]},
     
    -{"description":"<a a='\\u000C",
    -"input":"<a a='\u000C",
    -"output":["ParseError", ["StartTag", "a", {"a":"\u000C"}]]},
    +{"description":"<a a='\\u000C'>",
    +"input":"<a a='\u000C'>",
    +"output":[["StartTag", "a", {"a":"\u000C"}]]},
     
    -{"description":"<a a=' ",
    -"input":"<a a=' ",
    -"output":["ParseError", ["StartTag", "a", {"a":" "}]]},
    +{"description":"<a a=' '>",
    +"input":"<a a=' '>",
    +"output":[["StartTag", "a", {"a":" "}]]},
     
    -{"description":"<a a='!",
    -"input":"<a a='!",
    -"output":["ParseError", ["StartTag", "a", {"a":"!"}]]},
    +{"description":"<a a='!'>",
    +"input":"<a a='!'>",
    +"output":[["StartTag", "a", {"a":"!"}]]},
     
    -{"description":"<a a='\"",
    -"input":"<a a='\"",
    -"output":["ParseError", ["StartTag", "a", {"a":"\""}]]},
    +{"description":"<a a='\"'>",
    +"input":"<a a='\"'>",
    +"output":[["StartTag", "a", {"a":"\""}]]},
     
    -{"description":"<a a='%",
    -"input":"<a a='%",
    -"output":["ParseError", ["StartTag", "a", {"a":"%"}]]},
    +{"description":"<a a='%'>",
    +"input":"<a a='%'>",
    +"output":[["StartTag", "a", {"a":"%"}]]},
     
    -{"description":"<a a='&",
    -"input":"<a a='&",
    -"output":["ParseError", ["StartTag", "a", {"a":"&"}]]},
    +{"description":"<a a='&'>",
    +"input":"<a a='&'>",
    +"output":[["StartTag", "a", {"a":"&"}]]},
     
    -{"description":"<a a=''",
    -"input":"<a a=''",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a=''>",
    +"input":"<a a=''>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=''\\u0000",
    -"input":"<a a=''\u0000",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"a":"", "\uFFFD":""}]]},
    +{"description":"<a a=''\\u0000>",
    +"input":"<a a=''\u0000>",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\uFFFD":""}]]},
     
    -{"description":"<a a=''\\u0008",
    -"input":"<a a=''\u0008",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u0008":""}]]},
    +{"description":"<a a=''\\u0008>",
    +"input":"<a a=''\u0008>",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u0008":""}]]},
     
    -{"description":"<a a=''\\u0009",
    -"input":"<a a=''\u0009",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a=''\\u0009>",
    +"input":"<a a=''\u0009>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=''\\u000A",
    -"input":"<a a=''\u000A",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a=''\\u000A>",
    +"input":"<a a=''\u000A>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=''\\u000B",
    -"input":"<a a=''\u000B",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u000B":""}]]},
    +{"description":"<a a=''\\u000B>",
    +"input":"<a a=''\u000B>",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u000B":""}]]},
     
    -{"description":"<a a=''\\u000C",
    -"input":"<a a=''\u000C",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a=''\\u000C>",
    +"input":"<a a=''\u000C>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=''\\u000D",
    -"input":"<a a=''\u000D",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a=''\\u000D>",
    +"input":"<a a=''\u000D>",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=''\\u001F",
    -"input":"<a a=''\u001F",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u001F":""}]]},
    +{"description":"<a a=''\\u001F>",
    +"input":"<a a=''\u001F>",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u001F":""}]]},
     
    -{"description":"<a a='' ",
    -"input":"<a a='' ",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a='' >",
    +"input":"<a a='' >",
    +"output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=''!",
    -"input":"<a a=''!",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "!":""}]]},
    +{"description":"<a a=''!>",
    +"input":"<a a=''!>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "!":""}]]},
     
    -{"description":"<a a=''\"",
    -"input":"<a a=''\"",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"a":"", "\"":""}]]},
    +{"description":"<a a=''\">",
    +"input":"<a a=''\">",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\"":""}]]},
     
    -{"description":"<a a=''&",
    -"input":"<a a=''&",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "&":""}]]},
    +{"description":"<a a=''&>",
    +"input":"<a a=''&>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "&":""}]]},
     
    -{"description":"<a a='''",
    -"input":"<a a='''",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"a":"", "'":""}]]},
    +{"description":"<a a='''>",
    +"input":"<a a='''>",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "'":""}]]},
     
    -{"description":"<a a=''-",
    -"input":"<a a=''-",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "-":""}]]},
    +{"description":"<a a=''->",
    +"input":"<a a=''->",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "-":""}]]},
     
    -{"description":"<a a=''.",
    -"input":"<a a=''.",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", ".":""}]]},
    +{"description":"<a a=''.>",
    +"input":"<a a=''.>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", ".":""}]]},
     
    -{"description":"<a a=''/",
    -"input":"<a a=''/",
    -"output":["ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a=''/>",
    +"input":"<a a=''/>",
    +"output":[["StartTag", "a", {"a":""}, true]]},
     
    -{"description":"<a a=''0",
    -"input":"<a a=''0",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "0":""}]]},
    +{"description":"<a a=''0>",
    +"input":"<a a=''0>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "0":""}]]},
     
    -{"description":"<a a=''1",
    -"input":"<a a=''1",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "1":""}]]},
    +{"description":"<a a=''1>",
    +"input":"<a a=''1>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "1":""}]]},
     
    -{"description":"<a a=''9",
    -"input":"<a a=''9",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "9":""}]]},
    +{"description":"<a a=''9>",
    +"input":"<a a=''9>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "9":""}]]},
     
    -{"description":"<a a=''<",
    -"input":"<a a=''<",
    +{"description":"<a a=''<>",
    +"input":"<a a=''<>",
     "output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "<":""}]]},
     
    -{"description":"<a a=''=",
    -"input":"<a a=''=",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"a":"", "=":""}]]},
    +{"description":"<a a=''=>",
    +"input":"<a a=''=>",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "=":""}]]},
     
     {"description":"<a a=''>",
     "input":"<a a=''>",
     "output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=''?",
    -"input":"<a a=''?",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "?":""}]]},
    +{"description":"<a a=''?>",
    +"input":"<a a=''?>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "?":""}]]},
     
    -{"description":"<a a=''@",
    -"input":"<a a=''@",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "@":""}]]},
    +{"description":"<a a=''@>",
    +"input":"<a a=''@>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "@":""}]]},
     
    -{"description":"<a a=''A",
    -"input":"<a a=''A",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a=''A>",
    +"input":"<a a=''A>",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=''B",
    -"input":"<a a=''B",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "b":""}]]},
    +{"description":"<a a=''B>",
    +"input":"<a a=''B>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "b":""}]]},
     
    -{"description":"<a a=''Y",
    -"input":"<a a=''Y",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "y":""}]]},
    +{"description":"<a a=''Y>",
    +"input":"<a a=''Y>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "y":""}]]},
     
    -{"description":"<a a=''Z",
    -"input":"<a a=''Z",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "z":""}]]},
    +{"description":"<a a=''Z>",
    +"input":"<a a=''Z>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "z":""}]]},
     
    -{"description":"<a a=''`",
    -"input":"<a a=''`",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "`":""}]]},
    +{"description":"<a a=''`>",
    +"input":"<a a=''`>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "`":""}]]},
     
    -{"description":"<a a=''a",
    -"input":"<a a=''a",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a a=''a>",
    +"input":"<a a=''a>",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=''b",
    -"input":"<a a=''b",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "b":""}]]},
    +{"description":"<a a=''b>",
    +"input":"<a a=''b>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "b":""}]]},
     
    -{"description":"<a a=''y",
    -"input":"<a a=''y",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "y":""}]]},
    +{"description":"<a a=''y>",
    +"input":"<a a=''y>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "y":""}]]},
     
    -{"description":"<a a=''z",
    -"input":"<a a=''z",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "z":""}]]},
    +{"description":"<a a=''z>",
    +"input":"<a a=''z>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "z":""}]]},
     
    -{"description":"<a a=''{",
    -"input":"<a a=''{",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "{":""}]]},
    +{"description":"<a a=''{>",
    +"input":"<a a=''{>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "{":""}]]},
     
    -{"description":"<a a=''\\uDBC0\\uDC00",
    -"input":"<a a=''\uDBC0\uDC00",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\uDBC0\uDC00":""}]]},
    +{"description":"<a a=''\\uDBC0\\uDC00>",
    +"input":"<a a=''\uDBC0\uDC00>",
    +"output":["ParseError", ["StartTag", "a", {"a":"", "\uDBC0\uDC00":""}]]},
     
    -{"description":"<a a='(",
    -"input":"<a a='(",
    -"output":["ParseError", ["StartTag", "a", {"a":"("}]]},
    +{"description":"<a a='('>",
    +"input":"<a a='('>",
    +"output":[["StartTag", "a", {"a":"("}]]},
     
    -{"description":"<a a='-",
    -"input":"<a a='-",
    -"output":["ParseError", ["StartTag", "a", {"a":"-"}]]},
    +{"description":"<a a='-'>",
    +"input":"<a a='-'>",
    +"output":[["StartTag", "a", {"a":"-"}]]},
     
    -{"description":"<a a='/",
    -"input":"<a a='/",
    -"output":["ParseError", ["StartTag", "a", {"a":"/"}]]},
    +{"description":"<a a='/'>",
    +"input":"<a a='/'>",
    +"output":[["StartTag", "a", {"a":"/"}]]},
     
    -{"description":"<a a='0",
    -"input":"<a a='0",
    -"output":["ParseError", ["StartTag", "a", {"a":"0"}]]},
    +{"description":"<a a='0'>",
    +"input":"<a a='0'>",
    +"output":[["StartTag", "a", {"a":"0"}]]},
     
    -{"description":"<a a='1",
    -"input":"<a a='1",
    -"output":["ParseError", ["StartTag", "a", {"a":"1"}]]},
    +{"description":"<a a='1'>",
    +"input":"<a a='1'>",
    +"output":[["StartTag", "a", {"a":"1"}]]},
     
    -{"description":"<a a='9",
    -"input":"<a a='9",
    -"output":["ParseError", ["StartTag", "a", {"a":"9"}]]},
    +{"description":"<a a='9'>",
    +"input":"<a a='9'>",
    +"output":[["StartTag", "a", {"a":"9"}]]},
     
    -{"description":"<a a='<",
    -"input":"<a a='<",
    -"output":["ParseError", ["StartTag", "a", {"a":"<"}]]},
    +{"description":"<a a='<'>",
    +"input":"<a a='<'>",
    +"output":[["StartTag", "a", {"a":"<"}]]},
     
    -{"description":"<a a='=",
    -"input":"<a a='=",
    -"output":["ParseError", ["StartTag", "a", {"a":"="}]]},
    +{"description":"<a a='='>",
    +"input":"<a a='='>",
    +"output":[["StartTag", "a", {"a":"="}]]},
     
    -{"description":"<a a='>",
    -"input":"<a a='>",
    -"output":["ParseError", ["StartTag", "a", {"a":">"}]]},
    +{"description":"<a a='>'>",
    +"input":"<a a='>'>",
    +"output":[["StartTag", "a", {"a":">"}]]},
     
    -{"description":"<a a='?",
    -"input":"<a a='?",
    -"output":["ParseError", ["StartTag", "a", {"a":"?"}]]},
    +{"description":"<a a='?'>",
    +"input":"<a a='?'>",
    +"output":[["StartTag", "a", {"a":"?"}]]},
     
    -{"description":"<a a='@",
    -"input":"<a a='@",
    -"output":["ParseError", ["StartTag", "a", {"a":"@"}]]},
    +{"description":"<a a='@'>",
    +"input":"<a a='@'>",
    +"output":[["StartTag", "a", {"a":"@"}]]},
     
    -{"description":"<a a='A",
    -"input":"<a a='A",
    -"output":["ParseError", ["StartTag", "a", {"a":"A"}]]},
    +{"description":"<a a='A'>",
    +"input":"<a a='A'>",
    +"output":[["StartTag", "a", {"a":"A"}]]},
     
    -{"description":"<a a='B",
    -"input":"<a a='B",
    -"output":["ParseError", ["StartTag", "a", {"a":"B"}]]},
    +{"description":"<a a='B'>",
    +"input":"<a a='B'>",
    +"output":[["StartTag", "a", {"a":"B"}]]},
     
    -{"description":"<a a='Y",
    -"input":"<a a='Y",
    -"output":["ParseError", ["StartTag", "a", {"a":"Y"}]]},
    +{"description":"<a a='Y'>",
    +"input":"<a a='Y'>",
    +"output":[["StartTag", "a", {"a":"Y"}]]},
     
    -{"description":"<a a='Z",
    -"input":"<a a='Z",
    -"output":["ParseError", ["StartTag", "a", {"a":"Z"}]]},
    +{"description":"<a a='Z'>",
    +"input":"<a a='Z'>",
    +"output":[["StartTag", "a", {"a":"Z"}]]},
     
    -{"description":"<a a='`",
    -"input":"<a a='`",
    -"output":["ParseError", ["StartTag", "a", {"a":"`"}]]},
    +{"description":"<a a='`'>",
    +"input":"<a a='`'>",
    +"output":[["StartTag", "a", {"a":"`"}]]},
     
    -{"description":"<a a='a",
    -"input":"<a a='a",
    -"output":["ParseError", ["StartTag", "a", {"a":"a"}]]},
    +{"description":"<a a='a'>",
    +"input":"<a a='a'>",
    +"output":[["StartTag", "a", {"a":"a"}]]},
     
    -{"description":"<a a='b",
    -"input":"<a a='b",
    -"output":["ParseError", ["StartTag", "a", {"a":"b"}]]},
    +{"description":"<a a='b'>",
    +"input":"<a a='b'>",
    +"output":[["StartTag", "a", {"a":"b"}]]},
     
    -{"description":"<a a='y",
    -"input":"<a a='y",
    -"output":["ParseError", ["StartTag", "a", {"a":"y"}]]},
    +{"description":"<a a='y'>",
    +"input":"<a a='y'>",
    +"output":[["StartTag", "a", {"a":"y"}]]},
     
    -{"description":"<a a='z",
    -"input":"<a a='z",
    -"output":["ParseError", ["StartTag", "a", {"a":"z"}]]},
    +{"description":"<a a='z'>",
    +"input":"<a a='z'>",
    +"output":[["StartTag", "a", {"a":"z"}]]},
     
    -{"description":"<a a='{",
    -"input":"<a a='{",
    -"output":["ParseError", ["StartTag", "a", {"a":"{"}]]},
    +{"description":"<a a='{'>",
    +"input":"<a a='{'>",
    +"output":[["StartTag", "a", {"a":"{"}]]},
     
    -{"description":"<a a='\\uDBC0\\uDC00",
    -"input":"<a a='\uDBC0\uDC00",
    -"output":["ParseError", ["StartTag", "a", {"a":"\uDBC0\uDC00"}]]},
    +{"description":"<a a='\\uDBC0\\uDC00'>",
    +"input":"<a a='\uDBC0\uDC00'>",
    +"output":[["StartTag", "a", {"a":"\uDBC0\uDC00"}]]},
     
    -{"description":"<a a=(",
    -"input":"<a a=(",
    -"output":["ParseError", ["StartTag", "a", {"a":"("}]]},
    +{"description":"<a a=(>",
    +"input":"<a a=(>",
    +"output":[["StartTag", "a", {"a":"("}]]},
     
    -{"description":"<a a=-",
    -"input":"<a a=-",
    -"output":["ParseError", ["StartTag", "a", {"a":"-"}]]},
    +{"description":"<a a=->",
    +"input":"<a a=->",
    +"output":[["StartTag", "a", {"a":"-"}]]},
     
    -{"description":"<a a=/",
    -"input":"<a a=/",
    -"output":["ParseError", ["StartTag", "a", {"a":"/"}]]},
    +{"description":"<a a=/>",
    +"input":"<a a=/>",
    +"output":[["StartTag", "a", {"a":"/"}]]},
     
    -{"description":"<a a=0",
    -"input":"<a a=0",
    -"output":["ParseError", ["StartTag", "a", {"a":"0"}]]},
    +{"description":"<a a=0>",
    +"input":"<a a=0>",
    +"output":[["StartTag", "a", {"a":"0"}]]},
     
    -{"description":"<a a=1",
    -"input":"<a a=1",
    -"output":["ParseError", ["StartTag", "a", {"a":"1"}]]},
    +{"description":"<a a=1>",
    +"input":"<a a=1>",
    +"output":[["StartTag", "a", {"a":"1"}]]},
     
    -{"description":"<a a=9",
    -"input":"<a a=9",
    -"output":["ParseError", ["StartTag", "a", {"a":"9"}]]},
    +{"description":"<a a=9>",
    +"input":"<a a=9>",
    +"output":[["StartTag", "a", {"a":"9"}]]},
     
    -{"description":"<a a=<",
    -"input":"<a a=<",
    +{"description":"<a a=<>",
    +"input":"<a a=<>",
     "output":["ParseError", ["StartTag", "a", {"a":"<"}]]},
     
    -{"description":"<a a==",
    -"input":"<a a==",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"="}]]},
    +{"description":"<a a==>",
    +"input":"<a a==>",
    +"output":["ParseError", ["StartTag", "a", {"a":"="}]]},
     
     {"description":"<a a=>",
     "input":"<a a=>",
     "output":["ParseError", ["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a=?",
    -"input":"<a a=?",
    -"output":["ParseError", ["StartTag", "a", {"a":"?"}]]},
    +{"description":"<a a=?>",
    +"input":"<a a=?>",
    +"output":[["StartTag", "a", {"a":"?"}]]},
     
    -{"description":"<a a=@",
    -"input":"<a a=@",
    -"output":["ParseError", ["StartTag", "a", {"a":"@"}]]},
    +{"description":"<a a=@>",
    +"input":"<a a=@>",
    +"output":[["StartTag", "a", {"a":"@"}]]},
     
    -{"description":"<a a=A",
    -"input":"<a a=A",
    -"output":["ParseError", ["StartTag", "a", {"a":"A"}]]},
    +{"description":"<a a=A>",
    +"input":"<a a=A>",
    +"output":[["StartTag", "a", {"a":"A"}]]},
     
    -{"description":"<a a=B",
    -"input":"<a a=B",
    -"output":["ParseError", ["StartTag", "a", {"a":"B"}]]},
    +{"description":"<a a=B>",
    +"input":"<a a=B>",
    +"output":[["StartTag", "a", {"a":"B"}]]},
     
    -{"description":"<a a=Y",
    -"input":"<a a=Y",
    -"output":["ParseError", ["StartTag", "a", {"a":"Y"}]]},
    +{"description":"<a a=Y>",
    +"input":"<a a=Y>",
    +"output":[["StartTag", "a", {"a":"Y"}]]},
     
    -{"description":"<a a=Z",
    -"input":"<a a=Z",
    -"output":["ParseError", ["StartTag", "a", {"a":"Z"}]]},
    +{"description":"<a a=Z>",
    +"input":"<a a=Z>",
    +"output":[["StartTag", "a", {"a":"Z"}]]},
     
    -{"description":"<a a=`",
    -"input":"<a a=`",
    +{"description":"<a a=`>",
    +"input":"<a a=`>",
     "output":["ParseError", ["StartTag", "a", {"a":"`"}]]},
     
    -{"description":"<a a=a",
    -"input":"<a a=a",
    -"output":["ParseError", ["StartTag", "a", {"a":"a"}]]},
    +{"description":"<a a=a>",
    +"input":"<a a=a>",
    +"output":[["StartTag", "a", {"a":"a"}]]},
     
    -{"description":"<a a=a\\u0000",
    -"input":"<a a=a\u0000",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"a\uFFFD"}]]},
    +{"description":"<a a=a\\u0000>",
    +"input":"<a a=a\u0000>",
    +"output":["ParseError", ["StartTag", "a", {"a":"a\uFFFD"}]]},
     
    -{"description":"<a a=a\\u0008",
    -"input":"<a a=a\u0008",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"a\u0008"}]]},
    +{"description":"<a a=a\\u0008>",
    +"input":"<a a=a\u0008>",
    +"output":["ParseError", ["StartTag", "a", {"a":"a\u0008"}]]},
     
    -{"description":"<a a=a\\u0009",
    -"input":"<a a=a\u0009",
    -"output":["ParseError", ["StartTag", "a", {"a":"a"}]]},
    +{"description":"<a a=a\\u0009>",
    +"input":"<a a=a\u0009>",
    +"output":[["StartTag", "a", {"a":"a"}]]},
     
    -{"description":"<a a=a\\u000A",
    -"input":"<a a=a\u000A",
    -"output":["ParseError", ["StartTag", "a", {"a":"a"}]]},
    +{"description":"<a a=a\\u000A>",
    +"input":"<a a=a\u000A>",
    +"output":[["StartTag", "a", {"a":"a"}]]},
     
    -{"description":"<a a=a\\u000B",
    -"input":"<a a=a\u000B",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"a\u000B"}]]},
    +{"description":"<a a=a\\u000B>",
    +"input":"<a a=a\u000B>",
    +"output":["ParseError", ["StartTag", "a", {"a":"a\u000B"}]]},
     
    -{"description":"<a a=a\\u000C",
    -"input":"<a a=a\u000C",
    -"output":["ParseError", ["StartTag", "a", {"a":"a"}]]},
    +{"description":"<a a=a\\u000C>",
    +"input":"<a a=a\u000C>",
    +"output":[["StartTag", "a", {"a":"a"}]]},
     
    -{"description":"<a a=a\\u000D",
    -"input":"<a a=a\u000D",
    -"output":["ParseError", ["StartTag", "a", {"a":"a"}]]},
    +{"description":"<a a=a\\u000D>",
    +"input":"<a a=a\u000D>",
    +"output":[["StartTag", "a", {"a":"a"}]]},
     
    -{"description":"<a a=a\\u001F",
    -"input":"<a a=a\u001F",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"a\u001F"}]]},
    +{"description":"<a a=a\\u001F>",
    +"input":"<a a=a\u001F>",
    +"output":["ParseError", ["StartTag", "a", {"a":"a\u001F"}]]},
     
    -{"description":"<a a=a ",
    -"input":"<a a=a ",
    -"output":["ParseError", ["StartTag", "a", {"a":"a"}]]},
    +{"description":"<a a=a >",
    +"input":"<a a=a >",
    +"output":[["StartTag", "a", {"a":"a"}]]},
     
    -{"description":"<a a=a!",
    -"input":"<a a=a!",
    -"output":["ParseError", ["StartTag", "a", {"a":"a!"}]]},
    +{"description":"<a a=a!>",
    +"input":"<a a=a!>",
    +"output":[["StartTag", "a", {"a":"a!"}]]},
     
    -{"description":"<a a=a\"",
    -"input":"<a a=a\"",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"a\""}]]},
    +{"description":"<a a=a\">",
    +"input":"<a a=a\">",
    +"output":["ParseError", ["StartTag", "a", {"a":"a\""}]]},
     
    -{"description":"<a a=a#",
    -"input":"<a a=a#",
    -"output":["ParseError", ["StartTag", "a", {"a":"a#"}]]},
    +{"description":"<a a=a#>",
    +"input":"<a a=a#>",
    +"output":[["StartTag", "a", {"a":"a#"}]]},
     
    -{"description":"<a a=a%",
    -"input":"<a a=a%",
    -"output":["ParseError", ["StartTag", "a", {"a":"a%"}]]},
    +{"description":"<a a=a%>",
    +"input":"<a a=a%>",
    +"output":[["StartTag", "a", {"a":"a%"}]]},
     
    -{"description":"<a a=a&",
    -"input":"<a a=a&",
    -"output":["ParseError", ["StartTag", "a", {"a":"a&"}]]},
    +{"description":"<a a=a&>",
    +"input":"<a a=a&>",
    +"output":[["StartTag", "a", {"a":"a&"}]]},
     
    -{"description":"<a a=a'",
    -"input":"<a a=a'",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"a'"}]]},
    +{"description":"<a a=a'>",
    +"input":"<a a=a'>",
    +"output":["ParseError", ["StartTag", "a", {"a":"a'"}]]},
     
    -{"description":"<a a=a(",
    -"input":"<a a=a(",
    -"output":["ParseError", ["StartTag", "a", {"a":"a("}]]},
    +{"description":"<a a=a(>",
    +"input":"<a a=a(>",
    +"output":[["StartTag", "a", {"a":"a("}]]},
     
    -{"description":"<a a=a-",
    -"input":"<a a=a-",
    -"output":["ParseError", ["StartTag", "a", {"a":"a-"}]]},
    +{"description":"<a a=a->",
    +"input":"<a a=a->",
    +"output":[["StartTag", "a", {"a":"a-"}]]},
     
    -{"description":"<a a=a/",
    -"input":"<a a=a/",
    -"output":["ParseError", ["StartTag", "a", {"a":"a/"}]]},
    +{"description":"<a a=a/>",
    +"input":"<a a=a/>",
    +"output":[["StartTag", "a", {"a":"a/"}]]},
     
    -{"description":"<a a=a0",
    -"input":"<a a=a0",
    -"output":["ParseError", ["StartTag", "a", {"a":"a0"}]]},
    +{"description":"<a a=a0>",
    +"input":"<a a=a0>",
    +"output":[["StartTag", "a", {"a":"a0"}]]},
     
    -{"description":"<a a=a1",
    -"input":"<a a=a1",
    -"output":["ParseError", ["StartTag", "a", {"a":"a1"}]]},
    +{"description":"<a a=a1>",
    +"input":"<a a=a1>",
    +"output":[["StartTag", "a", {"a":"a1"}]]},
     
    -{"description":"<a a=a9",
    -"input":"<a a=a9",
    -"output":["ParseError", ["StartTag", "a", {"a":"a9"}]]},
    +{"description":"<a a=a9>",
    +"input":"<a a=a9>",
    +"output":[["StartTag", "a", {"a":"a9"}]]},
     
    -{"description":"<a a=a<",
    -"input":"<a a=a<",
    +{"description":"<a a=a<>",
    +"input":"<a a=a<>",
     "output":["ParseError", ["StartTag", "a", {"a":"a<"}]]},
     
    -{"description":"<a a=a=",
    -"input":"<a a=a=",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"a="}]]},
    +{"description":"<a a=a=>",
    +"input":"<a a=a=>",
    +"output":["ParseError", ["StartTag", "a", {"a":"a="}]]},
     
     {"description":"<a a=a>",
     "input":"<a a=a>",
     "output":[["StartTag", "a", {"a":"a"}]]},
     
    -{"description":"<a a=a?",
    -"input":"<a a=a?",
    -"output":["ParseError", ["StartTag", "a", {"a":"a?"}]]},
    +{"description":"<a a=a?>",
    +"input":"<a a=a?>",
    +"output":[["StartTag", "a", {"a":"a?"}]]},
     
    -{"description":"<a a=a@",
    -"input":"<a a=a@",
    -"output":["ParseError", ["StartTag", "a", {"a":"a@"}]]},
    +{"description":"<a a=a@>",
    +"input":"<a a=a@>",
    +"output":[["StartTag", "a", {"a":"a@"}]]},
     
    -{"description":"<a a=aA",
    -"input":"<a a=aA",
    -"output":["ParseError", ["StartTag", "a", {"a":"aA"}]]},
    +{"description":"<a a=aA>",
    +"input":"<a a=aA>",
    +"output":[["StartTag", "a", {"a":"aA"}]]},
     
    -{"description":"<a a=aB",
    -"input":"<a a=aB",
    -"output":["ParseError", ["StartTag", "a", {"a":"aB"}]]},
    +{"description":"<a a=aB>",
    +"input":"<a a=aB>",
    +"output":[["StartTag", "a", {"a":"aB"}]]},
     
    -{"description":"<a a=aY",
    -"input":"<a a=aY",
    -"output":["ParseError", ["StartTag", "a", {"a":"aY"}]]},
    +{"description":"<a a=aY>",
    +"input":"<a a=aY>",
    +"output":[["StartTag", "a", {"a":"aY"}]]},
     
    -{"description":"<a a=aZ",
    -"input":"<a a=aZ",
    -"output":["ParseError", ["StartTag", "a", {"a":"aZ"}]]},
    +{"description":"<a a=aZ>",
    +"input":"<a a=aZ>",
    +"output":[["StartTag", "a", {"a":"aZ"}]]},
     
    -{"description":"<a a=a`",
    -"input":"<a a=a`",
    +{"description":"<a a=a`>",
    +"input":"<a a=a`>",
     "output":["ParseError", ["StartTag", "a", {"a":"a`"}]]},
     
    -{"description":"<a a=aa",
    -"input":"<a a=aa",
    -"output":["ParseError", ["StartTag", "a", {"a":"aa"}]]},
    +{"description":"<a a=aa>",
    +"input":"<a a=aa>",
    +"output":[["StartTag", "a", {"a":"aa"}]]},
     
    -{"description":"<a a=ab",
    -"input":"<a a=ab",
    -"output":["ParseError", ["StartTag", "a", {"a":"ab"}]]},
    +{"description":"<a a=ab>",
    +"input":"<a a=ab>",
    +"output":[["StartTag", "a", {"a":"ab"}]]},
     
    -{"description":"<a a=ay",
    -"input":"<a a=ay",
    -"output":["ParseError", ["StartTag", "a", {"a":"ay"}]]},
    +{"description":"<a a=ay>",
    +"input":"<a a=ay>",
    +"output":[["StartTag", "a", {"a":"ay"}]]},
     
    -{"description":"<a a=az",
    -"input":"<a a=az",
    -"output":["ParseError", ["StartTag", "a", {"a":"az"}]]},
    +{"description":"<a a=az>",
    +"input":"<a a=az>",
    +"output":[["StartTag", "a", {"a":"az"}]]},
     
    -{"description":"<a a=a{",
    -"input":"<a a=a{",
    -"output":["ParseError", ["StartTag", "a", {"a":"a{"}]]},
    +{"description":"<a a=a{>",
    +"input":"<a a=a{>",
    +"output":[["StartTag", "a", {"a":"a{"}]]},
     
    -{"description":"<a a=a\\uDBC0\\uDC00",
    -"input":"<a a=a\uDBC0\uDC00",
    -"output":["ParseError", ["StartTag", "a", {"a":"a\uDBC0\uDC00"}]]},
    +{"description":"<a a=a\\uDBC0\\uDC00>",
    +"input":"<a a=a\uDBC0\uDC00>",
    +"output":[["StartTag", "a", {"a":"a\uDBC0\uDC00"}]]},
     
    -{"description":"<a a=b",
    -"input":"<a a=b",
    -"output":["ParseError", ["StartTag", "a", {"a":"b"}]]},
    +{"description":"<a a=b>",
    +"input":"<a a=b>",
    +"output":[["StartTag", "a", {"a":"b"}]]},
     
    -{"description":"<a a=y",
    -"input":"<a a=y",
    -"output":["ParseError", ["StartTag", "a", {"a":"y"}]]},
    +{"description":"<a a=y>",
    +"input":"<a a=y>",
    +"output":[["StartTag", "a", {"a":"y"}]]},
     
    -{"description":"<a a=z",
    -"input":"<a a=z",
    -"output":["ParseError", ["StartTag", "a", {"a":"z"}]]},
    +{"description":"<a a=z>",
    +"input":"<a a=z>",
    +"output":[["StartTag", "a", {"a":"z"}]]},
     
    -{"description":"<a a={",
    -"input":"<a a={",
    -"output":["ParseError", ["StartTag", "a", {"a":"{"}]]},
    +{"description":"<a a={>",
    +"input":"<a a={>",
    +"output":[["StartTag", "a", {"a":"{"}]]},
     
    -{"description":"<a a=\\uDBC0\\uDC00",
    -"input":"<a a=\uDBC0\uDC00",
    -"output":["ParseError", ["StartTag", "a", {"a":"\uDBC0\uDC00"}]]},
    +{"description":"<a a=\\uDBC0\\uDC00>",
    +"input":"<a a=\uDBC0\uDC00>",
    +"output":[["StartTag", "a", {"a":"\uDBC0\uDC00"}]]},
     
     {"description":"<a a>",
     "input":"<a a>",
     "output":[["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a a?",
    -"input":"<a a?",
    -"output":["ParseError", ["StartTag", "a", {"a?":""}]]},
    +{"description":"<a a?>",
    +"input":"<a a?>",
    +"output":[["StartTag", "a", {"a?":""}]]},
     
    -{"description":"<a a@",
    -"input":"<a a@",
    -"output":["ParseError", ["StartTag", "a", {"a@":""}]]},
    +{"description":"<a a@>",
    +"input":"<a a@>",
    +"output":[["StartTag", "a", {"a@":""}]]},
     
    -{"description":"<a aA",
    -"input":"<a aA",
    -"output":["ParseError", ["StartTag", "a", {"aa":""}]]},
    +{"description":"<a aA>",
    +"input":"<a aA>",
    +"output":[["StartTag", "a", {"aa":""}]]},
     
    -{"description":"<a aB",
    -"input":"<a aB",
    -"output":["ParseError", ["StartTag", "a", {"ab":""}]]},
    +{"description":"<a aB>",
    +"input":"<a aB>",
    +"output":[["StartTag", "a", {"ab":""}]]},
     
    -{"description":"<a aY",
    -"input":"<a aY",
    -"output":["ParseError", ["StartTag", "a", {"ay":""}]]},
    +{"description":"<a aY>",
    +"input":"<a aY>",
    +"output":[["StartTag", "a", {"ay":""}]]},
     
    -{"description":"<a aZ",
    -"input":"<a aZ",
    -"output":["ParseError", ["StartTag", "a", {"az":""}]]},
    +{"description":"<a aZ>",
    +"input":"<a aZ>",
    +"output":[["StartTag", "a", {"az":""}]]},
     
    -{"description":"<a a[",
    -"input":"<a a[",
    -"output":["ParseError", ["StartTag", "a", {"a[":""}]]},
    +{"description":"<a a[>",
    +"input":"<a a[>",
    +"output":[["StartTag", "a", {"a[":""}]]},
     
    -{"description":"<a a`",
    -"input":"<a a`",
    -"output":["ParseError", ["StartTag", "a", {"a`":""}]]},
    +{"description":"<a a`>",
    +"input":"<a a`>",
    +"output":[["StartTag", "a", {"a`":""}]]},
     
    -{"description":"<a aa",
    -"input":"<a aa",
    -"output":["ParseError", ["StartTag", "a", {"aa":""}]]},
    +{"description":"<a aa>",
    +"input":"<a aa>",
    +"output":[["StartTag", "a", {"aa":""}]]},
     
    -{"description":"<a ab",
    -"input":"<a ab",
    -"output":["ParseError", ["StartTag", "a", {"ab":""}]]},
    +{"description":"<a ab>",
    +"input":"<a ab>",
    +"output":[["StartTag", "a", {"ab":""}]]},
     
    -{"description":"<a ay",
    -"input":"<a ay",
    -"output":["ParseError", ["StartTag", "a", {"ay":""}]]},
    +{"description":"<a ay>",
    +"input":"<a ay>",
    +"output":[["StartTag", "a", {"ay":""}]]},
     
    -{"description":"<a az",
    -"input":"<a az",
    -"output":["ParseError", ["StartTag", "a", {"az":""}]]},
    +{"description":"<a az>",
    +"input":"<a az>",
    +"output":[["StartTag", "a", {"az":""}]]},
     
    -{"description":"<a a{",
    -"input":"<a a{",
    -"output":["ParseError", ["StartTag", "a", {"a{":""}]]},
    +{"description":"<a a{>",
    +"input":"<a a{>",
    +"output":[["StartTag", "a", {"a{":""}]]},
     
    -{"description":"<a a\\uDBC0\\uDC00",
    -"input":"<a a\uDBC0\uDC00",
    -"output":["ParseError", ["StartTag", "a", {"a\uDBC0\uDC00":""}]]},
    +{"description":"<a a\\uDBC0\\uDC00>",
    +"input":"<a a\uDBC0\uDC00>",
    +"output":[["StartTag", "a", {"a\uDBC0\uDC00":""}]]},
     
    -{"description":"<a b",
    -"input":"<a b",
    -"output":["ParseError", ["StartTag", "a", {"b":""}]]},
    +{"description":"<a b>",
    +"input":"<a b>",
    +"output":[["StartTag", "a", {"b":""}]]},
     
    -{"description":"<a y",
    -"input":"<a y",
    -"output":["ParseError", ["StartTag", "a", {"y":""}]]},
    +{"description":"<a y>",
    +"input":"<a y>",
    +"output":[["StartTag", "a", {"y":""}]]},
     
    -{"description":"<a z",
    -"input":"<a z",
    -"output":["ParseError", ["StartTag", "a", {"z":""}]]},
    +{"description":"<a z>",
    +"input":"<a z>",
    +"output":[["StartTag", "a", {"z":""}]]},
     
    -{"description":"<a {",
    -"input":"<a {",
    -"output":["ParseError", ["StartTag", "a", {"{":""}]]},
    +{"description":"<a {>",
    +"input":"<a {>",
    +"output":[["StartTag", "a", {"{":""}]]},
     
    -{"description":"<a \\uDBC0\\uDC00",
    -"input":"<a \uDBC0\uDC00",
    -"output":["ParseError", ["StartTag", "a", {"\uDBC0\uDC00":""}]]},
    +{"description":"<a \\uDBC0\\uDC00>",
    +"input":"<a \uDBC0\uDC00>",
    +"output":[["StartTag", "a", {"\uDBC0\uDC00":""}]]},
     
    -{"description":"<a!",
    -"input":"<a!",
    -"output":["ParseError", ["StartTag", "a!", {}]]},
    +{"description":"<a!>",
    +"input":"<a!>",
    +"output":[["StartTag", "a!", {}]]},
     
    -{"description":"<a\"",
    -"input":"<a\"",
    -"output":["ParseError", ["StartTag", "a\"", {}]]},
    +{"description":"<a\">",
    +"input":"<a\">",
    +"output":[["StartTag", "a\"", {}]]},
     
    -{"description":"<a&",
    -"input":"<a&",
    -"output":["ParseError", ["StartTag", "a&", {}]]},
    +{"description":"<a&>",
    +"input":"<a&>",
    +"output":[["StartTag", "a&", {}]]},
     
    -{"description":"<a'",
    -"input":"<a'",
    -"output":["ParseError", ["StartTag", "a'", {}]]},
    +{"description":"<a'>",
    +"input":"<a'>",
    +"output":[["StartTag", "a'", {}]]},
     
    -{"description":"<a-",
    -"input":"<a-",
    -"output":["ParseError", ["StartTag", "a-", {}]]},
    +{"description":"<a->",
    +"input":"<a->",
    +"output":[["StartTag", "a-", {}]]},
     
    -{"description":"<a.",
    -"input":"<a.",
    -"output":["ParseError", ["StartTag", "a.", {}]]},
    +{"description":"<a.>",
    +"input":"<a.>",
    +"output":[["StartTag", "a.", {}]]},
     
    -{"description":"<a/",
    -"input":"<a/",
    -"output":["ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a/>",
    +"input":"<a/>",
    +"output":[["StartTag", "a", {}, true]]},
     
    -{"description":"<a/\\u0000",
    -"input":"<a/\u0000",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"\uFFFD":""}]]},
    +{"description":"<a/\\u0000>",
    +"input":"<a/\u0000>",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"\uFFFD":""}]]},
     
    -{"description":"<a/\\u0009",
    -"input":"<a/\u0009",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a/\\u0009>",
    +"input":"<a/\u0009>",
    +"output":["ParseError", ["StartTag", "a", {}]]},
     
    -{"description":"<a/\\u000A",
    -"input":"<a/\u000A",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a/\\u000A>",
    +"input":"<a/\u000A>",
    +"output":["ParseError", ["StartTag", "a", {}]]},
     
    -{"description":"<a/\\u000B",
    -"input":"<a/\u000B",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"\u000B":""}]]},
    +{"description":"<a/\\u000B>",
    +"input":"<a/\u000B>",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"\u000B":""}]]},
     
    -{"description":"<a/\\u000C",
    -"input":"<a/\u000C",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a/\\u000C>",
    +"input":"<a/\u000C>",
    +"output":["ParseError", ["StartTag", "a", {}]]},
     
    -{"description":"<a/ ",
    -"input":"<a/ ",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a/ >",
    +"input":"<a/ >",
    +"output":["ParseError", ["StartTag", "a", {}]]},
     
    -{"description":"<a/!",
    -"input":"<a/!",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"!":""}]]},
    +{"description":"<a/!>",
    +"input":"<a/!>",
    +"output":["ParseError", ["StartTag", "a", {"!":""}]]},
     
    -{"description":"<a/\"",
    -"input":"<a/\"",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"\"":""}]]},
    +{"description":"<a/\">",
    +"input":"<a/\">",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"\"":""}]]},
     
    -{"description":"<a/&",
    -"input":"<a/&",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"&":""}]]},
    +{"description":"<a/&>",
    +"input":"<a/&>",
    +"output":["ParseError", ["StartTag", "a", {"&":""}]]},
     
    -{"description":"<a/'",
    -"input":"<a/'",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"'":""}]]},
    +{"description":"<a/'>",
    +"input":"<a/'>",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"'":""}]]},
     
    -{"description":"<a/-",
    -"input":"<a/-",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"-":""}]]},
    +{"description":"<a/->",
    +"input":"<a/->",
    +"output":["ParseError", ["StartTag", "a", {"-":""}]]},
     
    -{"description":"<a//",
    -"input":"<a//",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {}]]},
    +{"description":"<a//>",
    +"input":"<a//>",
    +"output":["ParseError", ["StartTag", "a", {}, true]]},
     
    -{"description":"<a/0",
    -"input":"<a/0",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"0":""}]]},
    +{"description":"<a/0>",
    +"input":"<a/0>",
    +"output":["ParseError", ["StartTag", "a", {"0":""}]]},
     
    -{"description":"<a/1",
    -"input":"<a/1",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"1":""}]]},
    +{"description":"<a/1>",
    +"input":"<a/1>",
    +"output":["ParseError", ["StartTag", "a", {"1":""}]]},
     
    -{"description":"<a/9",
    -"input":"<a/9",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"9":""}]]},
    +{"description":"<a/9>",
    +"input":"<a/9>",
    +"output":["ParseError", ["StartTag", "a", {"9":""}]]},
     
    -{"description":"<a/<",
    -"input":"<a/<",
    +{"description":"<a/<>",
    +"input":"<a/<>",
     "output":["ParseError", "ParseError", ["StartTag", "a", {"<":""}]]},
     
    -{"description":"<a/=",
    -"input":"<a/=",
    -"output":["ParseError", "ParseError", "ParseError", ["StartTag", "a", {"=":""}]]},
    +{"description":"<a/=>",
    +"input":"<a/=>",
    +"output":["ParseError", "ParseError", ["StartTag", "a", {"=":""}]]},
     
     {"description":"<a/>",
     "input":"<a/>",
     "output":[["StartTag", "a", {}, true]]},
     
    -{"description":"<a/?",
    -"input":"<a/?",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"?":""}]]},
    +{"description":"<a/?>",
    +"input":"<a/?>",
    +"output":["ParseError", ["StartTag", "a", {"?":""}]]},
     
    -{"description":"<a/@",
    -"input":"<a/@",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"@":""}]]},
    +{"description":"<a/@>",
    +"input":"<a/@>",
    +"output":["ParseError", ["StartTag", "a", {"@":""}]]},
     
    -{"description":"<a/A",
    -"input":"<a/A",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a/A>",
    +"input":"<a/A>",
    +"output":["ParseError", ["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a/B",
    -"input":"<a/B",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"b":""}]]},
    +{"description":"<a/B>",
    +"input":"<a/B>",
    +"output":["ParseError", ["StartTag", "a", {"b":""}]]},
     
    -{"description":"<a/Y",
    -"input":"<a/Y",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"y":""}]]},
    +{"description":"<a/Y>",
    +"input":"<a/Y>",
    +"output":["ParseError", ["StartTag", "a", {"y":""}]]},
     
    -{"description":"<a/Z",
    -"input":"<a/Z",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"z":""}]]},
    +{"description":"<a/Z>",
    +"input":"<a/Z>",
    +"output":["ParseError", ["StartTag", "a", {"z":""}]]},
     
    -{"description":"<a/`",
    -"input":"<a/`",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"`":""}]]},
    +{"description":"<a/`>",
    +"input":"<a/`>",
    +"output":["ParseError", ["StartTag", "a", {"`":""}]]},
     
    -{"description":"<a/a",
    -"input":"<a/a",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"a":""}]]},
    +{"description":"<a/a>",
    +"input":"<a/a>",
    +"output":["ParseError", ["StartTag", "a", {"a":""}]]},
     
    -{"description":"<a/b",
    -"input":"<a/b",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"b":""}]]},
    +{"description":"<a/b>",
    +"input":"<a/b>",
    +"output":["ParseError", ["StartTag", "a", {"b":""}]]},
     
    -{"description":"<a/y",
    -"input":"<a/y",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"y":""}]]},
    +{"description":"<a/y>",
    +"input":"<a/y>",
    +"output":["ParseError", ["StartTag", "a", {"y":""}]]},
     
    -{"description":"<a/z",
    -"input":"<a/z",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"z":""}]]},
    +{"description":"<a/z>",
    +"input":"<a/z>",
    +"output":["ParseError", ["StartTag", "a", {"z":""}]]},
     
    -{"description":"<a/{",
    -"input":"<a/{",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"{":""}]]},
    +{"description":"<a/{>",
    +"input":"<a/{>",
    +"output":["ParseError", ["StartTag", "a", {"{":""}]]},
     
    -{"description":"<a/\\uDBC0\\uDC00",
    -"input":"<a/\uDBC0\uDC00",
    -"output":["ParseError", "ParseError", ["StartTag", "a", {"\uDBC0\uDC00":""}]]},
    +{"description":"<a/\\uDBC0\\uDC00>",
    +"input":"<a/\uDBC0\uDC00>",
    +"output":["ParseError", ["StartTag", "a", {"\uDBC0\uDC00":""}]]},
     
    -{"description":"<a0",
    -"input":"<a0",
    -"output":["ParseError", ["StartTag", "a0", {}]]},
    +{"description":"<a0>",
    +"input":"<a0>",
    +"output":[["StartTag", "a0", {}]]},
     
    -{"description":"<a1",
    -"input":"<a1",
    -"output":["ParseError", ["StartTag", "a1", {}]]},
    +{"description":"<a1>",
    +"input":"<a1>",
    +"output":[["StartTag", "a1", {}]]},
     
    -{"description":"<a9",
    -"input":"<a9",
    -"output":["ParseError", ["StartTag", "a9", {}]]},
    +{"description":"<a9>",
    +"input":"<a9>",
    +"output":[["StartTag", "a9", {}]]},
     
    -{"description":"<a<",
    -"input":"<a<",
    -"output":["ParseError", ["StartTag", "a<", {}]]},
    +{"description":"<a<>",
    +"input":"<a<>",
    +"output":[["StartTag", "a<", {}]]},
     
    -{"description":"<a=",
    -"input":"<a=",
    -"output":["ParseError", ["StartTag", "a=", {}]]},
    +{"description":"<a=>",
    +"input":"<a=>",
    +"output":[["StartTag", "a=", {}]]},
     
     {"description":"<a>",
     "input":"<a>",
     "output":[["StartTag", "a", {}]]},
     
    -{"description":"<a?",
    -"input":"<a?",
    -"output":["ParseError", ["StartTag", "a?", {}]]},
    +{"description":"<a?>",
    +"input":"<a?>",
    +"output":[["StartTag", "a?", {}]]},
     
    -{"description":"<a@",
    -"input":"<a@",
    -"output":["ParseError", ["StartTag", "a@", {}]]},
    +{"description":"<a@>",
    +"input":"<a@>",
    +"output":[["StartTag", "a@", {}]]},
     
    -{"description":"<aA",
    -"input":"<aA",
    -"output":["ParseError", ["StartTag", "aa", {}]]},
    +{"description":"<aA>",
    +"input":"<aA>",
    +"output":[["StartTag", "aa", {}]]},
     
    -{"description":"<aB",
    -"input":"<aB",
    -"output":["ParseError", ["StartTag", "ab", {}]]},
    +{"description":"<aB>",
    +"input":"<aB>",
    +"output":[["StartTag", "ab", {}]]},
     
    -{"description":"<aY",
    -"input":"<aY",
    -"output":["ParseError", ["StartTag", "ay", {}]]},
    +{"description":"<aY>",
    +"input":"<aY>",
    +"output":[["StartTag", "ay", {}]]},
     
    -{"description":"<aZ",
    -"input":"<aZ",
    -"output":["ParseError", ["StartTag", "az", {}]]},
    +{"description":"<aZ>",
    +"input":"<aZ>",
    +"output":[["StartTag", "az", {}]]},
     
    -{"description":"<a[",
    -"input":"<a[",
    -"output":["ParseError", ["StartTag", "a[", {}]]},
    +{"description":"<a[>",
    +"input":"<a[>",
    +"output":[["StartTag", "a[", {}]]},
     
    -{"description":"<a`",
    -"input":"<a`",
    -"output":["ParseError", ["StartTag", "a`", {}]]},
    +{"description":"<a`>",
    +"input":"<a`>",
    +"output":[["StartTag", "a`", {}]]},
     
    -{"description":"<aa",
    -"input":"<aa",
    -"output":["ParseError", ["StartTag", "aa", {}]]},
    +{"description":"<aa>",
    +"input":"<aa>",
    +"output":[["StartTag", "aa", {}]]},
     
    -{"description":"<ab",
    -"input":"<ab",
    -"output":["ParseError", ["StartTag", "ab", {}]]},
    +{"description":"<ab>",
    +"input":"<ab>",
    +"output":[["StartTag", "ab", {}]]},
     
    -{"description":"<ay",
    -"input":"<ay",
    -"output":["ParseError", ["StartTag", "ay", {}]]},
    +{"description":"<ay>",
    +"input":"<ay>",
    +"output":[["StartTag", "ay", {}]]},
     
    -{"description":"<az",
    -"input":"<az",
    -"output":["ParseError", ["StartTag", "az", {}]]},
    +{"description":"<az>",
    +"input":"<az>",
    +"output":[["StartTag", "az", {}]]},
     
    -{"description":"<a{",
    -"input":"<a{",
    -"output":["ParseError", ["StartTag", "a{", {}]]},
    +{"description":"<a{>",
    +"input":"<a{>",
    +"output":[["StartTag", "a{", {}]]},
     
    -{"description":"<a\\uDBC0\\uDC00",
    -"input":"<a\uDBC0\uDC00",
    -"output":["ParseError", ["StartTag", "a\uDBC0\uDC00", {}]]},
    +{"description":"<a\\uDBC0\\uDC00>",
    +"input":"<a\uDBC0\uDC00>",
    +"output":[["StartTag", "a\uDBC0\uDC00", {}]]},
     
    -{"description":"<b",
    -"input":"<b",
    -"output":["ParseError", ["StartTag", "b", {}]]},
    +{"description":"<b>",
    +"input":"<b>",
    +"output":[["StartTag", "b", {}]]},
     
    -{"description":"<y",
    -"input":"<y",
    -"output":["ParseError", ["StartTag", "y", {}]]},
    +{"description":"<y>",
    +"input":"<y>",
    +"output":[["StartTag", "y", {}]]},
     
    -{"description":"<z",
    -"input":"<z",
    -"output":["ParseError", ["StartTag", "z", {}]]},
    +{"description":"<z>",
    +"input":"<z>",
    +"output":[["StartTag", "z", {}]]},
     
     {"description":"<{",
     "input":"<{",
    diff --git a/test/data/tokeniser2/test4.test b/test/data/tokeniser2/test4.test
    index ec8f72c..4be94b0 100644
    --- a/test/data/tokeniser2/test4.test
    +++ b/test/data/tokeniser2/test4.test
    @@ -1,11 +1,11 @@
     {"tests": [
     
     {"description":"< in attribute name",
    -"input":"<z/0  <",
    +"input":"<z/0  <>",
     "output":["ParseError", "ParseError", ["StartTag", "z", {"0": "", "<": ""}]]},
     
     {"description":"< in attribute value",
    -"input":"<z x=<",
    +"input":"<z x=<>",
     "output":["ParseError", ["StartTag", "z", {"x": "<"}]]},
     
     {"description":"= in unquoted attribute value",
    @@ -28,25 +28,25 @@
     "input":"<z ====>",
     "output":["ParseError", "ParseError", "ParseError", ["StartTag", "z", {"=": "=="}]]},
     
    -{"description":"Allowed \" after ampersand in attribute value",
    +{"description":"\" after ampersand in double-quoted attribute value",
     "input":"<z z=\"&\">",
     "output":[["StartTag", "z", {"z": "&"}]]},
     
    -{"description":"Non-allowed ' after ampersand in attribute value",
    +{"description":"' after ampersand in double-quoted attribute value",
     "input":"<z z=\"&'\">",
    -"output":["ParseError", ["StartTag", "z", {"z": "&'"}]]},
    +"output":[["StartTag", "z", {"z": "&'"}]]},
     
    -{"description":"Allowed ' after ampersand in attribute value",
    +{"description":"' after ampersand in single-quoted attribute value",
     "input":"<z z='&'>",
     "output":[["StartTag", "z", {"z": "&"}]]},
     
    -{"description":"Non-allowed \" after ampersand in attribute value",
    +{"description":"\" after ampersand in single-quoted attribute value",
     "input":"<z z='&\"'>",
    -"output":["ParseError", ["StartTag", "z", {"z": "&\""}]]},
    +"output":[["StartTag", "z", {"z": "&\""}]]},
     
     {"description":"Text after bogus character reference",
     "input":"<z z='&xlink_xmlns;'>bar<z>",
    -"output":["ParseError",["StartTag","z",{"z":"&xlink_xmlns;"}],["Character","bar"],["StartTag","z",{}]]},
    +"output":[["StartTag","z",{"z":"&xlink_xmlns;"}],["Character","bar"],["StartTag","z",{}]]},
     
     {"description":"Text after hex character reference",
     "input":"<z z='&#x0020; foo'>bar<z>",
    @@ -98,11 +98,11 @@
     
     {"description":"CR EOF in tag name",
     "input":"<z\r",
    -"output":["ParseError", ["StartTag", "z", {}]]},
    +"output":["ParseError"]},
     
     {"description":"Slash EOF in tag name",
     "input":"<z/",
    -"output":["ParseError", ["StartTag", "z", {}]]},
    +"output":["ParseError"]},
     
     {"description":"Zero hex numeric entity",
     "input":"&#x0",
    @@ -134,7 +134,7 @@
     
     {"description":"Maximum non-BMP numeric entity",
     "input":"&#X10FFFF;",
    -"output":["ParseError", ["Character", "\uFFFD"]]},
    +"output":["ParseError", ["Character", "\uDBFF\uDFFF"]]},
     
     {"description":"Above maximum numeric entity",
     "input":"&#x110000;",
    @@ -222,12 +222,12 @@
     
     {"description":"U+0000 in lookahead region after non-matching character",
     "input":"<!doc>\u0000",
    -"output":["ParseError", ["Comment", "doc"], "ParseError", ["Character", "\uFFFD"]],
    +"output":["ParseError", ["Comment", "doc"], "ParseError", ["Character", "\u0000"]],
     "ignoreErrorOrder":true},
     
     {"description":"U+0000 in lookahead region",
     "input":"<!doc\u0000",
    -"output":["ParseError", "ParseError", ["Comment", "doc\uFFFD"]],
    +"output":["ParseError", ["Comment", "doc\uFFFD"]],
     "ignoreErrorOrder":true},
     
     {"description":"U+0080 in lookahead region",
    @@ -245,11 +245,6 @@
     "output":["ParseError", "ParseError", ["Comment", "doc\uD83F\uDFFF"]],
     "ignoreErrorOrder":true},
     
    -{"description":"CR followed by U+0000",
    -"input":"\r\u0000",
    -"output":["ParseError", ["Character", "\n\uFFFD"]],
    -"ignoreErrorOrder":true},
    -
     {"description":"CR followed by non-LF",
     "input":"\r?",
     "output":[["Character", "\n?"]]},
    @@ -300,6 +295,50 @@
     
     {"description":"Doctype html x>text",
     "input":"<!DOCTYPE html x>text",
    -"output":["ParseError", ["DOCTYPE", "html", null, null, false], ["Character", "text"]]}
    +"output":["ParseError", ["DOCTYPE", "html", null, null, false], ["Character", "text"]]},
    +
    +{"description":"Grave accent in unquoted attribute",
    +"input":"<a a=aa`>",
    +"output":["ParseError", ["StartTag", "a", {"a":"aa`"}]]},
    +
    +{"description":"EOF in tag name state ",
    +"input":"<a",
    +"output":["ParseError"]},
    +
    +{"description":"EOF in tag name state",
    +"input":"<a",
    +"output":["ParseError"]},
    +
    +{"description":"EOF in before attribute name state",
    +"input":"<a ",
    +"output":["ParseError"]},
    +
    +{"description":"EOF in attribute name state",
    +"input":"<a a",
    +"output":["ParseError"]},
    +
    +{"description":"EOF in after attribute name state",
    +"input":"<a a ",
    +"output":["ParseError"]},
    +
    +{"description":"EOF in before attribute value state",
    +"input":"<a a =",
    +"output":["ParseError"]},
    +
    +{"description":"EOF in attribute value (double quoted) state",
    +"input":"<a a =\"a",
    +"output":["ParseError"]},
    +
    +{"description":"EOF in attribute value (single quoted) state",
    +"input":"<a a ='a",
    +"output":["ParseError"]},
    +
    +{"description":"EOF in attribute value (unquoted) state",
    +"input":"<a a =a",
    +"output":["ParseError"]},
    +
    +{"description":"EOF in after attribute value state",
    +"input":"<a a ='a'",
    +"output":["ParseError"]}
     
     ]}
    diff --git a/test/data/tokeniser2/unicodeChars.test b/test/data/tokeniser2/unicodeChars.test
    index 9b59015..c778668 100644
    --- a/test/data/tokeniser2/unicodeChars.test
    +++ b/test/data/tokeniser2/unicodeChars.test
    @@ -112,14 +112,6 @@
     "input": "\u007F",
     "output": ["ParseError", ["Character", "\u007F"]]},
     
    -{"description": "Invalid Unicode character U+D800",
    -"input": "\uD800",
    -"output": ["ParseError", ["Character", "\uD800"]]},
    -
    -{"description": "Invalid Unicode character U+DFFF",
    -"input": "\uDFFF",
    -"output": ["ParseError", ["Character", "\uDFFF"]]},
    -
     {"description": "Invalid Unicode character U+FDD0",
     "input": "\uFDD0",
     "output": ["ParseError", ["Character", "\uFDD0"]]},
    diff --git a/test/testutils.h b/test/testutils.h
    index 45870f9..fa159d6 100644
    --- a/test/testutils.h
    +++ b/test/testutils.h
    @@ -63,6 +63,7 @@ typedef bool (*line_func)(const char *data, size_t datalen, void *pw);
     static size_t parse_strlen(const char *str, size_t limit);
     bool parse_testfile(const char *filename, line_func callback, void *pw);
     size_t parse_filesize(const char *filename);
    +size_t n_str(const char *str);
     
     /**
      * Testcase datafile parser driver
    @@ -147,6 +148,24 @@ size_t parse_filesize(const char *filename)
     	return len;
     }
     
    +/**
    + * Utility string length measurer; assumes strings are '\0' terminated
    + *
    + * \param str    String to measure length of
    + * \return String length
    + */
    +size_t n_str(const char *str)
    +{
    +	size_t len = 0;
    +
    +	if (str == NULL)
    +		return 0;
    +
    +	for (; *str++;len++);
    +
    +	return len;
    +}
    +
     
     #ifndef strndup
     char *my_strndup(const char *s, size_t n);
    diff --git a/test/tokeniser2.c b/test/tokeniser2.c
    index c8ab9c0..c320f42 100644
    --- a/test/tokeniser2.c
    +++ b/test/tokeniser2.c
    @@ -14,6 +14,8 @@
     
     #include "testutils.h"
     
    +#define strlen n_str
    +
     typedef struct context {
     	const uint8_t *pbuffer;
     
    @@ -301,7 +303,8 @@ hubbub_error token_handler(const hubbub_token *token, void *pw)
     				gotsys,
     				(int) token->data.doctype.system_id.len);
     		}
    -
    +		printf(":%d: :%d:\n", (int)token->data.doctype.name.len, (int) strlen(expname));
    +		printf(":%s: :%s:\n", gotname, expname);
     		assert(token->data.doctype.name.len == strlen(expname));
     		assert(strncmp(gotname, expname, strlen(expname)) == 0);
     
    -- 
    1.8.3.2
    
    
  • patch file icon 0002-Replacing-content-model-with-states-except-SCRIPT-DA.patch (57,023 bytes) 2014-03-11 17:00 -
    From 2a58f19635d9c8b2c5a1ce293b6a3fc5f57be7d8 Mon Sep 17 00:00:00 2001
    From: Achal-Aggarwal <theachalaggarwal@gmail.com>
    Date: Tue, 11 Mar 2014 17:57:08 +0530
    Subject: [PATCH 2/4] Replacing content model with states (except SCRIPT DATA).
    
    ---
     include/hubbub/parser.h                     |    6 +-
     include/hubbub/types.h                      |   13 +-
     src/parser.c                                |    4 +-
     src/tokeniser/tokeniser.c                   | 1224 +++++++++++++++++++++++----
     src/tokeniser/tokeniser.h                   |    6 +-
     src/treebuilder/in_body.c                   |    4 +-
     src/treebuilder/treebuilder.c               |    6 +-
     test/data/tokeniser2/contentModelFlags.test |   50 +-
     test/data/tokeniser2/escapeFlag.test        |   24 +-
     test/tokeniser2.c                           |   47 +-
     10 files changed, 1129 insertions(+), 255 deletions(-)
    
    diff --git a/include/hubbub/parser.h b/include/hubbub/parser.h
    index bdc5e20..42d68cc 100644
    --- a/include/hubbub/parser.h
    +++ b/include/hubbub/parser.h
    @@ -29,7 +29,7 @@ typedef struct hubbub_parser hubbub_parser;
     typedef enum hubbub_parser_opttype {
     	HUBBUB_PARSER_TOKEN_HANDLER,
     	HUBBUB_PARSER_ERROR_HANDLER,
    -	HUBBUB_PARSER_CONTENT_MODEL,
    +	HUBBUB_PARSER_INITIAL_STATE,
     	HUBBUB_PARSER_TREE_HANDLER,
     	HUBBUB_PARSER_DOCUMENT_NODE,
     	HUBBUB_PARSER_ENABLE_SCRIPTING,
    @@ -51,8 +51,8 @@ typedef union hubbub_parser_optparams {
     	} error_handler;		/**< Error handling callback */
     
     	struct {
    -		hubbub_content_model model;
    -	} content_model;		/**< Current content model */
    +		hubbub_initial_state state;
    +	} initial_state;		/**< Initial state of tokeniser */
     
     	hubbub_tree_handler *tree_handler;	/**< Tree handling callbacks */
     
    diff --git a/include/hubbub/types.h b/include/hubbub/types.h
    index e5c208b..6e14fb7 100644
    --- a/include/hubbub/types.h
    +++ b/include/hubbub/types.h
    @@ -29,12 +29,13 @@ typedef enum hubbub_charset_source {
     /**
      * Content model flag
      */
    -typedef enum hubbub_content_model {
    -	HUBBUB_CONTENT_MODEL_PCDATA,
    -	HUBBUB_CONTENT_MODEL_RCDATA,
    -	HUBBUB_CONTENT_MODEL_CDATA,
    -	HUBBUB_CONTENT_MODEL_PLAINTEXT
    -} hubbub_content_model;
    +typedef enum hubbub_initial_state {
    +	HUBBUB_INITIAL_STATE_DATA,
    +	HUBBUB_INITIAL_STATE_RCDATA,
    +	HUBBUB_INITIAL_STATE_CDATA,
    +	HUBBUB_INITIAL_STATE_PLAINTEXT,
    +	HUBBUB_INITIAL_STATE_RAWTEXT
    +} hubbub_initial_state;
     
     /**
      * Quirks mode flag
    diff --git a/src/parser.c b/src/parser.c
    index 671e129..749c674 100644
    --- a/src/parser.c
    +++ b/src/parser.c
    @@ -160,9 +160,9 @@ hubbub_error hubbub_parser_setopt(hubbub_parser *parser,
     		}
     		break;
     
    -	case HUBBUB_PARSER_CONTENT_MODEL:
    +	case HUBBUB_PARSER_INITIAL_STATE:
     		result = hubbub_tokeniser_setopt(parser->tok,
    -				HUBBUB_TOKENISER_CONTENT_MODEL,
    +				HUBBUB_TOKENISER_INITIAL_STATE,
     				(hubbub_tokeniser_optparams *) params);
     		break;
     
    diff --git a/src/tokeniser/tokeniser.c b/src/tokeniser/tokeniser.c
    index 3eab8a7..7152f05 100644
    --- a/src/tokeniser/tokeniser.c
    +++ b/src/tokeniser/tokeniser.c
    @@ -43,16 +43,26 @@ static const hubbub_string u_fffd_str = { u_fffd, sizeof(u_fffd) };
     static const uint8_t lf = '\n';
     static const hubbub_string lf_str = { &lf, 1 };
     
    -
     /**
      * Tokeniser states
      */
     typedef enum hubbub_tokeniser_state {
     	STATE_DATA,
     	STATE_CHARACTER_REFERENCE_DATA,
    +	STATE_RCDATA,
    +	STATE_CHARACTER_REFERENCE_RCDATA,
    +	STATE_RAWTEXT,
    +	STATE_SCRIPT_DATA,
    +	STATE_PLAINTEXT,
     	STATE_TAG_OPEN,
     	STATE_CLOSE_TAG_OPEN,
     	STATE_TAG_NAME,
    +	STATE_RCDATA_LESSTHAN,
    +	STATE_RCDATA_CLOSE_TAG_OPEN,
    +	STATE_RCDATA_CLOSE_TAG_NAME,
    +	STATE_RAWTEXT_LESSTHAN,
    +	STATE_RAWTEXT_CLOSE_TAG_OPEN,
    +	STATE_RAWTEXT_CLOSE_TAG_NAME,
     	STATE_BEFORE_ATTRIBUTE_NAME,
     	STATE_ATTRIBUTE_NAME,
     	STATE_AFTER_ATTRIBUTE_NAME,
    @@ -166,8 +176,6 @@ typedef struct hubbub_tokeniser_context {
      */
     struct hubbub_tokeniser {
     	hubbub_tokeniser_state state;	/**< Current tokeniser state */
    -	hubbub_content_model content_model;	/**< Current content
    -						 * model flag */
     	bool escape_flag;		/**< Escape flag **/
     	bool process_cdata_section;	/**< Whether to process CDATA sections*/
     	bool paused; /**< flag for if parsing is currently paused */
    @@ -188,12 +196,34 @@ struct hubbub_tokeniser {
     static hubbub_error hubbub_tokeniser_handle_data(hubbub_tokeniser *tokeniser);
     static hubbub_error hubbub_tokeniser_handle_character_reference_data(
     		hubbub_tokeniser *tokeniser);
    +static hubbub_error hubbub_tokeniser_handle_rcdata(
    +		hubbub_tokeniser *tokeniser);
    +static hubbub_error hubbub_tokeniser_handle_character_reference_rcdata(
    +		hubbub_tokeniser *tokeniser);
    +static hubbub_error hubbub_tokeniser_handle_rawtext(
    +		hubbub_tokeniser *tokeniser);
    +static hubbub_error hubbub_tokeniser_handle_script_data(
    +		hubbub_tokeniser *tokeniser);
    +static hubbub_error hubbub_tokeniser_handle_plaintext(
    +		hubbub_tokeniser *tokeniser);
     static hubbub_error hubbub_tokeniser_handle_tag_open(
     		hubbub_tokeniser *tokeniser);
     static hubbub_error hubbub_tokeniser_handle_close_tag_open(
     		hubbub_tokeniser *tokeniser);
     static hubbub_error hubbub_tokeniser_handle_tag_name(
     		hubbub_tokeniser *tokeniser);
    +static hubbub_error hubbub_tokeniser_handle_rcdata_lessthan(
    +		hubbub_tokeniser *tokeniser);
    +static hubbub_error hubbub_tokeniser_handle_rcdata_close_tag_open(
    +		hubbub_tokeniser *tokeniser);
    +static hubbub_error hubbub_tokeniser_handle_rcdata_close_tag_name(
    +		hubbub_tokeniser *tokeniser);
    +static hubbub_error hubbub_tokeniser_handle_rawtext_lessthan(
    +		hubbub_tokeniser *tokeniser);
    +static hubbub_error hubbub_tokeniser_handle_rawtext_close_tag_open(
    +		hubbub_tokeniser *tokeniser);
    +static hubbub_error hubbub_tokeniser_handle_rawtext_close_tag_name(
    +		hubbub_tokeniser *tokeniser);
     static hubbub_error hubbub_tokeniser_handle_before_attribute_name(
     		hubbub_tokeniser *tokeniser);
     static hubbub_error hubbub_tokeniser_handle_attribute_name(
    @@ -313,7 +343,6 @@ hubbub_error hubbub_tokeniser_create(parserutils_inputstream *input,
     	}
     
     	tok->state = STATE_DATA;
    -	tok->content_model = HUBBUB_CONTENT_MODEL_PCDATA;
     
     	tok->escape_flag = false;
     	tok->process_cdata_section = false;
    @@ -385,8 +414,18 @@ hubbub_error hubbub_tokeniser_setopt(hubbub_tokeniser *tokeniser,
     		tokeniser->error_handler = params->error_handler.handler;
     		tokeniser->error_pw = params->error_handler.pw;
     		break;
    -	case HUBBUB_TOKENISER_CONTENT_MODEL:
    -		tokeniser->content_model = params->content_model.model;
    +	case HUBBUB_TOKENISER_INITIAL_STATE:
    +		if (params->initial_state.state == HUBBUB_INITIAL_STATE_DATA) {
    +			tokeniser->state = STATE_DATA;
    +		} else if (params->initial_state.state == HUBBUB_INITIAL_STATE_RCDATA) {
    +			tokeniser->state = STATE_RCDATA;
    +		} else if (params->initial_state.state == HUBBUB_INITIAL_STATE_CDATA) {
    +			tokeniser->state = STATE_CDATA_BLOCK;
    +		} else if (params->initial_state.state == HUBBUB_INITIAL_STATE_PLAINTEXT) {
    +			tokeniser->state = STATE_PLAINTEXT;
    +		} else if (params->initial_state.state == HUBBUB_INITIAL_STATE_RAWTEXT) {
    +			tokeniser->state = STATE_RAWTEXT;
    +		}  
     		break;
     	case HUBBUB_TOKENISER_PROCESS_CDATA:
     		tokeniser->process_cdata_section = params->process_cdata;
    @@ -465,6 +504,26 @@ hubbub_error hubbub_tokeniser_run(hubbub_tokeniser *tokeniser)
     			cont = hubbub_tokeniser_handle_character_reference_data(
     					tokeniser);
     			break;
    +		state(STATE_RCDATA)
    +			cont = hubbub_tokeniser_handle_rcdata(
    +					tokeniser);
    +			break;
    +		state(STATE_CHARACTER_REFERENCE_RCDATA)
    +			cont = hubbub_tokeniser_handle_character_reference_rcdata(
    +					tokeniser);
    +			break;
    +		state(STATE_RAWTEXT)
    +			cont = hubbub_tokeniser_handle_rawtext(
    +					tokeniser);
    +			break;
    +		state(STATE_SCRIPT_DATA)
    +			cont = hubbub_tokeniser_handle_script_data(
    +					tokeniser);
    +			break;
    +		state(STATE_PLAINTEXT)
    +			cont = hubbub_tokeniser_handle_plaintext(
    +					tokeniser);
    +			break;
     		state(STATE_TAG_OPEN)
     			cont = hubbub_tokeniser_handle_tag_open(tokeniser);
     			break;
    @@ -475,6 +534,30 @@ hubbub_error hubbub_tokeniser_run(hubbub_tokeniser *tokeniser)
     		state(STATE_TAG_NAME)
     			cont = hubbub_tokeniser_handle_tag_name(tokeniser);
     			break;
    +		state(STATE_RCDATA_LESSTHAN)
    +			cont = hubbub_tokeniser_handle_rcdata_lessthan(
    +					tokeniser);
    +			break;
    +		state(STATE_RCDATA_CLOSE_TAG_OPEN)
    +			cont = hubbub_tokeniser_handle_rcdata_close_tag_open(
    +					tokeniser);
    +			break;
    +		state(STATE_RCDATA_CLOSE_TAG_NAME)
    +			cont = hubbub_tokeniser_handle_rcdata_close_tag_name(
    +					tokeniser);
    +			break;
    +		state(STATE_RAWTEXT_LESSTHAN)
    +			cont = hubbub_tokeniser_handle_rawtext_lessthan(
    +					tokeniser);
    +			break;
    +		state(STATE_RAWTEXT_CLOSE_TAG_OPEN)
    +			cont = hubbub_tokeniser_handle_rawtext_close_tag_open(
    +					tokeniser);
    +			break;
    +		state(STATE_RAWTEXT_CLOSE_TAG_NAME)
    +			cont = hubbub_tokeniser_handle_rawtext_close_tag_name(
    +					tokeniser);
    +			break;
     		state(STATE_BEFORE_ATTRIBUTE_NAME)
     			cont = hubbub_tokeniser_handle_before_attribute_name(
     					tokeniser);
    @@ -703,103 +786,899 @@ hubbub_error hubbub_tokeniser_handle_data(hubbub_tokeniser *tokeniser)
     				break;
     			}
     
    -			if (tokeniser->context.pending > 0) {
    -				/* Emit any pending characters */
    -				emit_current_chars(tokeniser);
    -			}
    +			if (tokeniser->context.pending > 0) {
    +				/* Emit any pending characters */
    +				emit_current_chars(tokeniser);
    +			}
    +
    +			if (error == PARSERUTILS_EOF ||	*cptr != '\n') {
    +				/* Emit newline */
    +				emit_character_token(tokeniser, &lf_str);
    +			}
    +
    +			/* Advance over */
    +			parserutils_inputstream_advance(tokeniser->input, 1);
    +		} else {
    +			if (c == '\0') {
    +				/** \todo parse error */
    +			}
    +
    +			/* Just collect into buffer */
    +			tokeniser->context.pending += len;
    +		}
    +	}
    +	if (tokeniser->state != STATE_TAG_OPEN &&
    +		(tokeniser->state != STATE_DATA || error == PARSERUTILS_EOF) &&
    +			tokeniser->context.pending > 0) {
    +		/* Emit any pending characters */
    +		emit_current_chars(tokeniser);
    +	}
    +
    +	if (error == PARSERUTILS_EOF) {
    +		token.type = HUBBUB_TOKEN_EOF;
    +		hubbub_tokeniser_emit_token(tokeniser, &token);
    +	}
    +
    +	if (error == PARSERUTILS_EOF) {
    +		return HUBBUB_NEEDDATA;
    +	} else {
    +		return hubbub_error_from_parserutils_error(error);
    +	}
    +}
    +
    +
    +
    +/* emit any pending tokens before calling */
    +hubbub_error hubbub_tokeniser_handle_character_reference_data(
    +		hubbub_tokeniser *tokeniser)
    +{
    +	assert(tokeniser->context.pending == 0);
    +
    +	if (tokeniser->context.match_entity.complete == false) {
    +		return hubbub_tokeniser_consume_character_reference(tokeniser,
    +				tokeniser->context.pending);
    +	} else {
    +		hubbub_token token;
    +
    +		uint8_t utf8[6];
    +		uint8_t *utf8ptr = utf8;
    +		size_t len = sizeof(utf8);
    +
    +		token.type = HUBBUB_TOKEN_CHARACTER;
    +
    +		if (tokeniser->context.match_entity.codepoint) {
    +			parserutils_charset_utf8_from_ucs4(
    +				tokeniser->context.match_entity.codepoint,
    +				&utf8ptr, &len);
    +
    +			token.data.character.ptr = utf8;
    +			token.data.character.len = sizeof(utf8) - len;
    +
    +			hubbub_tokeniser_emit_token(tokeniser, &token);
    +
    +			/* +1 for ampersand */
    +			parserutils_inputstream_advance(tokeniser->input,
    +					tokeniser->context.match_entity.length
    +							+ 1);
    +		} else {
    +			parserutils_error error;
    +			const uint8_t *cptr = NULL;
    +
    +			error = parserutils_inputstream_peek(
    +					tokeniser->input,
    +					tokeniser->context.pending,
    +					&cptr,
    +					&len);
    +			if (error != PARSERUTILS_OK) {
    +				return hubbub_error_from_parserutils_error(
    +						error);
    +			}
    +
    +			token.data.character.ptr = cptr;
    +			token.data.character.len = len;
    +
    +			hubbub_tokeniser_emit_token(tokeniser, &token);
    +			parserutils_inputstream_advance(tokeniser->input, len);
    +		}
    +
    +		/* Reset for next time */
    +		tokeniser->context.match_entity.complete = false;
    +
    +		tokeniser->state = STATE_DATA;
    +	}
    +
    +	return HUBBUB_OK;
    +}
    +
    +hubbub_error hubbub_tokeniser_handle_rcdata(hubbub_tokeniser *tokeniser)
    +{
    +	parserutils_error error;
    +	hubbub_token token;
    +	const uint8_t *cptr;
    +	size_t len;
    +
    +	while ((error = parserutils_inputstream_peek(tokeniser->input,
    +			tokeniser->context.pending, &cptr, &len)) ==
    +					PARSERUTILS_OK) {
    +		const uint8_t c = *cptr;
    +
    +		if (c == '&') {
    +			tokeniser->state = STATE_CHARACTER_REFERENCE_RCDATA;
    +			/* Don't eat the '&'; it'll be handled by entity
    +			 * consumption */
    +			break;
    +		} else if (c == '<') {
    +			if (tokeniser->context.pending > 0) {
    +				/* Emit any pending characters */
    +				emit_current_chars(tokeniser);
    +			}
    +
    +			/* Buffer '<' */
    +			tokeniser->context.pending = len;
    +			tokeniser->state = STATE_RCDATA_LESSTHAN;
    +			break;
    +		} else if (c == '\r') {
    +			error = parserutils_inputstream_peek(
    +					tokeniser->input,
    +					tokeniser->context.pending + len,
    +					&cptr,
    +					&len);
    +
    +			if (error != PARSERUTILS_OK && 
    +					error != PARSERUTILS_EOF) {
    +				break;
    +			}
    +
    +			if (tokeniser->context.pending > 0) {
    +				/* Emit any pending characters */
    +				emit_current_chars(tokeniser);
    +			}
    +
    +			if (error == PARSERUTILS_EOF ||	*cptr != '\n') {
    +				/* Emit newline */
    +				emit_character_token(tokeniser, &lf_str);
    +			}
    +
    +			/* Advance over */
    +			parserutils_inputstream_advance(tokeniser->input, 1);
    +		} else {
    +			if (c == '\0') {
    +				/** \todo parse error */
    +				error = parserutils_buffer_append(tokeniser->buffer,
    +				u_fffd, sizeof(u_fffd));
    +				if (error != PARSERUTILS_OK)
    +					return hubbub_error_from_parserutils_error(error);
    +			}
    +
    +			/* Just collect into buffer */
    +			tokeniser->context.pending += len;
    +		}
    +	}
    +	if (tokeniser->state != STATE_RCDATA_LESSTHAN &&
    +		(tokeniser->state != STATE_RCDATA || error == PARSERUTILS_EOF) &&
    +			tokeniser->context.pending > 0) {
    +		/* Emit any pending characters */
    +		emit_current_chars(tokeniser);
    +	}
    +
    +	if (error == PARSERUTILS_EOF) {
    +		token.type = HUBBUB_TOKEN_EOF;
    +		hubbub_tokeniser_emit_token(tokeniser, &token);
    +	}
    +
    +	if (error == PARSERUTILS_EOF) {
    +		return HUBBUB_NEEDDATA;
    +	} else {
    +		return hubbub_error_from_parserutils_error(error);
    +	}
    +}
    +
    +
    +
    +/* emit any pending tokens before calling */
    +hubbub_error hubbub_tokeniser_handle_character_reference_rcdata(
    +		hubbub_tokeniser *tokeniser)
    +{
    +	assert(tokeniser->context.pending == 0);
    +
    +	if (tokeniser->context.match_entity.complete == false) {
    +		return hubbub_tokeniser_consume_character_reference(tokeniser,
    +				tokeniser->context.pending);
    +	} else {
    +		hubbub_token token;
    +
    +		uint8_t utf8[6];
    +		uint8_t *utf8ptr = utf8;
    +		size_t len = sizeof(utf8);
    +
    +		token.type = HUBBUB_TOKEN_CHARACTER;
    +
    +		if (tokeniser->context.match_entity.codepoint) {
    +			parserutils_charset_utf8_from_ucs4(
    +				tokeniser->context.match_entity.codepoint,
    +				&utf8ptr, &len);
    +
    +			token.data.character.ptr = utf8;
    +			token.data.character.len = sizeof(utf8) - len;
    +
    +			hubbub_tokeniser_emit_token(tokeniser, &token);
    +
    +			/* +1 for ampersand */
    +			parserutils_inputstream_advance(tokeniser->input,
    +					tokeniser->context.match_entity.length
    +							+ 1);
    +		} else {
    +			parserutils_error error;
    +			const uint8_t *cptr = NULL;
    +
    +			error = parserutils_inputstream_peek(
    +					tokeniser->input,
    +					tokeniser->context.pending,
    +					&cptr,
    +					&len);
    +			if (error != PARSERUTILS_OK) {
    +				return hubbub_error_from_parserutils_error(
    +						error);
    +			}
    +
    +			token.data.character.ptr = cptr;
    +			token.data.character.len = len;
    +
    +			hubbub_tokeniser_emit_token(tokeniser, &token);
    +			parserutils_inputstream_advance(tokeniser->input, len);
    +		}
    +
    +		/* Reset for next time */
    +		tokeniser->context.match_entity.complete = false;
    +
    +		tokeniser->state = STATE_RCDATA;
    +	}
    +
    +	return HUBBUB_OK;
    +}
    +
    +hubbub_error hubbub_tokeniser_handle_rawtext(hubbub_tokeniser *tokeniser)
    +{
    +	parserutils_error error;
    +	hubbub_token token;
    +	const uint8_t *cptr;
    +	size_t len;
    +
    +	while ((error = parserutils_inputstream_peek(tokeniser->input,
    +			tokeniser->context.pending, &cptr, &len)) ==
    +					PARSERUTILS_OK) {
    +		const uint8_t c = *cptr;
    +
    +		if (c == '<') {
    +			if (tokeniser->context.pending > 0) {
    +				/* Emit any pending characters */
    +				emit_current_chars(tokeniser);
    +			}
    +
    +			/* Buffer '<' */
    +			tokeniser->context.pending = len;
    +			tokeniser->state = STATE_RAWTEXT_LESSTHAN;
    +			break;
    +		} else if (c == '\r') {
    +			error = parserutils_inputstream_peek(
    +					tokeniser->input,
    +					tokeniser->context.pending + len,
    +					&cptr,
    +					&len);
    +
    +			if (error != PARSERUTILS_OK && 
    +					error != PARSERUTILS_EOF) {
    +				break;
    +			}
    +
    +			if (tokeniser->context.pending > 0) {
    +				/* Emit any pending characters */
    +				emit_current_chars(tokeniser);
    +			}
    +
    +			if (error == PARSERUTILS_EOF ||	*cptr != '\n') {
    +				/* Emit newline */
    +				emit_character_token(tokeniser, &lf_str);
    +			}
    +
    +			/* Advance over */
    +			parserutils_inputstream_advance(tokeniser->input, 1);
    +		} else {
    +			if (c == '\0') {
    +				/** \todo parse error */
    +				error = parserutils_buffer_append(tokeniser->buffer,
    +				u_fffd, sizeof(u_fffd));
    +				if (error != PARSERUTILS_OK)
    +					return hubbub_error_from_parserutils_error(error);
    +			}
    +
    +			/* Just collect into buffer */
    +			tokeniser->context.pending += len;
    +		}
    +	}
    +	if (tokeniser->state != STATE_RAWTEXT_LESSTHAN &&
    +		(tokeniser->state != STATE_RAWTEXT || error == PARSERUTILS_EOF) &&
    +			tokeniser->context.pending > 0) {
    +		/* Emit any pending characters */
    +		emit_current_chars(tokeniser);
    +	}
    +
    +	if (error == PARSERUTILS_EOF) {
    +		token.type = HUBBUB_TOKEN_EOF;
    +		hubbub_tokeniser_emit_token(tokeniser, &token);
    +	}
    +
    +	if (error == PARSERUTILS_EOF) {
    +		return HUBBUB_NEEDDATA;
    +	} else {
    +		return hubbub_error_from_parserutils_error(error);
    +	}
    +}
    +
    +hubbub_error hubbub_tokeniser_handle_script_data(hubbub_tokeniser *tokeniser)
    +{
    +	parserutils_error error;
    +	hubbub_token token;
    +	const uint8_t *cptr;
    +	size_t len;
    +
    +	while ((error = parserutils_inputstream_peek(tokeniser->input,
    +			tokeniser->context.pending, &cptr, &len)) ==
    +					PARSERUTILS_OK) {
    +		const uint8_t c = *cptr;
    +
    +		if (c == '<') {
    +			if (tokeniser->context.pending > 0) {
    +				/* Emit any pending characters */
    +				emit_current_chars(tokeniser);
    +			}
    +
    +			/* Buffer '<' */
    +			tokeniser->context.pending = len;
    +			////////tokeniser->state = STATE_SCRIPT_DATA_LESSTHAN;
    +			break;
    +		} else if (c == '\r') {
    +			error = parserutils_inputstream_peek(
    +					tokeniser->input,
    +					tokeniser->context.pending + len,
    +					&cptr,
    +					&len);
    +
    +			if (error != PARSERUTILS_OK && 
    +					error != PARSERUTILS_EOF) {
    +				break;
    +			}
    +
    +			if (tokeniser->context.pending > 0) {
    +				/* Emit any pending characters */
    +				emit_current_chars(tokeniser);
    +			}
    +
    +			if (error == PARSERUTILS_EOF ||	*cptr != '\n') {
    +				/* Emit newline */
    +				emit_character_token(tokeniser, &lf_str);
    +			}
    +
    +			/* Advance over */
    +			parserutils_inputstream_advance(tokeniser->input, 1);
    +		} else {
    +			if (c == '\0') {
    +				/** \todo parse error */
    +				error = parserutils_buffer_append(tokeniser->buffer,
    +				u_fffd, sizeof(u_fffd));
    +				if (error != PARSERUTILS_OK)
    +					return hubbub_error_from_parserutils_error(error);
    +			}
    +
    +			/* Just collect into buffer */
    +			tokeniser->context.pending += len;
    +		}
    +	}
    +	if (tokeniser->state != STATE_SCRIPT_DATA &&
    +		(/*tokeniser->state != STATE_SCRIPT_DATA_LESSTHAN || */error == PARSERUTILS_EOF) &&
    +			tokeniser->context.pending > 0) {
    +		/* Emit any pending characters */
    +		emit_current_chars(tokeniser);
    +	}
    +
    +	if (error == PARSERUTILS_EOF) {
    +		token.type = HUBBUB_TOKEN_EOF;
    +		hubbub_tokeniser_emit_token(tokeniser, &token);
    +	}
    +
    +	if (error == PARSERUTILS_EOF) {
    +		return HUBBUB_NEEDDATA;
    +	} else {
    +		return hubbub_error_from_parserutils_error(error);
    +	}
    +}
    +
    +hubbub_error hubbub_tokeniser_handle_plaintext(hubbub_tokeniser *tokeniser)
    +{
    +	parserutils_error error;
    +	hubbub_token token;
    +	const uint8_t *cptr;
    +	size_t len;
    +
    +	while ((error = parserutils_inputstream_peek(tokeniser->input,
    +			tokeniser->context.pending, &cptr, &len)) ==
    +					PARSERUTILS_OK) {
    +		const uint8_t c = *cptr;
    +
    +		if (c == '\r') {
    +			error = parserutils_inputstream_peek(
    +					tokeniser->input,
    +					tokeniser->context.pending + len,
    +					&cptr,
    +					&len);
    +
    +			if (error != PARSERUTILS_OK && 
    +					error != PARSERUTILS_EOF) {
    +				break;
    +			}
    +
    +			if (tokeniser->context.pending > 0) {
    +				/* Emit any pending characters */
    +				emit_current_chars(tokeniser);
    +			}
    +
    +			if (error == PARSERUTILS_EOF ||	*cptr != '\n') {
    +				/* Emit newline */
    +				emit_character_token(tokeniser, &lf_str);
    +			}
    +
    +			/* Advance over */
    +			parserutils_inputstream_advance(tokeniser->input, 1);
    +		} else {
    +			if (c == '\0') {
    +				/** \todo parse error */
    +				error = parserutils_buffer_append(tokeniser->buffer,
    +				u_fffd, sizeof(u_fffd));
    +				if (error != PARSERUTILS_OK)
    +					return hubbub_error_from_parserutils_error(error);
    +			}
    +
    +			/* Just collect into buffer */
    +			tokeniser->context.pending += len;
    +		}
    +	}
    +	if (tokeniser->context.pending > 0) {
    +		/* Emit any pending characters */
    +		emit_current_chars(tokeniser);
    +	}
    +
    +	if (error == PARSERUTILS_EOF) {
    +		token.type = HUBBUB_TOKEN_EOF;
    +		hubbub_tokeniser_emit_token(tokeniser, &token);
    +	}
    +
    +	if (error == PARSERUTILS_EOF) {
    +		return HUBBUB_NEEDDATA;
    +	} else {
    +		return hubbub_error_from_parserutils_error(error);
    +	}
    +}
    +
    +/* this state always switches to another state straight away */
    +/* this state expects the current character to be '<' */
    +hubbub_error hubbub_tokeniser_handle_tag_open(hubbub_tokeniser *tokeniser)
    +{
    +	hubbub_tag *ctag = &tokeniser->context.current_tag;
    +
    +	size_t len;
    +	const uint8_t *cptr;
    +	parserutils_error error;
    +	uint8_t c;
    +
    +	assert(tokeniser->context.pending == 1);
    +/*	assert(tokeniser->context.chars.ptr[0] == '<'); */
    +
    +	error = parserutils_inputstream_peek(tokeniser->input, 
    +			tokeniser->context.pending, &cptr, &len);
    +
    +	if (error != PARSERUTILS_OK) {
    +		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
    +			/* Emit single '<' char  */
    +			emit_current_chars(tokeniser);
    +			tokeniser->state = STATE_DATA;
    +			return HUBBUB_OK;
    +		} else {
    +			return hubbub_error_from_parserutils_error(error);
    +		}
    +	}
    +
    +	c = *cptr;
    +
    +	if (c == '!') {
    +		parserutils_inputstream_advance(tokeniser->input, SLEN("<!"));
    +
    +		tokeniser->context.pending = 0;
    +		tokeniser->state = STATE_MARKUP_DECLARATION_OPEN;
    +	} else if (c == '/'){
    +		tokeniser->context.pending += len;
    +
    +		tokeniser->context.close_tag_match.match = false;
    +		tokeniser->context.close_tag_match.count = 0;
    +
    +		tokeniser->state = STATE_CLOSE_TAG_OPEN;
    +	} else if ('A' <= c && c <= 'Z') {
    +		uint8_t lc = (c + 0x20);
    +
    +		START_BUF(ctag->name, &lc, len);
    +		ctag->n_attributes = 0;
    +		tokeniser->context.current_tag_type =
    +				HUBBUB_TOKEN_START_TAG;
    +
    +		tokeniser->context.pending += len;
    +
    +		tokeniser->state = STATE_TAG_NAME;
    +	} else if ('a' <= c && c <= 'z') {
    +		START_BUF(ctag->name, cptr, len);
    +		ctag->n_attributes = 0;
    +		tokeniser->context.current_tag_type =
    +				HUBBUB_TOKEN_START_TAG;
    +
    +		tokeniser->context.pending += len;
    +
    +		tokeniser->state = STATE_TAG_NAME;
    +	} else if (c == '?'){
    +		/** \todo parse error */
    +		/* Cursor still at "<", need to advance past it */
    +			parserutils_inputstream_advance(
    +					tokeniser->input, SLEN("<"));
    +			tokeniser->context.pending = 0;
    +
    +			tokeniser->state = STATE_BOGUS_COMMENT;
    +	} else {
    +		/** \todo parse error */
    +		/* Emit single '<' char  */
    +		emit_current_chars(tokeniser);
    +		tokeniser->state = STATE_DATA;
    +	}
    +
    +
    +	return HUBBUB_OK;
    +}
    +
    +/* this state expects tokeniser->context.chars to be "</" */
    +/* this state never stays in this state for more than one character */
    +hubbub_error hubbub_tokeniser_handle_close_tag_open(hubbub_tokeniser *tokeniser)
    +{
    +	size_t len;
    +	const uint8_t *cptr;
    +	parserutils_error error;
    +	uint8_t c;
    +
    +	assert(tokeniser->context.pending == 2);
    +/*	assert(tokeniser->context.chars.ptr[0] == '<'); */
    +/*	assert(tokeniser->context.chars.ptr[1] == '/'); */
    +
    +	error = parserutils_inputstream_peek(tokeniser->input, 
    +			tokeniser->context.pending, &cptr, &len);
    +
    +	if (error != PARSERUTILS_OK) {
    +		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
    +			/* Emit '</' chars  */
    +			emit_current_chars(tokeniser);
    +			tokeniser->state = STATE_DATA;
    +			return HUBBUB_OK;
    +		} else {
    +			return hubbub_error_from_parserutils_error(error);
    +		}
    +	}
    +
    +	c = *cptr;
    +
    +	if ('A' <= c && c <= 'Z') {
    +		uint8_t lc = (c + 0x20);
    +		START_BUF(tokeniser->context.current_tag.name,
    +				&lc, len);
    +		tokeniser->context.current_tag.n_attributes = 0;
    +
    +		tokeniser->context.current_tag_type = HUBBUB_TOKEN_END_TAG;
    +
    +		tokeniser->context.pending += len;
    +
    +		tokeniser->state = STATE_TAG_NAME;
    +	} else if ('a' <= c && c <= 'z') {
    +		START_BUF(tokeniser->context.current_tag.name,
    +				cptr, len);
    +		tokeniser->context.current_tag.n_attributes = 0;
    +
    +		tokeniser->context.current_tag_type = HUBBUB_TOKEN_END_TAG;
    +
    +		tokeniser->context.pending += len;
    +
    +		tokeniser->state = STATE_TAG_NAME;
    +	} else if (c == '>') {
    +		/** \todo parse error */
    +
    +		/* Cursor still at "</", need to collect ">" */
    +		tokeniser->context.pending += len;
    +
    +		/* Now need to advance past "</>" */
    +		parserutils_inputstream_advance(tokeniser->input,
    +				tokeniser->context.pending);
    +		tokeniser->context.pending = 0;
    +
    +		tokeniser->state = STATE_DATA;
    +	} else {
    +		/** \todo parse error */
    +
    +		/* Cursor still at "</", need to advance past it */
    +		parserutils_inputstream_advance(tokeniser->input,
    +				tokeniser->context.pending);
    +		tokeniser->context.pending = 0;
    +
    +		tokeniser->state = STATE_BOGUS_COMMENT;
    +	}
    +
    +	return HUBBUB_OK;
    +}
    +
    +/* this state expects tokeniser->context.current_tag to already have its
    +   first character set */
    +hubbub_error hubbub_tokeniser_handle_tag_name(hubbub_tokeniser *tokeniser)
    +{
    +	hubbub_tag *ctag = &tokeniser->context.current_tag;
    +
    +	size_t len;
    +	const uint8_t *cptr;
    +	parserutils_error error;
    +	uint8_t c;
    +
    +	assert(tokeniser->context.pending > 0);
    +/*	assert(tokeniser->context.chars.ptr[0] == '<'); */
    +	assert(ctag->name.len > 0);
    +/*	assert(ctag->name.ptr); */
    +
    +	error = parserutils_inputstream_peek(tokeniser->input, 
    +			tokeniser->context.pending, &cptr, &len);
    +
    +	if (error != PARSERUTILS_OK) {
    +		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
    +			tokeniser->state = STATE_DATA;
    +
    +			// skips all pending charachters
    +			parserutils_inputstream_advance(
    +					tokeniser->input, tokeniser->context.pending);
    +			return HUBBUB_OK;
    +		} else {
    +			return hubbub_error_from_parserutils_error(error);
    +		}
    +	}
    +
    +	c = *cptr;
    +
    +	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') {
    +		tokeniser->context.pending += len;
    +		tokeniser->state = STATE_BEFORE_ATTRIBUTE_NAME;
    +	} else if (c == '/') {
    +		tokeniser->context.pending += len;
    +		tokeniser->state = STATE_SELF_CLOSING_START_TAG;
    +	} else if (c == '>') {
    +		tokeniser->context.pending += len;
    +		tokeniser->state = STATE_DATA;
    +		return emit_current_tag(tokeniser);
    +	} else if ('A' <= c && c <= 'Z') {
    +		uint8_t lc = (c + 0x20);
    +		COLLECT(ctag->name, &lc, len);
    +		tokeniser->context.pending += len;
    +	} else if (c == '\0') {
    +		COLLECT(ctag->name, u_fffd, sizeof(u_fffd));
    +		tokeniser->context.pending += len;
    +	} else {
    +		COLLECT(ctag->name, cptr, len);
    +		tokeniser->context.pending += len;
    +	}
    +
    +	return HUBBUB_OK;
    +}
    +
    +/* this state always switches to another state straight away */
    +/* this state expects the current character to be '<' */
    +hubbub_error hubbub_tokeniser_handle_rcdata_lessthan(hubbub_tokeniser *tokeniser)
    +{
    +	//hubbub_tag *ctag = &tokeniser->context.current_tag;
    +
    +	size_t len;
    +	const uint8_t *cptr;
    +	parserutils_error error;
    +	uint8_t c;
    +
    +	assert(tokeniser->context.pending == 1);
    +/*	assert(tokeniser->context.chars.ptr[0] == '<'); */
    +
    +	error = parserutils_inputstream_peek(tokeniser->input, 
    +			tokeniser->context.pending, &cptr, &len);
    +
    +	if (error != PARSERUTILS_OK) {
    +		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
    +			/* Emit single '<' char  */
    +			emit_current_chars(tokeniser);
    +			tokeniser->state = STATE_RCDATA;
    +			return HUBBUB_OK;
    +		} else {
    +			return hubbub_error_from_parserutils_error(error);
    +		}
    +	}
    +
    +	c = *cptr;
    +
    +	if (c == '/'){
    +		tokeniser->context.pending += len;
    +
    +		tokeniser->context.close_tag_match.match = false;
    +		tokeniser->context.close_tag_match.count = 0;
    +
    +		tokeniser->state = STATE_RCDATA_CLOSE_TAG_OPEN;
    +	} else {
    +		/* Emit single '<' char  */
    +		emit_current_chars(tokeniser);
    +		tokeniser->state = STATE_RCDATA;
    +	}
    +
    +
    +	return HUBBUB_OK;
    +}
    +
    +/* this state expects tokeniser->context.chars to be "</" */
    +/* this state never stays in this state for more than one character */
    +hubbub_error hubbub_tokeniser_handle_rcdata_close_tag_open(hubbub_tokeniser *tokeniser)
    +{
    +	hubbub_tokeniser_context *ctx = &tokeniser->context;
    +
    +	size_t len;
    +	const uint8_t *cptr;
    +	parserutils_error error;
    +	uint8_t c;
    +
    +	assert(tokeniser->context.pending == 2);
    +/*	assert(tokeniser->context.chars.ptr[0] == '<'); */
    +/*	assert(tokeniser->context.chars.ptr[1] == '/'); */
    +
    +	uint8_t *start_tag_name =
    +			tokeniser->context.last_start_tag_name;
    +	size_t start_tag_len =
    +		tokeniser->context.last_start_tag_len;
     
    -			if (error == PARSERUTILS_EOF ||	*cptr != '\n') {
    -				/* Emit newline */
    -				emit_character_token(tokeniser, &lf_str);
    -			}
    +	while ((error = parserutils_inputstream_peek(tokeniser->input,
    +				ctx->pending +
    +					ctx->close_tag_match.count,
    +				&cptr,
    +				&len)) == PARSERUTILS_OK) {
    +		c = *cptr;
     
    -			/* Advance over */
    -			parserutils_inputstream_advance(tokeniser->input, 1);
    -		} else {
    -			if (c == '\0') {
    -				/** \todo parse error */
    -			}
    +		if ((start_tag_name[ctx->close_tag_match.count] & ~0x20)
    +				!= (c & ~0x20)) {
    +			break;
    +		}
     
    -			/* Just collect into buffer */
    -			tokeniser->context.pending += len;
    +		ctx->close_tag_match.count += len;
    +
    +		if (ctx->close_tag_match.count == start_tag_len) {
    +
    +			// Sets the flag to be used in name state.
    +			ctx->close_tag_match.match = true;
    +			break;
     		}
     	}
    -	if (tokeniser->state != STATE_TAG_OPEN &&
    -		(tokeniser->state != STATE_DATA || error == PARSERUTILS_EOF) &&
    -			tokeniser->context.pending > 0) {
    -		/* Emit any pending characters */
    -		emit_current_chars(tokeniser);
    -	}
     
    -	if (error == PARSERUTILS_EOF) {
    -		token.type = HUBBUB_TOKEN_EOF;
    -		hubbub_tokeniser_emit_token(tokeniser, &token);
    +	if (error != PARSERUTILS_OK) {
    +		if (error == PARSERUTILS_EOF) {
    +			tokeniser->state = STATE_RCDATA;
    +			tokeniser->context.pending += ctx->close_tag_match.count;
    +			return HUBBUB_OK;
    +		} else {
    +			return hubbub_error_from_parserutils_error(error);
    +		}
     	}
     
    -	if (error == PARSERUTILS_EOF) {
    -		return HUBBUB_NEEDDATA;
    -	} else {
    -		return hubbub_error_from_parserutils_error(error);
    +	if (ctx->close_tag_match.match == true) {
    +		error = parserutils_inputstream_peek(
    +				 		tokeniser->input,
    +				 		ctx->pending +
    +					 		ctx->close_tag_match.count,
    +						&cptr,
    +				 		&len);
    +
    +		if (error != PARSERUTILS_OK && 
    +				error != PARSERUTILS_EOF) {
    +			return hubbub_error_from_parserutils_error(
    +					error);
    +		} else if (error != PARSERUTILS_EOF) {
    +			c = *cptr;
    +
    +			if (c != '\t' && c != '\n' && c != '\f' && c != '\r' && 
    +					c != ' ' && c != '>' &&
    +					c != '/') {
    +				ctx->close_tag_match.match = false;
    +			}
    +		}
     	}
    -}
     
    -/* emit any pending tokens before calling */
    -hubbub_error hubbub_tokeniser_handle_character_reference_data(
    -		hubbub_tokeniser *tokeniser)
    -{
    -	assert(tokeniser->context.pending == 0);
    +	if (ctx->close_tag_match.match == true) {
     
    -	if (tokeniser->context.match_entity.complete == false) {
    -		return hubbub_tokeniser_consume_character_reference(tokeniser,
    -				tokeniser->context.pending);
    -	} else {
    -		hubbub_token token;
    +		tokeniser->state = STATE_RCDATA_CLOSE_TAG_NAME;
     
    -		uint8_t utf8[6];
    -		uint8_t *utf8ptr = utf8;
    -		size_t len = sizeof(utf8);
    +		// Creates a new buffer and sets first charachter of the tag name 
    +		START_BUF(ctx->current_tag.name,
    +					&start_tag_name[0], len);
    +		tokeniser->context.current_tag.n_attributes = 0;
     
    -		token.type = HUBBUB_TOKEN_CHARACTER;
    +		tokeniser->context.current_tag_type =
    +				HUBBUB_TOKEN_END_TAG;
     
    -		if (tokeniser->context.match_entity.codepoint) {
    -			parserutils_charset_utf8_from_ucs4(
    -				tokeniser->context.match_entity.codepoint,
    -				&utf8ptr, &len);
    +		tokeniser->context.pending += len;
     
    -			token.data.character.ptr = utf8;
    -			token.data.character.len = sizeof(utf8) - len;
    +		tokeniser->state = STATE_RCDATA_CLOSE_TAG_NAME;
    +	} else {
    +		emit_current_chars(tokeniser);
    +		tokeniser->state = STATE_RCDATA;
    +	}
     
    -			hubbub_tokeniser_emit_token(tokeniser, &token);
    +	return HUBBUB_OK;
    +}
     
    -			/* +1 for ampersand */
    -			parserutils_inputstream_advance(tokeniser->input,
    -					tokeniser->context.match_entity.length
    -							+ 1);
    -		} else {
    -			parserutils_error error;
    -			const uint8_t *cptr = NULL;
    +/* this state expects tokeniser->context.current_tag to already have its
    +   first character set */
    +hubbub_error hubbub_tokeniser_handle_rcdata_close_tag_name(hubbub_tokeniser *tokeniser)
    +{
    +	hubbub_tokeniser_context *ctx = &tokeniser->context;
     
    -			error = parserutils_inputstream_peek(
    -					tokeniser->input,
    -					tokeniser->context.pending,
    -					&cptr,
    -					&len);
    -			if (error != PARSERUTILS_OK) {
    -				return hubbub_error_from_parserutils_error(
    -						error);
    -			}
    +	size_t len;
    +	const uint8_t *cptr;
    +	parserutils_error error;
    +	uint8_t c;
     
    -			token.data.character.ptr = cptr;
    -			token.data.character.len = len;
    +	assert(tokeniser->context.pending > 0);
    +/*	assert(tokeniser->context.chars.ptr[0] == '<'); */
    +	assert(ctx.current_tag->name.len > 0);
    +/*	assert(ctx.current_tag->name.ptr); */
     
    -			hubbub_tokeniser_emit_token(tokeniser, &token);
    -			parserutils_inputstream_advance(tokeniser->input, len);
    +	error = parserutils_inputstream_peek(tokeniser->input, 
    +			tokeniser->context.pending, &cptr, &len);
    +
    +	if (error != PARSERUTILS_OK) {
    +		if (error == PARSERUTILS_EOF) {
    +			/** \todo parse error */
    +			tokeniser->state = STATE_RCDATA;
    +			return HUBBUB_OK;
    +		} else {
    +			return hubbub_error_from_parserutils_error(error);
     		}
    +	}
     
    -		/* Reset for next time */
    -		tokeniser->context.match_entity.complete = false;
    +	c = *cptr;
     
    +	if ((c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r')
    +		&& ctx->close_tag_match.match == true) {
    +		// Add condition for approproiate end tag token
    +		tokeniser->context.pending += len;
    +		tokeniser->state = STATE_BEFORE_ATTRIBUTE_NAME;
    +	} else if (c == '/' && ctx->close_tag_match.match == true) {
    +		// Add condition for approproiate end tag token
    +		tokeniser->context.pending += len;
    +		tokeniser->state = STATE_SELF_CLOSING_START_TAG;
    +	} else if (c == '>' && ctx->close_tag_match.match == true) {
    +		// Add condition for approproiate end tag token
    +		tokeniser->context.pending += len;
     		tokeniser->state = STATE_DATA;
    +		return emit_current_tag(tokeniser);
    +	} else if ('A' <= c && c <= 'Z') {
    +		uint8_t lc = (c + 0x20);
    +		COLLECT(ctx->current_tag.name, &lc, len);
    +		tokeniser->context.pending += len;
    +	} else if ('a' <= c && c <= 'z') {
    +		COLLECT(ctx->current_tag.name, cptr, len);
    +		tokeniser->context.pending += len;
    +	} else {
    +		tokeniser->state = STATE_RCDATA;
    +		return emit_current_chars(tokeniser);
     	}
     
     	return HUBBUB_OK;
    @@ -807,9 +1686,9 @@ hubbub_error hubbub_tokeniser_handle_character_reference_data(
     
     /* this state always switches to another state straight away */
     /* this state expects the current character to be '<' */
    -hubbub_error hubbub_tokeniser_handle_tag_open(hubbub_tokeniser *tokeniser)
    +hubbub_error hubbub_tokeniser_handle_rawtext_lessthan(hubbub_tokeniser *tokeniser)
     {
    -	hubbub_tag *ctag = &tokeniser->context.current_tag;
    +	//hubbub_tag *ctag = &tokeniser->context.current_tag;
     
     	size_t len;
     	const uint8_t *cptr;
    @@ -827,7 +1706,7 @@ hubbub_error hubbub_tokeniser_handle_tag_open(hubbub_tokeniser *tokeniser)
     			/** \todo parse error */
     			/* Emit single '<' char  */
     			emit_current_chars(tokeniser);
    -			tokeniser->state = STATE_DATA;
    +			tokeniser->state = STATE_RAWTEXT;
     			return HUBBUB_OK;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
    @@ -836,51 +1715,17 @@ hubbub_error hubbub_tokeniser_handle_tag_open(hubbub_tokeniser *tokeniser)
     
     	c = *cptr;
     
    -	if (c == '!') {
    -		parserutils_inputstream_advance(tokeniser->input, SLEN("<!"));
    -
    -		tokeniser->context.pending = 0;
    -		tokeniser->state = STATE_MARKUP_DECLARATION_OPEN;
    -	} else if (c == '/'){
    +	if (c == '/'){
     		tokeniser->context.pending += len;
     
     		tokeniser->context.close_tag_match.match = false;
     		tokeniser->context.close_tag_match.count = 0;
     
    -		tokeniser->state = STATE_CLOSE_TAG_OPEN;
    -	} else if ('A' <= c && c <= 'Z') {
    -		uint8_t lc = (c + 0x20);
    -
    -		START_BUF(ctag->name, &lc, len);
    -		ctag->n_attributes = 0;
    -		tokeniser->context.current_tag_type =
    -				HUBBUB_TOKEN_START_TAG;
    -
    -		tokeniser->context.pending += len;
    -
    -		tokeniser->state = STATE_TAG_NAME;
    -	} else if ('a' <= c && c <= 'z') {
    -		START_BUF(ctag->name, cptr, len);
    -		ctag->n_attributes = 0;
    -		tokeniser->context.current_tag_type =
    -				HUBBUB_TOKEN_START_TAG;
    -
    -		tokeniser->context.pending += len;
    -
    -		tokeniser->state = STATE_TAG_NAME;
    -	} else if (c == '?'){
    -		/** \todo parse error */
    -		/* Cursor still at "<", need to advance past it */
    -			parserutils_inputstream_advance(
    -					tokeniser->input, SLEN("<"));
    -			tokeniser->context.pending = 0;
    -
    -			tokeniser->state = STATE_BOGUS_COMMENT;
    +		tokeniser->state = STATE_RAWTEXT_CLOSE_TAG_OPEN;
     	} else {
    -		/** \todo parse error */
     		/* Emit single '<' char  */
     		emit_current_chars(tokeniser);
    -		tokeniser->state = STATE_DATA;
    +		tokeniser->state = STATE_RCDATA;
     	}
     
     
    @@ -889,8 +1734,10 @@ hubbub_error hubbub_tokeniser_handle_tag_open(hubbub_tokeniser *tokeniser)
     
     /* this state expects tokeniser->context.chars to be "</" */
     /* this state never stays in this state for more than one character */
    -hubbub_error hubbub_tokeniser_handle_close_tag_open(hubbub_tokeniser *tokeniser)
    +hubbub_error hubbub_tokeniser_handle_rawtext_close_tag_open(hubbub_tokeniser *tokeniser)
     {
    +	hubbub_tokeniser_context *ctx = &tokeniser->context;
    +
     	size_t len;
     	const uint8_t *cptr;
     	parserutils_error error;
    @@ -900,65 +1747,84 @@ hubbub_error hubbub_tokeniser_handle_close_tag_open(hubbub_tokeniser *tokeniser)
     /*	assert(tokeniser->context.chars.ptr[0] == '<'); */
     /*	assert(tokeniser->context.chars.ptr[1] == '/'); */
     
    -	error = parserutils_inputstream_peek(tokeniser->input, 
    -			tokeniser->context.pending, &cptr, &len);
    +	uint8_t *start_tag_name =
    +			tokeniser->context.last_start_tag_name;
    +	size_t start_tag_len =
    +		tokeniser->context.last_start_tag_len;
    +
    +	while ((error = parserutils_inputstream_peek(tokeniser->input,
    +				ctx->pending +
    +					ctx->close_tag_match.count,
    +				&cptr,
    +				&len)) == PARSERUTILS_OK) {
    +		c = *cptr;
    +
    +		if ((start_tag_name[ctx->close_tag_match.count] & ~0x20)
    +				!= (c & ~0x20)) {
    +			break;
    +		}
    +
    +		ctx->close_tag_match.count += len;
    +
    +		if (ctx->close_tag_match.count == start_tag_len) {
    +
    +			// Sets the flag to be used in name state.
    +			ctx->close_tag_match.match = true;
    +			break;
    +		}
    +	}
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    -			/** \todo parse error */
    -			/* Emit '</' chars  */
    -			emit_current_chars(tokeniser);
    -			tokeniser->state = STATE_DATA;
    +			tokeniser->state = STATE_RAWTEXT;
    +			tokeniser->context.pending += ctx->close_tag_match.count;
     			return HUBBUB_OK;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
     		}
     	}
     
    -	c = *cptr;
    +	if (ctx->close_tag_match.match == true) {
    +		error = parserutils_inputstream_peek(
    +				 		tokeniser->input,
    +				 		ctx->pending +
    +					 		ctx->close_tag_match.count,
    +						&cptr,
    +				 		&len);
    +
    +		if (error != PARSERUTILS_OK && 
    +				error != PARSERUTILS_EOF) {
    +			return hubbub_error_from_parserutils_error(
    +					error);
    +		} else if (error != PARSERUTILS_EOF) {
    +			c = *cptr;
     
    -	if ('A' <= c && c <= 'Z') {
    -		uint8_t lc = (c + 0x20);
    -		START_BUF(tokeniser->context.current_tag.name,
    -				&lc, len);
    -		tokeniser->context.current_tag.n_attributes = 0;
    +			if (c != '\t' && c != '\n' && c != '\f' && c != '\r' && 
    +					c != ' ' && c != '>' &&
    +					c != '/') {
    +				ctx->close_tag_match.match = false;
    +			}
    +		}
    +	}
     
    -		tokeniser->context.current_tag_type = HUBBUB_TOKEN_END_TAG;
    +	if (ctx->close_tag_match.match == true) {
     
    -		tokeniser->context.pending += len;
    +		tokeniser->state = STATE_RCDATA_CLOSE_TAG_NAME;
     
    -		tokeniser->state = STATE_TAG_NAME;
    -	} else if ('a' <= c && c <= 'z') {
    -		START_BUF(tokeniser->context.current_tag.name,
    -				cptr, len);
    +		// Creates a new buffer and sets first charachter of the tag name 
    +		START_BUF(ctx->current_tag.name,
    +					&start_tag_name[0], len);
     		tokeniser->context.current_tag.n_attributes = 0;
     
    -		tokeniser->context.current_tag_type = HUBBUB_TOKEN_END_TAG;
    -
    -		tokeniser->context.pending += len;
    -
    -		tokeniser->state = STATE_TAG_NAME;
    -	} else if (c == '>') {
    -		/** \todo parse error */
    +		tokeniser->context.current_tag_type =
    +				HUBBUB_TOKEN_END_TAG;
     
    -		/* Cursor still at "</", need to collect ">" */
     		tokeniser->context.pending += len;
     
    -		/* Now need to advance past "</>" */
    -		parserutils_inputstream_advance(tokeniser->input,
    -				tokeniser->context.pending);
    -		tokeniser->context.pending = 0;
    -
    -		tokeniser->state = STATE_DATA;
    +		tokeniser->state = STATE_RAWTEXT_CLOSE_TAG_NAME;
     	} else {
    -		/** \todo parse error */
    -
    -		/* Cursor still at "</", need to advance past it */
    -		parserutils_inputstream_advance(tokeniser->input,
    -				tokeniser->context.pending);
    -		tokeniser->context.pending = 0;
    -
    -		tokeniser->state = STATE_BOGUS_COMMENT;
    +		emit_current_chars(tokeniser);
    +		tokeniser->state = STATE_RAWTEXT;
     	}
     
     	return HUBBUB_OK;
    @@ -966,9 +1832,9 @@ hubbub_error hubbub_tokeniser_handle_close_tag_open(hubbub_tokeniser *tokeniser)
     
     /* this state expects tokeniser->context.current_tag to already have its
        first character set */
    -hubbub_error hubbub_tokeniser_handle_tag_name(hubbub_tokeniser *tokeniser)
    +hubbub_error hubbub_tokeniser_handle_rawtext_close_tag_name(hubbub_tokeniser *tokeniser)
     {
    -	hubbub_tag *ctag = &tokeniser->context.current_tag;
    +	hubbub_tokeniser_context *ctx = &tokeniser->context;
     
     	size_t len;
     	const uint8_t *cptr;
    @@ -985,12 +1851,9 @@ hubbub_error hubbub_tokeniser_handle_tag_name(hubbub_tokeniser *tokeniser)
     
     	if (error != PARSERUTILS_OK) {
     		if (error == PARSERUTILS_EOF) {
    -			/** \todo parse error */
    -			tokeniser->state = STATE_DATA;
    +			tokeniser->state = STATE_RAWTEXT;
     
    -			// skips all pending charachters
    -			parserutils_inputstream_advance(
    -					tokeniser->input, tokeniser->context.pending);
    +			emit_current_chars(tokeniser);
     			return HUBBUB_OK;
     		} else {
     			return hubbub_error_from_parserutils_error(error);
    @@ -999,26 +1862,30 @@ hubbub_error hubbub_tokeniser_handle_tag_name(hubbub_tokeniser *tokeniser)
     
     	c = *cptr;
     
    -	if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') {
    +	if ((c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r')
    +		&& ctx->close_tag_match.match == true) {
    +		// Add condition for approproiate end tag token
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_BEFORE_ATTRIBUTE_NAME;
    -	} else if (c == '/') {
    +	} else if (c == '/' && ctx->close_tag_match.match == true) {
    +		// Add condition for approproiate end tag token
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_SELF_CLOSING_START_TAG;
    -	} else if (c == '>') {
    +	} else if (c == '>' && ctx->close_tag_match.match == true) {
    +		// Add condition for approproiate end tag token
     		tokeniser->context.pending += len;
     		tokeniser->state = STATE_DATA;
     		return emit_current_tag(tokeniser);
     	} else if ('A' <= c && c <= 'Z') {
     		uint8_t lc = (c + 0x20);
    -		COLLECT(ctag->name, &lc, len);
    +		COLLECT(ctx->current_tag.name, &lc, len);
     		tokeniser->context.pending += len;
    -	} else if (c == '\0') {
    -		COLLECT(ctag->name, u_fffd, sizeof(u_fffd));
    +	} else if ('a' <= c && c <= 'z') {
    +		COLLECT(ctx->current_tag.name, cptr, len);
     		tokeniser->context.pending += len;
     	} else {
    -		COLLECT(ctag->name, cptr, len);
    -		tokeniser->context.pending += len;
    +		tokeniser->state = STATE_RAWTEXT;
    +		return emit_current_chars(tokeniser);
     	}
     
     	return HUBBUB_OK;
    @@ -3315,7 +4182,7 @@ hubbub_error emit_current_tag(hubbub_tokeniser *tokeniser)
     	err = hubbub_tokeniser_emit_token(tokeniser, &token);
     
     	if (token.type == HUBBUB_TOKEN_START_TAG) {
    -		/* Save start tag name for R?CDATA */
    +		/* Save start tag name for R?CDATA states */
     		if (token.data.tag.name.len <
     			sizeof(tokeniser->context.last_start_tag_name)) {
     			strncpy((char *) tokeniser->context.last_start_tag_name,
    @@ -3328,8 +4195,9 @@ hubbub_error emit_current_tag(hubbub_tokeniser *tokeniser)
     			tokeniser->context.last_start_tag_len = 0;
     		}
     	} else /* if (token->type == HUBBUB_TOKEN_END_TAG) */ {
    -		/* Reset content model after R?CDATA elements */
    -		tokeniser->content_model = HUBBUB_CONTENT_MODEL_PCDATA;
    +		/* Reset content model (i.e state will be now STATE_DATA)
    +			 after R?CDATA elements */
    +		tokeniser->state = STATE_DATA;
     	}
     
     	/* Reset the self-closing flag */
    diff --git a/src/tokeniser/tokeniser.h b/src/tokeniser/tokeniser.h
    index 5700923..cd8f662 100644
    --- a/src/tokeniser/tokeniser.h
    +++ b/src/tokeniser/tokeniser.h
    @@ -25,7 +25,7 @@ typedef struct hubbub_tokeniser hubbub_tokeniser;
     typedef enum hubbub_tokeniser_opttype {
     	HUBBUB_TOKENISER_TOKEN_HANDLER,
     	HUBBUB_TOKENISER_ERROR_HANDLER,
    -	HUBBUB_TOKENISER_CONTENT_MODEL,
    +	HUBBUB_TOKENISER_INITIAL_STATE,
     	HUBBUB_TOKENISER_PROCESS_CDATA,
     	HUBBUB_TOKENISER_PAUSE
     } hubbub_tokeniser_opttype;
    @@ -45,8 +45,8 @@ typedef union hubbub_tokeniser_optparams {
     	} error_handler;		/**< Error handling callback */
     
     	struct {
    -		hubbub_content_model model;
    -	} content_model;		/**< Current content model */
    +		hubbub_initial_state state;
    +	} initial_state;		/**< Initial State of the tokeniser */
     
     	bool process_cdata;		/**< Whether to process CDATA sections*/
     
    diff --git a/src/treebuilder/in_body.c b/src/treebuilder/in_body.c
    index 5157e66..d16a365 100644
    --- a/src/treebuilder/in_body.c
    +++ b/src/treebuilder/in_body.c
    @@ -740,10 +740,10 @@ hubbub_error process_plaintext_in_body(hubbub_treebuilder *treebuilder,
     	if (err != HUBBUB_OK)
     		return err;
     
    -	params.content_model.model = HUBBUB_CONTENT_MODEL_PLAINTEXT;
    +	params.initial_state.state = HUBBUB_INITIAL_STATE_PLAINTEXT;
     
     	err = hubbub_tokeniser_setopt(treebuilder->tokeniser,
    -			HUBBUB_TOKENISER_CONTENT_MODEL,
    +			HUBBUB_TOKENISER_INITIAL_STATE,
     			&params);
     	assert(err == HUBBUB_OK);
     
    diff --git a/src/treebuilder/treebuilder.c b/src/treebuilder/treebuilder.c
    index a6a4b43..5784a83 100644
    --- a/src/treebuilder/treebuilder.c
    +++ b/src/treebuilder/treebuilder.c
    @@ -473,10 +473,10 @@ hubbub_error parse_generic_rcdata(hubbub_treebuilder *treebuilder,
     	if (error != HUBBUB_OK)
     		return error;
     
    -	params.content_model.model = rcdata ? HUBBUB_CONTENT_MODEL_RCDATA
    -					    : HUBBUB_CONTENT_MODEL_CDATA;
    +	params.initial_state.state = rcdata ? HUBBUB_INITIAL_STATE_RCDATA
    +					    : HUBBUB_INITIAL_STATE_CDATA;
     	error = hubbub_tokeniser_setopt(treebuilder->tokeniser,
    -				HUBBUB_TOKENISER_CONTENT_MODEL, &params);
    +				HUBBUB_TOKENISER_INITIAL_STATE, &params);
     	/* There is no way that setopt can fail. Ensure this. */
     	assert(error == HUBBUB_OK);
     
    diff --git a/test/data/tokeniser2/contentModelFlags.test b/test/data/tokeniser2/contentModelFlags.test
    index 1dec3e8..a8b1695 100644
    --- a/test/data/tokeniser2/contentModelFlags.test
    +++ b/test/data/tokeniser2/contentModelFlags.test
    @@ -1,73 +1,73 @@
     {"tests": [
     
     {"description":"PLAINTEXT content model flag",
    -"contentModelFlags":["PLAINTEXT"],
    +"initialStates":["PLAINTEXT state"],
     "lastStartTag":"plaintext",
     "input":"<head>&body;",
     "output":[["Character", "<head>&body;"]]},
     
    -{"description":"End tag closing RCDATA or CDATA",
    -"contentModelFlags":["RCDATA", "CDATA"],
    +{"description":"End tag closing RCDATA or RAWTEXT",
    +"initialStates":["RCDATA state", "RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"foo</xmp>",
     "output":[["Character", "foo"], ["EndTag", "xmp"]]},
     
    -{"description":"End tag closing RCDATA or CDATA (case-insensitivity)",
    -"contentModelFlags":["RCDATA", "CDATA"],
    +{"description":"End tag closing RCDATA or RAWTEXT (case-insensitivity)",
    +"initialStates":["RCDATA state", "RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"foo</xMp>",
     "output":[["Character", "foo"], ["EndTag", "xmp"]]},
     
    -{"description":"End tag closing RCDATA or CDATA (ending with space)",
    -"contentModelFlags":["RCDATA", "CDATA"],
    +{"description":"End tag closing RCDATA or RAWTEXT (ending with space)",
    +"initialStates":["RCDATA state", "RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"foo</xmp ",
    -"output":[["Character", "foo"], "ParseError", ["EndTag", "xmp"]]},
    +"output":[["Character", "foo"], "ParseError"]},
     
    -{"description":"End tag closing RCDATA or CDATA (ending with EOF)",
    -"contentModelFlags":["RCDATA", "CDATA"],
    +{"description":"End tag closing RCDATA or RAWTEXT (ending with EOF)",
    +"initialStates":["RCDATA state", "RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"foo</xmp",
    -"output":[["Character", "foo"], "ParseError", ["EndTag", "xmp"]]},
    +"output":[["Character", "foo</xmp"]]},
     
    -{"description":"End tag closing RCDATA or CDATA (ending with slash)",
    -"contentModelFlags":["RCDATA", "CDATA"],
    +{"description":"End tag closing RCDATA or RAWTEXT (ending with slash)",
    +"initialStates":["RCDATA state", "RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"foo</xmp/",
    -"output":[["Character", "foo"], "ParseError", ["EndTag", "xmp"]]},
    +"output":[["Character", "foo"], "ParseError"]},
     
    -{"description":"End tag not closing RCDATA or CDATA (ending with left-angle-bracket)",
    -"contentModelFlags":["RCDATA", "CDATA"],
    +{"description":"End tag not closing RCDATA or RAWTEXT (ending with left-angle-bracket)",
    +"initialStates":["RCDATA state", "RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"foo</xmp<",
     "output":[["Character", "foo</xmp<"]]},
     
    -{"description":"End tag with incorrect name in RCDATA or CDATA",
    -"contentModelFlags":["RCDATA", "CDATA"],
    +{"description":"End tag with incorrect name in RCDATA or RAWTEXT",
    +"initialStates":["RCDATA state", "RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"</foo>bar</xmp>",
     "output":[["Character", "</foo>bar"], ["EndTag", "xmp"]]},
     
    -{"description":"End tag with incorrect name in RCDATA or CDATA (starting like correct name)",
    -"contentModelFlags":["RCDATA", "CDATA"],
    +{"description":"End tag with incorrect name in RCDATA or RAWTEXT (starting like correct name)",
    +"initialStates":["RCDATA state", "RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"</foo>bar</xmpaar>",
     "output":[["Character", "</foo>bar</xmpaar>"]]},
     
    -{"description":"End tag closing RCDATA or CDATA, switching back to PCDATA",
    -"contentModelFlags":["RCDATA", "CDATA"],
    +{"description":"End tag closing RCDATA or RAWTEXT, switching back to PCDATA",
    +"initialStates":["RCDATA state", "RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"foo</xmp></baz>",
     "output":[["Character", "foo"], ["EndTag", "xmp"], ["EndTag", "baz"]]},
     
    -{"description":"CDATA w/ something looking like an entity",
    -"contentModelFlags":["CDATA"],
    +{"description":"RAWTEXT w/ something looking like an entity",
    +"initialStates":["RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"&foo;",
     "output":[["Character", "&foo;"]]},
     
     {"description":"RCDATA w/ an entity",
    -"contentModelFlags":["RCDATA"],
    +"initialStates":["RCDATA state"],
     "lastStartTag":"textarea",
     "input":"&lt;",
     "output":[["Character", "<"]]}
    diff --git a/test/data/tokeniser2/escapeFlag.test b/test/data/tokeniser2/escapeFlag.test
    index 4c4bf51..18cb430 100644
    --- a/test/data/tokeniser2/escapeFlag.test
    +++ b/test/data/tokeniser2/escapeFlag.test
    @@ -1,33 +1,33 @@
     {"tests": [
     
    -{"description":"Commented close tag in [R]CDATA",
    -"contentModelFlags":["RCDATA", "CDATA"],
    +{"description":"Commented close tag in RCDATA or RAWTEXT",
    +"initialStates":["RCDATA state", "RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"foo<!--</xmp>--></xmp>",
    -"output":[["Character", "foo<!--</xmp>-->"], ["EndTag", "xmp"]]},
    +"output":[["Character", "foo<!--"], ["EndTag", "xmp"], ["Character", "-->"], ["EndTag", "xmp"]]},
     
    -{"description":"Bogus comment in [R]CDATA",
    -"contentModelFlags":["RCDATA", "CDATA"],
    +{"description":"Bogus comment in RCDATA or RAWTEXT",
    +"initialStates":["RCDATA state", "RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"foo<!-->baz</xmp>",
     "output":[["Character", "foo<!-->baz"], ["EndTag", "xmp"]]},
     
    -{"description":"End tag surrounded by bogus comment in [R]CDATA",
    -"contentModelFlags":["RCDATA", "CDATA"],
    +{"description":"End tag surrounded by bogus comment in RCDATA or RAWTEXT",
    +"initialStates":["RCDATA state", "RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"foo<!--></xmp><!-->baz</xmp>",
     "output":[["Character", "foo<!-->"], ["EndTag", "xmp"], "ParseError", ["Comment", ""], ["Character", "baz"], ["EndTag", "xmp"]]},
     
     {"description":"Commented entities in RCDATA",
    -"contentModelFlags":["RCDATA"],
    +"initialStates":["RCDATA state"],
     "lastStartTag":"xmp",
     "input":" &amp; <!-- &amp; --> &amp; </xmp>",
    -"output":[["Character", " & <!-- &amp; --> & "], ["EndTag", "xmp"]]},
    +"output":[["Character", " & <!-- & --> & "], ["EndTag", "xmp"]]},
     
    -{"description":"Incorrect comment ending sequences in [R]CDATA",
    -"contentModelFlags":["RCDATA", "CDATA"],
    +{"description":"Incorrect comment ending sequences in RCDATA or RAWTEXT",
    +"initialStates":["RCDATA state", "RAWTEXT state"],
     "lastStartTag":"xmp",
     "input":"foo<!-- x --x>x-- >x--!>x--<></xmp>",
    -"output":[["Character", "foo<!-- x --x>x-- >x--!>x--<></xmp>"]]}
    +"output":[["Character", "foo<!-- x --x>x-- >x--!>x--<>"], ["EndTag", "xmp"]]}
     
     ]}
    diff --git a/test/tokeniser2.c b/test/tokeniser2.c
    index c320f42..d9bc3c1 100644
    --- a/test/tokeniser2.c
    +++ b/test/tokeniser2.c
    @@ -27,7 +27,7 @@ typedef struct context {
     	size_t char_off;
     
     	const char *last_start_tag;
    -	struct array_list *content_model;
    +	struct array_list *initial_state;
     	bool process_cdata;
     } context;
     
    @@ -65,7 +65,7 @@ int main(int argc, char **argv)
     			(struct json_object *) array_list_get_idx(tests, i);
     
     		ctx.last_start_tag = NULL;
    -		ctx.content_model = NULL;
    +		ctx.initial_state = NULL;
     		ctx.process_cdata = false;
     
     		/* Extract settings */
    @@ -88,8 +88,8 @@ int main(int argc, char **argv)
     			} else if (strcmp(key, "lastStartTag") == 0) {
     				ctx.last_start_tag = (const char *)
     						json_object_get_string(val);
    -			} else if (strcmp(key, "contentModelFlags") == 0) {
    -				ctx.content_model =
    +			} else if (strcmp(key, "initialStates") == 0) {
    +				ctx.initial_state =
     						json_object_get_array(val);
     			} else if (strcmp(key, "processCDATA") == 0) {
     				ctx.process_cdata =
    @@ -116,10 +116,10 @@ void run_test(context *ctx)
     	int i, max_i;
     	struct array_list *outputsave = ctx->output;
     
    -	if (ctx->content_model == NULL) {
    +	if (ctx->initial_state == NULL) {
     		max_i = 1;
     	} else {
    -		max_i = array_list_length(ctx->content_model);
    +		max_i = array_list_length(ctx->initial_state);
     	}
     
     	/* We test for each of the content models specified */
    @@ -163,30 +163,35 @@ void run_test(context *ctx)
     				HUBBUB_TOKENISER_TOKEN_HANDLER,
     				&params) == HUBBUB_OK);
     
    -		if (ctx->content_model == NULL) {
    -			params.content_model.model =
    -					HUBBUB_CONTENT_MODEL_PCDATA;
    +		if (ctx->initial_state == NULL) {
    +			params.initial_state.state =
    +					HUBBUB_INITIAL_STATE_DATA;
     		} else {
     			const char *cm = json_object_get_string(
     				(struct json_object *)
    -				array_list_get_idx(ctx->content_model, i));
    +				array_list_get_idx(ctx->initial_state, i));
     
     			if (strcmp(cm, "PCDATA") == 0) {
    -				params.content_model.model =
    -						HUBBUB_CONTENT_MODEL_PCDATA;
    -			} else if (strcmp(cm, "RCDATA") == 0) {
    -				params.content_model.model =
    -						HUBBUB_CONTENT_MODEL_RCDATA;
    -			} else if (strcmp(cm, "CDATA") == 0) {
    -				params.content_model.model =
    -						HUBBUB_CONTENT_MODEL_CDATA;
    +				params.initial_state.state =
    +						HUBBUB_INITIAL_STATE_DATA;
    +			} else if (strcmp(cm, "RCDATA state") == 0) {
    +				
    +				params.initial_state.state =
    +						HUBBUB_INITIAL_STATE_RCDATA;
    +			} else if (strcmp(cm, "CDATA state") == 0) {
    +				params.initial_state.state =
    +						HUBBUB_INITIAL_STATE_CDATA;
    +			} else if (strcmp(cm, "RAWTEXT state") == 0) {
    +			params.initial_state.state =
    +						HUBBUB_INITIAL_STATE_RAWTEXT;
     			} else {
    -				params.content_model.model =
    -					HUBBUB_CONTENT_MODEL_PLAINTEXT;
    +			params.initial_state.state =
    +					HUBBUB_INITIAL_STATE_PLAINTEXT;
     			}
     		}
    +
     		assert(hubbub_tokeniser_setopt(tok,
    -				HUBBUB_TOKENISER_CONTENT_MODEL,
    +				HUBBUB_TOKENISER_INITIAL_STATE,
     				&params) == HUBBUB_OK);
     
     		assert(parserutils_inputstream_append(stream,
    -- 
    1.8.3.2
    
    
  • patch file icon 0003-Fix-tokeniser-test-executer-for-content-model-replac.patch (4,014 bytes) 2014-03-11 17:01 -
    From 63739d3e61df0d30a520070b45ecc86e2aa771e7 Mon Sep 17 00:00:00 2001
    From: Achal-Aggarwal <theachalaggarwal@gmail.com>
    Date: Tue, 11 Mar 2014 18:04:11 +0530
    Subject: [PATCH 3/4] Fix tokeniser test executer for content model
     replacement.
    
    ---
     test/tokeniser2.c |  1 -
     test/tokeniser3.c | 48 +++++++++++++++++++++++++++---------------------
     2 files changed, 27 insertions(+), 22 deletions(-)
    
    diff --git a/test/tokeniser2.c b/test/tokeniser2.c
    index d9bc3c1..db7c8f8 100644
    --- a/test/tokeniser2.c
    +++ b/test/tokeniser2.c
    @@ -175,7 +175,6 @@ void run_test(context *ctx)
     				params.initial_state.state =
     						HUBBUB_INITIAL_STATE_DATA;
     			} else if (strcmp(cm, "RCDATA state") == 0) {
    -				
     				params.initial_state.state =
     						HUBBUB_INITIAL_STATE_RCDATA;
     			} else if (strcmp(cm, "CDATA state") == 0) {
    diff --git a/test/tokeniser3.c b/test/tokeniser3.c
    index 949ddd0..7ce2602 100644
    --- a/test/tokeniser3.c
    +++ b/test/tokeniser3.c
    @@ -14,6 +14,8 @@
     
     #include "testutils.h"
     
    +#define strlen n_str
    +
     typedef struct context {
     	const uint8_t *input;
     	size_t input_len;
    @@ -23,7 +25,7 @@ typedef struct context {
     	size_t char_off;
     
     	const char *last_start_tag;
    -	struct array_list *content_model;
    +	struct array_list *initial_state;
     	bool process_cdata;
     } context;
     
    @@ -61,7 +63,7 @@ int main(int argc, char **argv)
     			(struct json_object *) array_list_get_idx(tests, i);
     
     		ctx.last_start_tag = NULL;
    -		ctx.content_model = NULL;
    +		ctx.initial_state = NULL;
     		ctx.process_cdata = false;
     
     		/* Extract settings */
    @@ -85,8 +87,8 @@ int main(int argc, char **argv)
     			} else if (strcmp(key, "lastStartTag") == 0) {
     				ctx.last_start_tag = (const char *)
     						json_object_get_string(val);
    -			} else if (strcmp(key, "contentModelFlags") == 0) {
    -				ctx.content_model =
    +			} else if (strcmp(key, "initialStates") == 0) {
    +				ctx.initial_state =
     						json_object_get_array(val);
     			} else if (strcmp(key, "processCDATA") == 0) {
     				ctx.process_cdata =
    @@ -112,10 +114,10 @@ void run_test(context *ctx)
     	size_t j;
     	struct array_list *outputsave = ctx->output;
     
    -	if (ctx->content_model == NULL) {
    +	if (ctx->initial_state == NULL) {
     		max_i = 1;
     	} else {
    -		max_i = array_list_length(ctx->content_model);
    +		max_i = array_list_length(ctx->initial_state);
     	}
     
     	/* We test for each of the content models specified */
    @@ -159,30 +161,34 @@ void run_test(context *ctx)
     				HUBBUB_TOKENISER_TOKEN_HANDLER,
     				&params) == HUBBUB_OK);
     
    -		if (ctx->content_model == NULL) {
    -			params.content_model.model =
    -					HUBBUB_CONTENT_MODEL_PCDATA;
    +		if (ctx->initial_state == NULL) {
    +			params.initial_state.state =
    +					HUBBUB_INITIAL_STATE_DATA;
     		} else {
     			const char *cm = json_object_get_string(
     				(struct json_object *)
    -				array_list_get_idx(ctx->content_model, i));
    +				array_list_get_idx(ctx->initial_state, i));
     
     			if (strcmp(cm, "PCDATA") == 0) {
    -				params.content_model.model =
    -						HUBBUB_CONTENT_MODEL_PCDATA;
    -			} else if (strcmp(cm, "RCDATA") == 0) {
    -				params.content_model.model =
    -						HUBBUB_CONTENT_MODEL_RCDATA;
    -			} else if (strcmp(cm, "CDATA") == 0) {
    -				params.content_model.model =
    -						HUBBUB_CONTENT_MODEL_CDATA;
    +				params.initial_state.state =
    +						HUBBUB_INITIAL_STATE_DATA;
    +			} else if (strcmp(cm, "RCDATA state") == 0) {
    +				params.initial_state.state =
    +						HUBBUB_INITIAL_STATE_RCDATA;
    +			} else if (strcmp(cm, "CDATA state") == 0) {
    +				params.initial_state.state =
    +						HUBBUB_INITIAL_STATE_CDATA;
    +			} else if (strcmp(cm, "RAWTEXT state") == 0) {
    +			params.initial_state.state =
    +						HUBBUB_INITIAL_STATE_RAWTEXT;
     			} else {
    -				params.content_model.model =
    -					HUBBUB_CONTENT_MODEL_PLAINTEXT;
    +			params.initial_state.state =
    +					HUBBUB_INITIAL_STATE_PLAINTEXT;
     			}
     		}
    +
     		assert(hubbub_tokeniser_setopt(tok,
    -				HUBBUB_TOKENISER_CONTENT_MODEL,
    +				HUBBUB_TOKENISER_INITIAL_STATE,
     				&params) == HUBBUB_OK);
     
     		printf("Input: '%.*s' (%d)\n", (int) ctx->input_len,
    -- 
    1.8.3.2
    
    
  • patch file icon 0004-Fixing-rcdata-and-rawtext-close-tag-open-state-for-b.patch (4,433 bytes) 2014-03-11 17:01 -
    From 7c54cf903300c4804540b8ed746ab5bca350bd81 Mon Sep 17 00:00:00 2001
    From: Achal-Aggarwal <theachalaggarwal@gmail.com>
    Date: Tue, 11 Mar 2014 19:15:02 +0530
    Subject: [PATCH 4/4] Fixing rcdata and rawtext close tag open state for byte
     by byte test.
    
    ---
     src/tokeniser/tokeniser.c | 108 ++++++++++++++++++++++++----------------------
     1 file changed, 56 insertions(+), 52 deletions(-)
    
    diff --git a/src/tokeniser/tokeniser.c b/src/tokeniser/tokeniser.c
    index 7152f05..3c18e92 100644
    --- a/src/tokeniser/tokeniser.c
    +++ b/src/tokeniser/tokeniser.c
    @@ -1537,44 +1537,46 @@ hubbub_error hubbub_tokeniser_handle_rcdata_close_tag_open(hubbub_tokeniser *tok
     	parserutils_error error;
     	uint8_t c;
     
    +	uint8_t *start_tag_name =
    +				tokeniser->context.last_start_tag_name;
    +		size_t start_tag_len =
    +			tokeniser->context.last_start_tag_len;
    +
     	assert(tokeniser->context.pending == 2);
     /*	assert(tokeniser->context.chars.ptr[0] == '<'); */
     /*	assert(tokeniser->context.chars.ptr[1] == '/'); */
     
    -	uint8_t *start_tag_name =
    -			tokeniser->context.last_start_tag_name;
    -	size_t start_tag_len =
    -		tokeniser->context.last_start_tag_len;
    -
    -	while ((error = parserutils_inputstream_peek(tokeniser->input,
    -				ctx->pending +
    -					ctx->close_tag_match.count,
    -				&cptr,
    -				&len)) == PARSERUTILS_OK) {
    -		c = *cptr;
    +	if (ctx->close_tag_match.match == false) {
     
    -		if ((start_tag_name[ctx->close_tag_match.count] & ~0x20)
    -				!= (c & ~0x20)) {
    -			break;
    -		}
    -
    -		ctx->close_tag_match.count += len;
    +		while ((error = parserutils_inputstream_peek(tokeniser->input,
    +					ctx->pending +
    +						ctx->close_tag_match.count,
    +					&cptr,
    +					&len)) == PARSERUTILS_OK) {
    +			c = *cptr;
    +			if ((start_tag_name[ctx->close_tag_match.count] & ~0x20)
    +					!= (c & ~0x20)) {
    +				break;
    +			}
     
    -		if (ctx->close_tag_match.count == start_tag_len) {
    +			ctx->close_tag_match.count += len;
     
    -			// Sets the flag to be used in name state.
    -			ctx->close_tag_match.match = true;
    -			break;
    +			if (ctx->close_tag_match.count == start_tag_len) {
    +				// Sets the flag to be used in name state.
    +				ctx->close_tag_match.match = true;
    +				break;
    +			}
     		}
    -	}
     
    -	if (error != PARSERUTILS_OK) {
    -		if (error == PARSERUTILS_EOF) {
    -			tokeniser->state = STATE_RCDATA;
    -			tokeniser->context.pending += ctx->close_tag_match.count;
    -			return HUBBUB_OK;
    -		} else {
    -			return hubbub_error_from_parserutils_error(error);
    +		if (error != PARSERUTILS_OK) {
    +			if (error == PARSERUTILS_EOF) {
    +				tokeniser->state = STATE_RCDATA;
    +				tokeniser->context.pending += ctx->close_tag_match.count;
    +
    +				return HUBBUB_OK;
    +			} else {
    +				return hubbub_error_from_parserutils_error(error);
    +			}
     		}
     	}
     
    @@ -1752,35 +1754,37 @@ hubbub_error hubbub_tokeniser_handle_rawtext_close_tag_open(hubbub_tokeniser *to
     	size_t start_tag_len =
     		tokeniser->context.last_start_tag_len;
     
    -	while ((error = parserutils_inputstream_peek(tokeniser->input,
    -				ctx->pending +
    -					ctx->close_tag_match.count,
    -				&cptr,
    -				&len)) == PARSERUTILS_OK) {
    -		c = *cptr;
    +	if (ctx->close_tag_match.match == false) {
    +		while ((error = parserutils_inputstream_peek(tokeniser->input,
    +					ctx->pending +
    +						ctx->close_tag_match.count,
    +					&cptr,
    +					&len)) == PARSERUTILS_OK) {
    +			c = *cptr;
     
    -		if ((start_tag_name[ctx->close_tag_match.count] & ~0x20)
    -				!= (c & ~0x20)) {
    -			break;
    -		}
    +			if ((start_tag_name[ctx->close_tag_match.count] & ~0x20)
    +					!= (c & ~0x20)) {
    +				break;
    +			}
     
    -		ctx->close_tag_match.count += len;
    +			ctx->close_tag_match.count += len;
     
    -		if (ctx->close_tag_match.count == start_tag_len) {
    +			if (ctx->close_tag_match.count == start_tag_len) {
     
    -			// Sets the flag to be used in name state.
    -			ctx->close_tag_match.match = true;
    -			break;
    +				// Sets the flag to be used in name state.
    +				ctx->close_tag_match.match = true;
    +				break;
    +			}
     		}
    -	}
     
    -	if (error != PARSERUTILS_OK) {
    -		if (error == PARSERUTILS_EOF) {
    -			tokeniser->state = STATE_RAWTEXT;
    -			tokeniser->context.pending += ctx->close_tag_match.count;
    -			return HUBBUB_OK;
    -		} else {
    -			return hubbub_error_from_parserutils_error(error);
    +		if (error != PARSERUTILS_OK) {
    +			if (error == PARSERUTILS_EOF) {
    +				tokeniser->state = STATE_RAWTEXT;
    +				tokeniser->context.pending += ctx->close_tag_match.count;
    +				return HUBBUB_OK;
    +			} else {
    +				return hubbub_error_from_parserutils_error(error);
    +			}
     		}
     	}
     
    -- 
    1.8.3.2
    
    

-Relationships
+Relationships

-Notes
Achal

~0000260

Achal (reporter)

contentModelFlags.test
escapeFlag.test
regression.test

are currently failing. I am working on them, will upload second patch soon.
Achal

~0000267

Achal (reporter)

New branch to track : https://github.com/Achal-Aggarwal/hibbub/compare/rewrite

What to expect from this?
Tokeniser updated to HTML5 spec with some few exceptions(working on that).
http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html

What is remaining in tokeniser?
SCRIPT DATA states (few implemented, few remaining...)
named entities
double escaped tests (unicodeCharsProblematic.test)

Tree Builder
tests are failing currently might be because of updated tokeniser.
+Notes

-Issue History
Date Modified Username Field Change
2014-03-09 14:48 Achal New Issue
2014-03-09 14:48 Achal File Added: libhubbub-test.diff
2014-03-09 14:58 Achal Note Added: 0000260
2014-03-11 16:00 Achal Note Added: 0000267
2014-03-11 16:29 Achal File Added: rewrite.diff
2014-03-11 17:00 Achal File Added: 0001-Rewriting-whole-tokenizer-and-updating-its-tests.patch
2014-03-11 17:00 Achal File Added: 0002-Replacing-content-model-with-states-except-SCRIPT-DA.patch
2014-03-11 17:01 Achal File Added: 0003-Fix-tokeniser-test-executer-for-content-model-replac.patch
2014-03-11 17:01 Achal File Added: 0004-Fixing-rcdata-and-rawtext-close-tag-open-state-for-b.patch
2014-06-12 11:24 Vincent Sanders Assigned To => John-Mark Bell
2014-06-12 11:24 Vincent Sanders Status new => acknowledged
+Issue History