modules/html/tokenizer.zzm

html-0.0.2 source code

Package

Name
html
Version
0.0.2
Uploaded
2026-06-12 23:25:02
Repository
https://github.com/tobyink/zuzu-html
Dependencies
Metadata
zuzu-distribution.json
Archive
Download .tar.gz
=encoding utf8

=head1 NAME

html/tokenizer - HTML input stream and tokenizer.

=head1 SYNOPSIS

  from html/tokenizer import HTMLTokenizer;
  
  let tokenizer := new HTMLTokenizer( _input: "<p title='x'>&amp;</p>" );
  let tokens := tokenizer.tokenize();

=head1 NOTE

This module is not normally useful to end users. Instead use C<html/parser>.

=head1 DESCRIPTION

This module implements the tokenizer layer for C<html/parser>. It
accepts already-decoded ZuzuScript strings, normalizes line endings,
tracks source position, emits HTML tokenizer tokens, and records
non-fatal parse errors with line, column, offset, and tokenizer state.

It intentionally does not build a DOM tree. C<html/parser> re-exports
these classes for focused tokenizer tests and for the tree builder. The
tokenizer exposes C<setAllowCDATA> and C<allowCDATA> so the tree builder
can recognise CDATA sections only while processing SVG or MathML foreign
content.

=head1 EXPORTS

=head2 Classes

=over

=item C<HTMLTokenizer>

Tokenizer for HTML strings. Construct it with C<_input> or call
C<reset(String input, String state?)> to reuse it. C<tokenize()> returns
all tokens. C<nextToken()> returns one token at a time and eventually an
EOF token.

Public state methods are C<state>, C<setState>,
C<setLastStartTagName>, C<lastStartTagName>, C<setAllowCDATA>,
C<allowCDATA>, and C<errors>. C<setState> accepts tokenizer state names
such as C<data>, C<rcdata>, C<rawtext>, C<script_data>, and
C<plaintext>. C<errors()> returns a copy of the parse errors emitted
during the last tokenization run.

=item C<HTMLInputStream>

Input stream used by C<HTMLTokenizer>. It normalizes CRLF and CR line
endings to LF, tracks source position, and exposes C<source>, C<offset>,
C<line>, C<column>, C<lastOffset>, C<lastLine>, C<lastColumn>, C<eof>,
C<consume>, C<reconsume>, C<peek>, and C<match>. Most users should use
C<HTMLTokenizer> instead of consuming the stream directly.

=item C<HTMLToken>

Token object emitted by the tokenizer. C<type()> returns values such as
C<start_tag>, C<end_tag>, C<characters>, C<comment>, C<doctype>, and
C<eof>. Other accessors are C<data>, C<tagName>, C<attributes>,
C<getAttribute>, C<hasAttribute>, C<selfClosing>, C<publicId>,
C<systemId>, C<forceQuirks>, and C<toDebugString>.

=item C<HTMLParseError>

Non-fatal tokenizer or tree-construction error. Accessors are C<code>,
C<message>, C<line>, C<column>, C<offset>, C<state>, and C<to_String>.

=item C<HTMLNamedCharacterReferences>

Small named-reference table wrapper. C<table()> returns the current
mapping, C<get(String name)> returns a named reference or C<null>,
C<isComplete()> returns false, and C<coverage()> describes the partial
coverage.

=back

=head1 CHARACTER REFERENCES

Numeric decimal and hexadecimal references are implemented, including
HTML replacement handling for null, surrogate, out-of-range, and C1
Windows-1252 values. The named-reference table is deliberately partial
and covers the common entities needed by the focused tokenizer suite:
C<amp>, C<lt>, C<gt>, C<quot>, C<apos>, C<nbsp>, C<copy>, C<reg>, and
C<not>, with their semicolon forms and the legacy no-semicolon forms
used by HTML tokenization.

=head1 LIMITATIONS

There is no DOM tree construction inside this module, no html5lib
C<.dat> harness, full CSS selector support, or full WHATWG
named-character-reference table.

=head1 COPYRIGHT AND LICENCE

B<< html/tokenizer >> is copyright Toby Inkster.

It is free software; you may redistribute it and/or modify it under
the terms of either the Artistic License 1.0 or the GNU General Public
License version 2.

=cut

from std/string import chr, index, join, ord, replace, substr, trim;

function _html_tok_string ( value ) {
	return value ≡ null ? "" : "" _ value;
}

function _html_tok_bool ( value ) {
	return value ? true : false;
}

function _html_tok_lc ( value ) {
	return lc(_html_tok_string(value));
}

function _html_tok_state_name ( value ) {
	let state := _html_tok_lc(value ≡ null ? "data" : value);
	state := replace( state, " ", "_", "g" );
	state := replace( state, "-", "_", "g" );
	return state;
}

function _html_tok_copy_attrs ( Array attrs ) {
	let out := [];
	for ( let attr in attrs ) {
		out.push( {
			name: attr{name},
			value: attr{value},
		} );
	}
	return out;
}

function _html_tok_is_space ( String ch ) {
	return ch eq " " or ch eq "\n" or ch eq "\t" or ch eq chr(12);
}

function _html_tok_is_alpha ( String ch ) {
	return ch ~ /^[A-Za-z]$/;
}

function _html_tok_is_digit ( String ch ) {
	return ch ~ /^[0-9]$/;
}

function _html_tok_is_hex_digit ( String ch ) {
	return ch ~ /^[0-9A-Fa-f]$/;
}

function _html_tok_is_alnum ( String ch ) {
	return ch ~ /^[0-9A-Za-z]$/;
}

function _html_tok_ascii_lower_char ( String ch ) {
	return _html_tok_is_alpha(ch) ? lc(ch) : ch;
}

function _html_tok_hex_value ( String ch ) {
	return index( "0123456789abcdef", lc(ch) );
}

function _html_tok_parse_int ( String text, Number base ) {
	let n := 0;
	let i := 0;
	while ( i < length text ) {
		let digit := base == 16
			? _html_tok_hex_value(substr( text, i, 1 ))
			: index( "0123456789", substr( text, i, 1 ) );
		return null if digit < 0 or digit >= base;
		n := n * base + digit;
		i++;
	}
	return n;
}

function _html_tok_control_replacement ( Number code ) {
	switch ( code: == ) {
		case 128: return 8364;
		case 130: return 8218;
		case 131: return 402;
		case 132: return 8222;
		case 133: return 8230;
		case 134: return 8224;
		case 135: return 8225;
		case 136: return 710;
		case 137: return 8240;
		case 138: return 352;
		case 139: return 8249;
		case 140: return 338;
		case 142: return 381;
		case 145: return 8216;
		case 146: return 8217;
		case 147: return 8220;
		case 148: return 8221;
		case 149: return 8226;
		case 150: return 8211;
		case 151: return 8212;
		case 152: return 732;
		case 153: return 8482;
		case 154: return 353;
		case 155: return 8250;
		case 156: return 339;
		case 158: return 382;
		case 159: return 376;
	}
	return null;
}

let _html_tok_named_references_cache := null;

function _html_tok_build_named_references;

function _html_tok_named_references () {
	if ( _html_tok_named_references_cache == null ) {
		_html_tok_named_references_cache := _html_tok_build_named_references();
	}
	let out := _html_tok_named_references_cache;
	return out;
}

// Generated from https://html.spec.whatwg.org/entities.json
function _html_tok_build_named_references () {
	let t := {};
	t.set( "AElig", chr(198) );
	t.set( "AElig;", chr(198) );
	t.set( "AMP", chr(38) );
	t.set( "AMP;", chr(38) );
	t.set( "Aacute", chr(193) );
	t.set( "Aacute;", chr(193) );
	t.set( "Abreve;", chr(258) );
	t.set( "Acirc", chr(194) );
	t.set( "Acirc;", chr(194) );
	t.set( "Acy;", chr(1040) );
	t.set( "Afr;", chr(120068) );
	t.set( "Agrave", chr(192) );
	t.set( "Agrave;", chr(192) );
	t.set( "Alpha;", chr(913) );
	t.set( "Amacr;", chr(256) );
	t.set( "And;", chr(10835) );
	t.set( "Aogon;", chr(260) );
	t.set( "Aopf;", chr(120120) );
	t.set( "ApplyFunction;", chr(8289) );
	t.set( "Aring", chr(197) );
	t.set( "Aring;", chr(197) );
	t.set( "Ascr;", chr(119964) );
	t.set( "Assign;", chr(8788) );
	t.set( "Atilde", chr(195) );
	t.set( "Atilde;", chr(195) );
	t.set( "Auml", chr(196) );
	t.set( "Auml;", chr(196) );
	t.set( "Backslash;", chr(8726) );
	t.set( "Barv;", chr(10983) );
	t.set( "Barwed;", chr(8966) );
	t.set( "Bcy;", chr(1041) );
	t.set( "Because;", chr(8757) );
	t.set( "Bernoullis;", chr(8492) );
	t.set( "Beta;", chr(914) );
	t.set( "Bfr;", chr(120069) );
	t.set( "Bopf;", chr(120121) );
	t.set( "Breve;", chr(728) );
	t.set( "Bscr;", chr(8492) );
	t.set( "Bumpeq;", chr(8782) );
	t.set( "CHcy;", chr(1063) );
	t.set( "COPY", chr(169) );
	t.set( "COPY;", chr(169) );
	t.set( "Cacute;", chr(262) );
	t.set( "Cap;", chr(8914) );
	t.set( "CapitalDifferentialD;", chr(8517) );
	t.set( "Cayleys;", chr(8493) );
	t.set( "Ccaron;", chr(268) );
	t.set( "Ccedil", chr(199) );
	t.set( "Ccedil;", chr(199) );
	t.set( "Ccirc;", chr(264) );
	t.set( "Cconint;", chr(8752) );
	t.set( "Cdot;", chr(266) );
	t.set( "Cedilla;", chr(184) );
	t.set( "CenterDot;", chr(183) );
	t.set( "Cfr;", chr(8493) );
	t.set( "Chi;", chr(935) );
	t.set( "CircleDot;", chr(8857) );
	t.set( "CircleMinus;", chr(8854) );
	t.set( "CirclePlus;", chr(8853) );
	t.set( "CircleTimes;", chr(8855) );
	t.set( "ClockwiseContourIntegral;", chr(8754) );
	t.set( "CloseCurlyDoubleQuote;", chr(8221) );
	t.set( "CloseCurlyQuote;", chr(8217) );
	t.set( "Colon;", chr(8759) );
	t.set( "Colone;", chr(10868) );
	t.set( "Congruent;", chr(8801) );
	t.set( "Conint;", chr(8751) );
	t.set( "ContourIntegral;", chr(8750) );
	t.set( "Copf;", chr(8450) );
	t.set( "Coproduct;", chr(8720) );
	t.set( "CounterClockwiseContourIntegral;", chr(8755) );
	t.set( "Cross;", chr(10799) );
	t.set( "Cscr;", chr(119966) );
	t.set( "Cup;", chr(8915) );
	t.set( "CupCap;", chr(8781) );
	t.set( "DD;", chr(8517) );
	t.set( "DDotrahd;", chr(10513) );
	t.set( "DJcy;", chr(1026) );
	t.set( "DScy;", chr(1029) );
	t.set( "DZcy;", chr(1039) );
	t.set( "Dagger;", chr(8225) );
	t.set( "Darr;", chr(8609) );
	t.set( "Dashv;", chr(10980) );
	t.set( "Dcaron;", chr(270) );
	t.set( "Dcy;", chr(1044) );
	t.set( "Del;", chr(8711) );
	t.set( "Delta;", chr(916) );
	t.set( "Dfr;", chr(120071) );
	t.set( "DiacriticalAcute;", chr(180) );
	t.set( "DiacriticalDot;", chr(729) );
	t.set( "DiacriticalDoubleAcute;", chr(733) );
	t.set( "DiacriticalGrave;", chr(96) );
	t.set( "DiacriticalTilde;", chr(732) );
	t.set( "Diamond;", chr(8900) );
	t.set( "DifferentialD;", chr(8518) );
	t.set( "Dopf;", chr(120123) );
	t.set( "Dot;", chr(168) );
	t.set( "DotDot;", chr(8412) );
	t.set( "DotEqual;", chr(8784) );
	t.set( "DoubleContourIntegral;", chr(8751) );
	t.set( "DoubleDot;", chr(168) );
	t.set( "DoubleDownArrow;", chr(8659) );
	t.set( "DoubleLeftArrow;", chr(8656) );
	t.set( "DoubleLeftRightArrow;", chr(8660) );
	t.set( "DoubleLeftTee;", chr(10980) );
	t.set( "DoubleLongLeftArrow;", chr(10232) );
	t.set( "DoubleLongLeftRightArrow;", chr(10234) );
	t.set( "DoubleLongRightArrow;", chr(10233) );
	t.set( "DoubleRightArrow;", chr(8658) );
	t.set( "DoubleRightTee;", chr(8872) );
	t.set( "DoubleUpArrow;", chr(8657) );
	t.set( "DoubleUpDownArrow;", chr(8661) );
	t.set( "DoubleVerticalBar;", chr(8741) );
	t.set( "DownArrow;", chr(8595) );
	t.set( "DownArrowBar;", chr(10515) );
	t.set( "DownArrowUpArrow;", chr(8693) );
	t.set( "DownBreve;", chr(785) );
	t.set( "DownLeftRightVector;", chr(10576) );
	t.set( "DownLeftTeeVector;", chr(10590) );
	t.set( "DownLeftVector;", chr(8637) );
	t.set( "DownLeftVectorBar;", chr(10582) );
	t.set( "DownRightTeeVector;", chr(10591) );
	t.set( "DownRightVector;", chr(8641) );
	t.set( "DownRightVectorBar;", chr(10583) );
	t.set( "DownTee;", chr(8868) );
	t.set( "DownTeeArrow;", chr(8615) );
	t.set( "Downarrow;", chr(8659) );
	t.set( "Dscr;", chr(119967) );
	t.set( "Dstrok;", chr(272) );
	t.set( "ENG;", chr(330) );
	t.set( "ETH", chr(208) );
	t.set( "ETH;", chr(208) );
	t.set( "Eacute", chr(201) );
	t.set( "Eacute;", chr(201) );
	t.set( "Ecaron;", chr(282) );
	t.set( "Ecirc", chr(202) );
	t.set( "Ecirc;", chr(202) );
	t.set( "Ecy;", chr(1069) );
	t.set( "Edot;", chr(278) );
	t.set( "Efr;", chr(120072) );
	t.set( "Egrave", chr(200) );
	t.set( "Egrave;", chr(200) );
	t.set( "Element;", chr(8712) );
	t.set( "Emacr;", chr(274) );
	t.set( "EmptySmallSquare;", chr(9723) );
	t.set( "EmptyVerySmallSquare;", chr(9643) );
	t.set( "Eogon;", chr(280) );
	t.set( "Eopf;", chr(120124) );
	t.set( "Epsilon;", chr(917) );
	t.set( "Equal;", chr(10869) );
	t.set( "EqualTilde;", chr(8770) );
	t.set( "Equilibrium;", chr(8652) );
	t.set( "Escr;", chr(8496) );
	t.set( "Esim;", chr(10867) );
	t.set( "Eta;", chr(919) );
	t.set( "Euml", chr(203) );
	t.set( "Euml;", chr(203) );
	t.set( "Exists;", chr(8707) );
	t.set( "ExponentialE;", chr(8519) );
	t.set( "Fcy;", chr(1060) );
	t.set( "Ffr;", chr(120073) );
	t.set( "FilledSmallSquare;", chr(9724) );
	t.set( "FilledVerySmallSquare;", chr(9642) );
	t.set( "Fopf;", chr(120125) );
	t.set( "ForAll;", chr(8704) );
	t.set( "Fouriertrf;", chr(8497) );
	t.set( "Fscr;", chr(8497) );
	t.set( "GJcy;", chr(1027) );
	t.set( "GT", chr(62) );
	t.set( "GT;", chr(62) );
	t.set( "Gamma;", chr(915) );
	t.set( "Gammad;", chr(988) );
	t.set( "Gbreve;", chr(286) );
	t.set( "Gcedil;", chr(290) );
	t.set( "Gcirc;", chr(284) );
	t.set( "Gcy;", chr(1043) );
	t.set( "Gdot;", chr(288) );
	t.set( "Gfr;", chr(120074) );
	t.set( "Gg;", chr(8921) );
	t.set( "Gopf;", chr(120126) );
	t.set( "GreaterEqual;", chr(8805) );
	t.set( "GreaterEqualLess;", chr(8923) );
	t.set( "GreaterFullEqual;", chr(8807) );
	t.set( "GreaterGreater;", chr(10914) );
	t.set( "GreaterLess;", chr(8823) );
	t.set( "GreaterSlantEqual;", chr(10878) );
	t.set( "GreaterTilde;", chr(8819) );
	t.set( "Gscr;", chr(119970) );
	t.set( "Gt;", chr(8811) );
	t.set( "HARDcy;", chr(1066) );
	t.set( "Hacek;", chr(711) );
	t.set( "Hat;", chr(94) );
	t.set( "Hcirc;", chr(292) );
	t.set( "Hfr;", chr(8460) );
	t.set( "HilbertSpace;", chr(8459) );
	t.set( "Hopf;", chr(8461) );
	t.set( "HorizontalLine;", chr(9472) );
	t.set( "Hscr;", chr(8459) );
	t.set( "Hstrok;", chr(294) );
	t.set( "HumpDownHump;", chr(8782) );
	t.set( "HumpEqual;", chr(8783) );
	t.set( "IEcy;", chr(1045) );
	t.set( "IJlig;", chr(306) );
	t.set( "IOcy;", chr(1025) );
	t.set( "Iacute", chr(205) );
	t.set( "Iacute;", chr(205) );
	t.set( "Icirc", chr(206) );
	t.set( "Icirc;", chr(206) );
	t.set( "Icy;", chr(1048) );
	t.set( "Idot;", chr(304) );
	t.set( "Ifr;", chr(8465) );
	t.set( "Igrave", chr(204) );
	t.set( "Igrave;", chr(204) );
	t.set( "Im;", chr(8465) );
	t.set( "Imacr;", chr(298) );
	t.set( "ImaginaryI;", chr(8520) );
	t.set( "Implies;", chr(8658) );
	t.set( "Int;", chr(8748) );
	t.set( "Integral;", chr(8747) );
	t.set( "Intersection;", chr(8898) );
	t.set( "InvisibleComma;", chr(8291) );
	t.set( "InvisibleTimes;", chr(8290) );
	t.set( "Iogon;", chr(302) );
	t.set( "Iopf;", chr(120128) );
	t.set( "Iota;", chr(921) );
	t.set( "Iscr;", chr(8464) );
	t.set( "Itilde;", chr(296) );
	t.set( "Iukcy;", chr(1030) );
	t.set( "Iuml", chr(207) );
	t.set( "Iuml;", chr(207) );
	t.set( "Jcirc;", chr(308) );
	t.set( "Jcy;", chr(1049) );
	t.set( "Jfr;", chr(120077) );
	t.set( "Jopf;", chr(120129) );
	t.set( "Jscr;", chr(119973) );
	t.set( "Jsercy;", chr(1032) );
	t.set( "Jukcy;", chr(1028) );
	t.set( "KHcy;", chr(1061) );
	t.set( "KJcy;", chr(1036) );
	t.set( "Kappa;", chr(922) );
	t.set( "Kcedil;", chr(310) );
	t.set( "Kcy;", chr(1050) );
	t.set( "Kfr;", chr(120078) );
	t.set( "Kopf;", chr(120130) );
	t.set( "Kscr;", chr(119974) );
	t.set( "LJcy;", chr(1033) );
	t.set( "LT", chr(60) );
	t.set( "LT;", chr(60) );
	t.set( "Lacute;", chr(313) );
	t.set( "Lambda;", chr(923) );
	t.set( "Lang;", chr(10218) );
	t.set( "Laplacetrf;", chr(8466) );
	t.set( "Larr;", chr(8606) );
	t.set( "Lcaron;", chr(317) );
	t.set( "Lcedil;", chr(315) );
	t.set( "Lcy;", chr(1051) );
	t.set( "LeftAngleBracket;", chr(10216) );
	t.set( "LeftArrow;", chr(8592) );
	t.set( "LeftArrowBar;", chr(8676) );
	t.set( "LeftArrowRightArrow;", chr(8646) );
	t.set( "LeftCeiling;", chr(8968) );
	t.set( "LeftDoubleBracket;", chr(10214) );
	t.set( "LeftDownTeeVector;", chr(10593) );
	t.set( "LeftDownVector;", chr(8643) );
	t.set( "LeftDownVectorBar;", chr(10585) );
	t.set( "LeftFloor;", chr(8970) );
	t.set( "LeftRightArrow;", chr(8596) );
	t.set( "LeftRightVector;", chr(10574) );
	t.set( "LeftTee;", chr(8867) );
	t.set( "LeftTeeArrow;", chr(8612) );
	t.set( "LeftTeeVector;", chr(10586) );
	t.set( "LeftTriangle;", chr(8882) );
	t.set( "LeftTriangleBar;", chr(10703) );
	t.set( "LeftTriangleEqual;", chr(8884) );
	t.set( "LeftUpDownVector;", chr(10577) );
	t.set( "LeftUpTeeVector;", chr(10592) );
	t.set( "LeftUpVector;", chr(8639) );
	t.set( "LeftUpVectorBar;", chr(10584) );
	t.set( "LeftVector;", chr(8636) );
	t.set( "LeftVectorBar;", chr(10578) );
	t.set( "Leftarrow;", chr(8656) );
	t.set( "Leftrightarrow;", chr(8660) );
	t.set( "LessEqualGreater;", chr(8922) );
	t.set( "LessFullEqual;", chr(8806) );
	t.set( "LessGreater;", chr(8822) );
	t.set( "LessLess;", chr(10913) );
	t.set( "LessSlantEqual;", chr(10877) );
	t.set( "LessTilde;", chr(8818) );
	t.set( "Lfr;", chr(120079) );
	t.set( "Ll;", chr(8920) );
	t.set( "Lleftarrow;", chr(8666) );
	t.set( "Lmidot;", chr(319) );
	t.set( "LongLeftArrow;", chr(10229) );
	t.set( "LongLeftRightArrow;", chr(10231) );
	t.set( "LongRightArrow;", chr(10230) );
	t.set( "Longleftarrow;", chr(10232) );
	t.set( "Longleftrightarrow;", chr(10234) );
	t.set( "Longrightarrow;", chr(10233) );
	t.set( "Lopf;", chr(120131) );
	t.set( "LowerLeftArrow;", chr(8601) );
	t.set( "LowerRightArrow;", chr(8600) );
	t.set( "Lscr;", chr(8466) );
	t.set( "Lsh;", chr(8624) );
	t.set( "Lstrok;", chr(321) );
	t.set( "Lt;", chr(8810) );
	t.set( "Map;", chr(10501) );
	t.set( "Mcy;", chr(1052) );
	t.set( "MediumSpace;", chr(8287) );
	t.set( "Mellintrf;", chr(8499) );
	t.set( "Mfr;", chr(120080) );
	t.set( "MinusPlus;", chr(8723) );
	t.set( "Mopf;", chr(120132) );
	t.set( "Mscr;", chr(8499) );
	t.set( "Mu;", chr(924) );
	t.set( "NJcy;", chr(1034) );
	t.set( "Nacute;", chr(323) );
	t.set( "Ncaron;", chr(327) );
	t.set( "Ncedil;", chr(325) );
	t.set( "Ncy;", chr(1053) );
	t.set( "NegativeMediumSpace;", chr(8203) );
	t.set( "NegativeThickSpace;", chr(8203) );
	t.set( "NegativeThinSpace;", chr(8203) );
	t.set( "NegativeVeryThinSpace;", chr(8203) );
	t.set( "NestedGreaterGreater;", chr(8811) );
	t.set( "NestedLessLess;", chr(8810) );
	t.set( "NewLine;", chr(10) );
	t.set( "Nfr;", chr(120081) );
	t.set( "NoBreak;", chr(8288) );
	t.set( "NonBreakingSpace;", chr(160) );
	t.set( "Nopf;", chr(8469) );
	t.set( "Not;", chr(10988) );
	t.set( "NotCongruent;", chr(8802) );
	t.set( "NotCupCap;", chr(8813) );
	t.set( "NotDoubleVerticalBar;", chr(8742) );
	t.set( "NotElement;", chr(8713) );
	t.set( "NotEqual;", chr(8800) );
	t.set( "NotEqualTilde;", chr(8770) _ chr(824) );
	t.set( "NotExists;", chr(8708) );
	t.set( "NotGreater;", chr(8815) );
	t.set( "NotGreaterEqual;", chr(8817) );
	t.set( "NotGreaterFullEqual;", chr(8807) _ chr(824) );
	t.set( "NotGreaterGreater;", chr(8811) _ chr(824) );
	t.set( "NotGreaterLess;", chr(8825) );
	t.set( "NotGreaterSlantEqual;", chr(10878) _ chr(824) );
	t.set( "NotGreaterTilde;", chr(8821) );
	t.set( "NotHumpDownHump;", chr(8782) _ chr(824) );
	t.set( "NotHumpEqual;", chr(8783) _ chr(824) );
	t.set( "NotLeftTriangle;", chr(8938) );
	t.set( "NotLeftTriangleBar;", chr(10703) _ chr(824) );
	t.set( "NotLeftTriangleEqual;", chr(8940) );
	t.set( "NotLess;", chr(8814) );
	t.set( "NotLessEqual;", chr(8816) );
	t.set( "NotLessGreater;", chr(8824) );
	t.set( "NotLessLess;", chr(8810) _ chr(824) );
	t.set( "NotLessSlantEqual;", chr(10877) _ chr(824) );
	t.set( "NotLessTilde;", chr(8820) );
	t.set( "NotNestedGreaterGreater;", chr(10914) _ chr(824) );
	t.set( "NotNestedLessLess;", chr(10913) _ chr(824) );
	t.set( "NotPrecedes;", chr(8832) );
	t.set( "NotPrecedesEqual;", chr(10927) _ chr(824) );
	t.set( "NotPrecedesSlantEqual;", chr(8928) );
	t.set( "NotReverseElement;", chr(8716) );
	t.set( "NotRightTriangle;", chr(8939) );
	t.set( "NotRightTriangleBar;", chr(10704) _ chr(824) );
	t.set( "NotRightTriangleEqual;", chr(8941) );
	t.set( "NotSquareSubset;", chr(8847) _ chr(824) );
	t.set( "NotSquareSubsetEqual;", chr(8930) );
	t.set( "NotSquareSuperset;", chr(8848) _ chr(824) );
	t.set( "NotSquareSupersetEqual;", chr(8931) );
	t.set( "NotSubset;", chr(8834) _ chr(8402) );
	t.set( "NotSubsetEqual;", chr(8840) );
	t.set( "NotSucceeds;", chr(8833) );
	t.set( "NotSucceedsEqual;", chr(10928) _ chr(824) );
	t.set( "NotSucceedsSlantEqual;", chr(8929) );
	t.set( "NotSucceedsTilde;", chr(8831) _ chr(824) );
	t.set( "NotSuperset;", chr(8835) _ chr(8402) );
	t.set( "NotSupersetEqual;", chr(8841) );
	t.set( "NotTilde;", chr(8769) );
	t.set( "NotTildeEqual;", chr(8772) );
	t.set( "NotTildeFullEqual;", chr(8775) );
	t.set( "NotTildeTilde;", chr(8777) );
	t.set( "NotVerticalBar;", chr(8740) );
	t.set( "Nscr;", chr(119977) );
	t.set( "Ntilde", chr(209) );
	t.set( "Ntilde;", chr(209) );
	t.set( "Nu;", chr(925) );
	t.set( "OElig;", chr(338) );
	t.set( "Oacute", chr(211) );
	t.set( "Oacute;", chr(211) );
	t.set( "Ocirc", chr(212) );
	t.set( "Ocirc;", chr(212) );
	t.set( "Ocy;", chr(1054) );
	t.set( "Odblac;", chr(336) );
	t.set( "Ofr;", chr(120082) );
	t.set( "Ograve", chr(210) );
	t.set( "Ograve;", chr(210) );
	t.set( "Omacr;", chr(332) );
	t.set( "Omega;", chr(937) );
	t.set( "Omicron;", chr(927) );
	t.set( "Oopf;", chr(120134) );
	t.set( "OpenCurlyDoubleQuote;", chr(8220) );
	t.set( "OpenCurlyQuote;", chr(8216) );
	t.set( "Or;", chr(10836) );
	t.set( "Oscr;", chr(119978) );
	t.set( "Oslash", chr(216) );
	t.set( "Oslash;", chr(216) );
	t.set( "Otilde", chr(213) );
	t.set( "Otilde;", chr(213) );
	t.set( "Otimes;", chr(10807) );
	t.set( "Ouml", chr(214) );
	t.set( "Ouml;", chr(214) );
	t.set( "OverBar;", chr(8254) );
	t.set( "OverBrace;", chr(9182) );
	t.set( "OverBracket;", chr(9140) );
	t.set( "OverParenthesis;", chr(9180) );
	t.set( "PartialD;", chr(8706) );
	t.set( "Pcy;", chr(1055) );
	t.set( "Pfr;", chr(120083) );
	t.set( "Phi;", chr(934) );
	t.set( "Pi;", chr(928) );
	t.set( "PlusMinus;", chr(177) );
	t.set( "Poincareplane;", chr(8460) );
	t.set( "Popf;", chr(8473) );
	t.set( "Pr;", chr(10939) );
	t.set( "Precedes;", chr(8826) );
	t.set( "PrecedesEqual;", chr(10927) );
	t.set( "PrecedesSlantEqual;", chr(8828) );
	t.set( "PrecedesTilde;", chr(8830) );
	t.set( "Prime;", chr(8243) );
	t.set( "Product;", chr(8719) );
	t.set( "Proportion;", chr(8759) );
	t.set( "Proportional;", chr(8733) );
	t.set( "Pscr;", chr(119979) );
	t.set( "Psi;", chr(936) );
	t.set( "QUOT", chr(34) );
	t.set( "QUOT;", chr(34) );
	t.set( "Qfr;", chr(120084) );
	t.set( "Qopf;", chr(8474) );
	t.set( "Qscr;", chr(119980) );
	t.set( "RBarr;", chr(10512) );
	t.set( "REG", chr(174) );
	t.set( "REG;", chr(174) );
	t.set( "Racute;", chr(340) );
	t.set( "Rang;", chr(10219) );
	t.set( "Rarr;", chr(8608) );
	t.set( "Rarrtl;", chr(10518) );
	t.set( "Rcaron;", chr(344) );
	t.set( "Rcedil;", chr(342) );
	t.set( "Rcy;", chr(1056) );
	t.set( "Re;", chr(8476) );
	t.set( "ReverseElement;", chr(8715) );
	t.set( "ReverseEquilibrium;", chr(8651) );
	t.set( "ReverseUpEquilibrium;", chr(10607) );
	t.set( "Rfr;", chr(8476) );
	t.set( "Rho;", chr(929) );
	t.set( "RightAngleBracket;", chr(10217) );
	t.set( "RightArrow;", chr(8594) );
	t.set( "RightArrowBar;", chr(8677) );
	t.set( "RightArrowLeftArrow;", chr(8644) );
	t.set( "RightCeiling;", chr(8969) );
	t.set( "RightDoubleBracket;", chr(10215) );
	t.set( "RightDownTeeVector;", chr(10589) );
	t.set( "RightDownVector;", chr(8642) );
	t.set( "RightDownVectorBar;", chr(10581) );
	t.set( "RightFloor;", chr(8971) );
	t.set( "RightTee;", chr(8866) );
	t.set( "RightTeeArrow;", chr(8614) );
	t.set( "RightTeeVector;", chr(10587) );
	t.set( "RightTriangle;", chr(8883) );
	t.set( "RightTriangleBar;", chr(10704) );
	t.set( "RightTriangleEqual;", chr(8885) );
	t.set( "RightUpDownVector;", chr(10575) );
	t.set( "RightUpTeeVector;", chr(10588) );
	t.set( "RightUpVector;", chr(8638) );
	t.set( "RightUpVectorBar;", chr(10580) );
	t.set( "RightVector;", chr(8640) );
	t.set( "RightVectorBar;", chr(10579) );
	t.set( "Rightarrow;", chr(8658) );
	t.set( "Ropf;", chr(8477) );
	t.set( "RoundImplies;", chr(10608) );
	t.set( "Rrightarrow;", chr(8667) );
	t.set( "Rscr;", chr(8475) );
	t.set( "Rsh;", chr(8625) );
	t.set( "RuleDelayed;", chr(10740) );
	t.set( "SHCHcy;", chr(1065) );
	t.set( "SHcy;", chr(1064) );
	t.set( "SOFTcy;", chr(1068) );
	t.set( "Sacute;", chr(346) );
	t.set( "Sc;", chr(10940) );
	t.set( "Scaron;", chr(352) );
	t.set( "Scedil;", chr(350) );
	t.set( "Scirc;", chr(348) );
	t.set( "Scy;", chr(1057) );
	t.set( "Sfr;", chr(120086) );
	t.set( "ShortDownArrow;", chr(8595) );
	t.set( "ShortLeftArrow;", chr(8592) );
	t.set( "ShortRightArrow;", chr(8594) );
	t.set( "ShortUpArrow;", chr(8593) );
	t.set( "Sigma;", chr(931) );
	t.set( "SmallCircle;", chr(8728) );
	t.set( "Sopf;", chr(120138) );
	t.set( "Sqrt;", chr(8730) );
	t.set( "Square;", chr(9633) );
	t.set( "SquareIntersection;", chr(8851) );
	t.set( "SquareSubset;", chr(8847) );
	t.set( "SquareSubsetEqual;", chr(8849) );
	t.set( "SquareSuperset;", chr(8848) );
	t.set( "SquareSupersetEqual;", chr(8850) );
	t.set( "SquareUnion;", chr(8852) );
	t.set( "Sscr;", chr(119982) );
	t.set( "Star;", chr(8902) );
	t.set( "Sub;", chr(8912) );
	t.set( "Subset;", chr(8912) );
	t.set( "SubsetEqual;", chr(8838) );
	t.set( "Succeeds;", chr(8827) );
	t.set( "SucceedsEqual;", chr(10928) );
	t.set( "SucceedsSlantEqual;", chr(8829) );
	t.set( "SucceedsTilde;", chr(8831) );
	t.set( "SuchThat;", chr(8715) );
	t.set( "Sum;", chr(8721) );
	t.set( "Sup;", chr(8913) );
	t.set( "Superset;", chr(8835) );
	t.set( "SupersetEqual;", chr(8839) );
	t.set( "Supset;", chr(8913) );
	t.set( "THORN", chr(222) );
	t.set( "THORN;", chr(222) );
	t.set( "TRADE;", chr(8482) );
	t.set( "TSHcy;", chr(1035) );
	t.set( "TScy;", chr(1062) );
	t.set( "Tab;", chr(9) );
	t.set( "Tau;", chr(932) );
	t.set( "Tcaron;", chr(356) );
	t.set( "Tcedil;", chr(354) );
	t.set( "Tcy;", chr(1058) );
	t.set( "Tfr;", chr(120087) );
	t.set( "Therefore;", chr(8756) );
	t.set( "Theta;", chr(920) );
	t.set( "ThickSpace;", chr(8287) _ chr(8202) );
	t.set( "ThinSpace;", chr(8201) );
	t.set( "Tilde;", chr(8764) );
	t.set( "TildeEqual;", chr(8771) );
	t.set( "TildeFullEqual;", chr(8773) );
	t.set( "TildeTilde;", chr(8776) );
	t.set( "Topf;", chr(120139) );
	t.set( "TripleDot;", chr(8411) );
	t.set( "Tscr;", chr(119983) );
	t.set( "Tstrok;", chr(358) );
	t.set( "Uacute", chr(218) );
	t.set( "Uacute;", chr(218) );
	t.set( "Uarr;", chr(8607) );
	t.set( "Uarrocir;", chr(10569) );
	t.set( "Ubrcy;", chr(1038) );
	t.set( "Ubreve;", chr(364) );
	t.set( "Ucirc", chr(219) );
	t.set( "Ucirc;", chr(219) );
	t.set( "Ucy;", chr(1059) );
	t.set( "Udblac;", chr(368) );
	t.set( "Ufr;", chr(120088) );
	t.set( "Ugrave", chr(217) );
	t.set( "Ugrave;", chr(217) );
	t.set( "Umacr;", chr(362) );
	t.set( "UnderBar;", chr(95) );
	t.set( "UnderBrace;", chr(9183) );
	t.set( "UnderBracket;", chr(9141) );
	t.set( "UnderParenthesis;", chr(9181) );
	t.set( "Union;", chr(8899) );
	t.set( "UnionPlus;", chr(8846) );
	t.set( "Uogon;", chr(370) );
	t.set( "Uopf;", chr(120140) );
	t.set( "UpArrow;", chr(8593) );
	t.set( "UpArrowBar;", chr(10514) );
	t.set( "UpArrowDownArrow;", chr(8645) );
	t.set( "UpDownArrow;", chr(8597) );
	t.set( "UpEquilibrium;", chr(10606) );
	t.set( "UpTee;", chr(8869) );
	t.set( "UpTeeArrow;", chr(8613) );
	t.set( "Uparrow;", chr(8657) );
	t.set( "Updownarrow;", chr(8661) );
	t.set( "UpperLeftArrow;", chr(8598) );
	t.set( "UpperRightArrow;", chr(8599) );
	t.set( "Upsi;", chr(978) );
	t.set( "Upsilon;", chr(933) );
	t.set( "Uring;", chr(366) );
	t.set( "Uscr;", chr(119984) );
	t.set( "Utilde;", chr(360) );
	t.set( "Uuml", chr(220) );
	t.set( "Uuml;", chr(220) );
	t.set( "VDash;", chr(8875) );
	t.set( "Vbar;", chr(10987) );
	t.set( "Vcy;", chr(1042) );
	t.set( "Vdash;", chr(8873) );
	t.set( "Vdashl;", chr(10982) );
	t.set( "Vee;", chr(8897) );
	t.set( "Verbar;", chr(8214) );
	t.set( "Vert;", chr(8214) );
	t.set( "VerticalBar;", chr(8739) );
	t.set( "VerticalLine;", chr(124) );
	t.set( "VerticalSeparator;", chr(10072) );
	t.set( "VerticalTilde;", chr(8768) );
	t.set( "VeryThinSpace;", chr(8202) );
	t.set( "Vfr;", chr(120089) );
	t.set( "Vopf;", chr(120141) );
	t.set( "Vscr;", chr(119985) );
	t.set( "Vvdash;", chr(8874) );
	t.set( "Wcirc;", chr(372) );
	t.set( "Wedge;", chr(8896) );
	t.set( "Wfr;", chr(120090) );
	t.set( "Wopf;", chr(120142) );
	t.set( "Wscr;", chr(119986) );
	t.set( "Xfr;", chr(120091) );
	t.set( "Xi;", chr(926) );
	t.set( "Xopf;", chr(120143) );
	t.set( "Xscr;", chr(119987) );
	t.set( "YAcy;", chr(1071) );
	t.set( "YIcy;", chr(1031) );
	t.set( "YUcy;", chr(1070) );
	t.set( "Yacute", chr(221) );
	t.set( "Yacute;", chr(221) );
	t.set( "Ycirc;", chr(374) );
	t.set( "Ycy;", chr(1067) );
	t.set( "Yfr;", chr(120092) );
	t.set( "Yopf;", chr(120144) );
	t.set( "Yscr;", chr(119988) );
	t.set( "Yuml;", chr(376) );
	t.set( "ZHcy;", chr(1046) );
	t.set( "Zacute;", chr(377) );
	t.set( "Zcaron;", chr(381) );
	t.set( "Zcy;", chr(1047) );
	t.set( "Zdot;", chr(379) );
	t.set( "ZeroWidthSpace;", chr(8203) );
	t.set( "Zeta;", chr(918) );
	t.set( "Zfr;", chr(8488) );
	t.set( "Zopf;", chr(8484) );
	t.set( "Zscr;", chr(119989) );
	t.set( "aacute", chr(225) );
	t.set( "aacute;", chr(225) );
	t.set( "abreve;", chr(259) );
	t.set( "ac;", chr(8766) );
	t.set( "acE;", chr(8766) _ chr(819) );
	t.set( "acd;", chr(8767) );
	t.set( "acirc", chr(226) );
	t.set( "acirc;", chr(226) );
	t.set( "acute", chr(180) );
	t.set( "acute;", chr(180) );
	t.set( "acy;", chr(1072) );
	t.set( "aelig", chr(230) );
	t.set( "aelig;", chr(230) );
	t.set( "af;", chr(8289) );
	t.set( "afr;", chr(120094) );
	t.set( "agrave", chr(224) );
	t.set( "agrave;", chr(224) );
	t.set( "alefsym;", chr(8501) );
	t.set( "aleph;", chr(8501) );
	t.set( "alpha;", chr(945) );
	t.set( "amacr;", chr(257) );
	t.set( "amalg;", chr(10815) );
	t.set( "amp", chr(38) );
	t.set( "amp;", chr(38) );
	t.set( "and;", chr(8743) );
	t.set( "andand;", chr(10837) );
	t.set( "andd;", chr(10844) );
	t.set( "andslope;", chr(10840) );
	t.set( "andv;", chr(10842) );
	t.set( "ang;", chr(8736) );
	t.set( "ange;", chr(10660) );
	t.set( "angle;", chr(8736) );
	t.set( "angmsd;", chr(8737) );
	t.set( "angmsdaa;", chr(10664) );
	t.set( "angmsdab;", chr(10665) );
	t.set( "angmsdac;", chr(10666) );
	t.set( "angmsdad;", chr(10667) );
	t.set( "angmsdae;", chr(10668) );
	t.set( "angmsdaf;", chr(10669) );
	t.set( "angmsdag;", chr(10670) );
	t.set( "angmsdah;", chr(10671) );
	t.set( "angrt;", chr(8735) );
	t.set( "angrtvb;", chr(8894) );
	t.set( "angrtvbd;", chr(10653) );
	t.set( "angsph;", chr(8738) );
	t.set( "angst;", chr(197) );
	t.set( "angzarr;", chr(9084) );
	t.set( "aogon;", chr(261) );
	t.set( "aopf;", chr(120146) );
	t.set( "ap;", chr(8776) );
	t.set( "apE;", chr(10864) );
	t.set( "apacir;", chr(10863) );
	t.set( "ape;", chr(8778) );
	t.set( "apid;", chr(8779) );
	t.set( "apos;", chr(39) );
	t.set( "approx;", chr(8776) );
	t.set( "approxeq;", chr(8778) );
	t.set( "aring", chr(229) );
	t.set( "aring;", chr(229) );
	t.set( "ascr;", chr(119990) );
	t.set( "ast;", chr(42) );
	t.set( "asymp;", chr(8776) );
	t.set( "asympeq;", chr(8781) );
	t.set( "atilde", chr(227) );
	t.set( "atilde;", chr(227) );
	t.set( "auml", chr(228) );
	t.set( "auml;", chr(228) );
	t.set( "awconint;", chr(8755) );
	t.set( "awint;", chr(10769) );
	t.set( "bNot;", chr(10989) );
	t.set( "backcong;", chr(8780) );
	t.set( "backepsilon;", chr(1014) );
	t.set( "backprime;", chr(8245) );
	t.set( "backsim;", chr(8765) );
	t.set( "backsimeq;", chr(8909) );
	t.set( "barvee;", chr(8893) );
	t.set( "barwed;", chr(8965) );
	t.set( "barwedge;", chr(8965) );
	t.set( "bbrk;", chr(9141) );
	t.set( "bbrktbrk;", chr(9142) );
	t.set( "bcong;", chr(8780) );
	t.set( "bcy;", chr(1073) );
	t.set( "bdquo;", chr(8222) );
	t.set( "becaus;", chr(8757) );
	t.set( "because;", chr(8757) );
	t.set( "bemptyv;", chr(10672) );
	t.set( "bepsi;", chr(1014) );
	t.set( "bernou;", chr(8492) );
	t.set( "beta;", chr(946) );
	t.set( "beth;", chr(8502) );
	t.set( "between;", chr(8812) );
	t.set( "bfr;", chr(120095) );
	t.set( "bigcap;", chr(8898) );
	t.set( "bigcirc;", chr(9711) );
	t.set( "bigcup;", chr(8899) );
	t.set( "bigodot;", chr(10752) );
	t.set( "bigoplus;", chr(10753) );
	t.set( "bigotimes;", chr(10754) );
	t.set( "bigsqcup;", chr(10758) );
	t.set( "bigstar;", chr(9733) );
	t.set( "bigtriangledown;", chr(9661) );
	t.set( "bigtriangleup;", chr(9651) );
	t.set( "biguplus;", chr(10756) );
	t.set( "bigvee;", chr(8897) );
	t.set( "bigwedge;", chr(8896) );
	t.set( "bkarow;", chr(10509) );
	t.set( "blacklozenge;", chr(10731) );
	t.set( "blacksquare;", chr(9642) );
	t.set( "blacktriangle;", chr(9652) );
	t.set( "blacktriangledown;", chr(9662) );
	t.set( "blacktriangleleft;", chr(9666) );
	t.set( "blacktriangleright;", chr(9656) );
	t.set( "blank;", chr(9251) );
	t.set( "blk12;", chr(9618) );
	t.set( "blk14;", chr(9617) );
	t.set( "blk34;", chr(9619) );
	t.set( "block;", chr(9608) );
	t.set( "bne;", chr(61) _ chr(8421) );
	t.set( "bnequiv;", chr(8801) _ chr(8421) );
	t.set( "bnot;", chr(8976) );
	t.set( "bopf;", chr(120147) );
	t.set( "bot;", chr(8869) );
	t.set( "bottom;", chr(8869) );
	t.set( "bowtie;", chr(8904) );
	t.set( "boxDL;", chr(9559) );
	t.set( "boxDR;", chr(9556) );
	t.set( "boxDl;", chr(9558) );
	t.set( "boxDr;", chr(9555) );
	t.set( "boxH;", chr(9552) );
	t.set( "boxHD;", chr(9574) );
	t.set( "boxHU;", chr(9577) );
	t.set( "boxHd;", chr(9572) );
	t.set( "boxHu;", chr(9575) );
	t.set( "boxUL;", chr(9565) );
	t.set( "boxUR;", chr(9562) );
	t.set( "boxUl;", chr(9564) );
	t.set( "boxUr;", chr(9561) );
	t.set( "boxV;", chr(9553) );
	t.set( "boxVH;", chr(9580) );
	t.set( "boxVL;", chr(9571) );
	t.set( "boxVR;", chr(9568) );
	t.set( "boxVh;", chr(9579) );
	t.set( "boxVl;", chr(9570) );
	t.set( "boxVr;", chr(9567) );
	t.set( "boxbox;", chr(10697) );
	t.set( "boxdL;", chr(9557) );
	t.set( "boxdR;", chr(9554) );
	t.set( "boxdl;", chr(9488) );
	t.set( "boxdr;", chr(9484) );
	t.set( "boxh;", chr(9472) );
	t.set( "boxhD;", chr(9573) );
	t.set( "boxhU;", chr(9576) );
	t.set( "boxhd;", chr(9516) );
	t.set( "boxhu;", chr(9524) );
	t.set( "boxminus;", chr(8863) );
	t.set( "boxplus;", chr(8862) );
	t.set( "boxtimes;", chr(8864) );
	t.set( "boxuL;", chr(9563) );
	t.set( "boxuR;", chr(9560) );
	t.set( "boxul;", chr(9496) );
	t.set( "boxur;", chr(9492) );
	t.set( "boxv;", chr(9474) );
	t.set( "boxvH;", chr(9578) );
	t.set( "boxvL;", chr(9569) );
	t.set( "boxvR;", chr(9566) );
	t.set( "boxvh;", chr(9532) );
	t.set( "boxvl;", chr(9508) );
	t.set( "boxvr;", chr(9500) );
	t.set( "bprime;", chr(8245) );
	t.set( "breve;", chr(728) );
	t.set( "brvbar", chr(166) );
	t.set( "brvbar;", chr(166) );
	t.set( "bscr;", chr(119991) );
	t.set( "bsemi;", chr(8271) );
	t.set( "bsim;", chr(8765) );
	t.set( "bsime;", chr(8909) );
	t.set( "bsol;", chr(92) );
	t.set( "bsolb;", chr(10693) );
	t.set( "bsolhsub;", chr(10184) );
	t.set( "bull;", chr(8226) );
	t.set( "bullet;", chr(8226) );
	t.set( "bump;", chr(8782) );
	t.set( "bumpE;", chr(10926) );
	t.set( "bumpe;", chr(8783) );
	t.set( "bumpeq;", chr(8783) );
	t.set( "cacute;", chr(263) );
	t.set( "cap;", chr(8745) );
	t.set( "capand;", chr(10820) );
	t.set( "capbrcup;", chr(10825) );
	t.set( "capcap;", chr(10827) );
	t.set( "capcup;", chr(10823) );
	t.set( "capdot;", chr(10816) );
	t.set( "caps;", chr(8745) _ chr(65024) );
	t.set( "caret;", chr(8257) );
	t.set( "caron;", chr(711) );
	t.set( "ccaps;", chr(10829) );
	t.set( "ccaron;", chr(269) );
	t.set( "ccedil", chr(231) );
	t.set( "ccedil;", chr(231) );
	t.set( "ccirc;", chr(265) );
	t.set( "ccups;", chr(10828) );
	t.set( "ccupssm;", chr(10832) );
	t.set( "cdot;", chr(267) );
	t.set( "cedil", chr(184) );
	t.set( "cedil;", chr(184) );
	t.set( "cemptyv;", chr(10674) );
	t.set( "cent", chr(162) );
	t.set( "cent;", chr(162) );
	t.set( "centerdot;", chr(183) );
	t.set( "cfr;", chr(120096) );
	t.set( "chcy;", chr(1095) );
	t.set( "check;", chr(10003) );
	t.set( "checkmark;", chr(10003) );
	t.set( "chi;", chr(967) );
	t.set( "cir;", chr(9675) );
	t.set( "cirE;", chr(10691) );
	t.set( "circ;", chr(710) );
	t.set( "circeq;", chr(8791) );
	t.set( "circlearrowleft;", chr(8634) );
	t.set( "circlearrowright;", chr(8635) );
	t.set( "circledR;", chr(174) );
	t.set( "circledS;", chr(9416) );
	t.set( "circledast;", chr(8859) );
	t.set( "circledcirc;", chr(8858) );
	t.set( "circleddash;", chr(8861) );
	t.set( "cire;", chr(8791) );
	t.set( "cirfnint;", chr(10768) );
	t.set( "cirmid;", chr(10991) );
	t.set( "cirscir;", chr(10690) );
	t.set( "clubs;", chr(9827) );
	t.set( "clubsuit;", chr(9827) );
	t.set( "colon;", chr(58) );
	t.set( "colone;", chr(8788) );
	t.set( "coloneq;", chr(8788) );
	t.set( "comma;", chr(44) );
	t.set( "commat;", chr(64) );
	t.set( "comp;", chr(8705) );
	t.set( "compfn;", chr(8728) );
	t.set( "complement;", chr(8705) );
	t.set( "complexes;", chr(8450) );
	t.set( "cong;", chr(8773) );
	t.set( "congdot;", chr(10861) );
	t.set( "conint;", chr(8750) );
	t.set( "copf;", chr(120148) );
	t.set( "coprod;", chr(8720) );
	t.set( "copy", chr(169) );
	t.set( "copy;", chr(169) );
	t.set( "copysr;", chr(8471) );
	t.set( "crarr;", chr(8629) );
	t.set( "cross;", chr(10007) );
	t.set( "cscr;", chr(119992) );
	t.set( "csub;", chr(10959) );
	t.set( "csube;", chr(10961) );
	t.set( "csup;", chr(10960) );
	t.set( "csupe;", chr(10962) );
	t.set( "ctdot;", chr(8943) );
	t.set( "cudarrl;", chr(10552) );
	t.set( "cudarrr;", chr(10549) );
	t.set( "cuepr;", chr(8926) );
	t.set( "cuesc;", chr(8927) );
	t.set( "cularr;", chr(8630) );
	t.set( "cularrp;", chr(10557) );
	t.set( "cup;", chr(8746) );
	t.set( "cupbrcap;", chr(10824) );
	t.set( "cupcap;", chr(10822) );
	t.set( "cupcup;", chr(10826) );
	t.set( "cupdot;", chr(8845) );
	t.set( "cupor;", chr(10821) );
	t.set( "cups;", chr(8746) _ chr(65024) );
	t.set( "curarr;", chr(8631) );
	t.set( "curarrm;", chr(10556) );
	t.set( "curlyeqprec;", chr(8926) );
	t.set( "curlyeqsucc;", chr(8927) );
	t.set( "curlyvee;", chr(8910) );
	t.set( "curlywedge;", chr(8911) );
	t.set( "curren", chr(164) );
	t.set( "curren;", chr(164) );
	t.set( "curvearrowleft;", chr(8630) );
	t.set( "curvearrowright;", chr(8631) );
	t.set( "cuvee;", chr(8910) );
	t.set( "cuwed;", chr(8911) );
	t.set( "cwconint;", chr(8754) );
	t.set( "cwint;", chr(8753) );
	t.set( "cylcty;", chr(9005) );
	t.set( "dArr;", chr(8659) );
	t.set( "dHar;", chr(10597) );
	t.set( "dagger;", chr(8224) );
	t.set( "daleth;", chr(8504) );
	t.set( "darr;", chr(8595) );
	t.set( "dash;", chr(8208) );
	t.set( "dashv;", chr(8867) );
	t.set( "dbkarow;", chr(10511) );
	t.set( "dblac;", chr(733) );
	t.set( "dcaron;", chr(271) );
	t.set( "dcy;", chr(1076) );
	t.set( "dd;", chr(8518) );
	t.set( "ddagger;", chr(8225) );
	t.set( "ddarr;", chr(8650) );
	t.set( "ddotseq;", chr(10871) );
	t.set( "deg", chr(176) );
	t.set( "deg;", chr(176) );
	t.set( "delta;", chr(948) );
	t.set( "demptyv;", chr(10673) );
	t.set( "dfisht;", chr(10623) );
	t.set( "dfr;", chr(120097) );
	t.set( "dharl;", chr(8643) );
	t.set( "dharr;", chr(8642) );
	t.set( "diam;", chr(8900) );
	t.set( "diamond;", chr(8900) );
	t.set( "diamondsuit;", chr(9830) );
	t.set( "diams;", chr(9830) );
	t.set( "die;", chr(168) );
	t.set( "digamma;", chr(989) );
	t.set( "disin;", chr(8946) );
	t.set( "div;", chr(247) );
	t.set( "divide", chr(247) );
	t.set( "divide;", chr(247) );
	t.set( "divideontimes;", chr(8903) );
	t.set( "divonx;", chr(8903) );
	t.set( "djcy;", chr(1106) );
	t.set( "dlcorn;", chr(8990) );
	t.set( "dlcrop;", chr(8973) );
	t.set( "dollar;", chr(36) );
	t.set( "dopf;", chr(120149) );
	t.set( "dot;", chr(729) );
	t.set( "doteq;", chr(8784) );
	t.set( "doteqdot;", chr(8785) );
	t.set( "dotminus;", chr(8760) );
	t.set( "dotplus;", chr(8724) );
	t.set( "dotsquare;", chr(8865) );
	t.set( "doublebarwedge;", chr(8966) );
	t.set( "downarrow;", chr(8595) );
	t.set( "downdownarrows;", chr(8650) );
	t.set( "downharpoonleft;", chr(8643) );
	t.set( "downharpoonright;", chr(8642) );
	t.set( "drbkarow;", chr(10512) );
	t.set( "drcorn;", chr(8991) );
	t.set( "drcrop;", chr(8972) );
	t.set( "dscr;", chr(119993) );
	t.set( "dscy;", chr(1109) );
	t.set( "dsol;", chr(10742) );
	t.set( "dstrok;", chr(273) );
	t.set( "dtdot;", chr(8945) );
	t.set( "dtri;", chr(9663) );
	t.set( "dtrif;", chr(9662) );
	t.set( "duarr;", chr(8693) );
	t.set( "duhar;", chr(10607) );
	t.set( "dwangle;", chr(10662) );
	t.set( "dzcy;", chr(1119) );
	t.set( "dzigrarr;", chr(10239) );
	t.set( "eDDot;", chr(10871) );
	t.set( "eDot;", chr(8785) );
	t.set( "eacute", chr(233) );
	t.set( "eacute;", chr(233) );
	t.set( "easter;", chr(10862) );
	t.set( "ecaron;", chr(283) );
	t.set( "ecir;", chr(8790) );
	t.set( "ecirc", chr(234) );
	t.set( "ecirc;", chr(234) );
	t.set( "ecolon;", chr(8789) );
	t.set( "ecy;", chr(1101) );
	t.set( "edot;", chr(279) );
	t.set( "ee;", chr(8519) );
	t.set( "efDot;", chr(8786) );
	t.set( "efr;", chr(120098) );
	t.set( "eg;", chr(10906) );
	t.set( "egrave", chr(232) );
	t.set( "egrave;", chr(232) );
	t.set( "egs;", chr(10902) );
	t.set( "egsdot;", chr(10904) );
	t.set( "el;", chr(10905) );
	t.set( "elinters;", chr(9191) );
	t.set( "ell;", chr(8467) );
	t.set( "els;", chr(10901) );
	t.set( "elsdot;", chr(10903) );
	t.set( "emacr;", chr(275) );
	t.set( "empty;", chr(8709) );
	t.set( "emptyset;", chr(8709) );
	t.set( "emptyv;", chr(8709) );
	t.set( "emsp13;", chr(8196) );
	t.set( "emsp14;", chr(8197) );
	t.set( "emsp;", chr(8195) );
	t.set( "eng;", chr(331) );
	t.set( "ensp;", chr(8194) );
	t.set( "eogon;", chr(281) );
	t.set( "eopf;", chr(120150) );
	t.set( "epar;", chr(8917) );
	t.set( "eparsl;", chr(10723) );
	t.set( "eplus;", chr(10865) );
	t.set( "epsi;", chr(949) );
	t.set( "epsilon;", chr(949) );
	t.set( "epsiv;", chr(1013) );
	t.set( "eqcirc;", chr(8790) );
	t.set( "eqcolon;", chr(8789) );
	t.set( "eqsim;", chr(8770) );
	t.set( "eqslantgtr;", chr(10902) );
	t.set( "eqslantless;", chr(10901) );
	t.set( "equals;", chr(61) );
	t.set( "equest;", chr(8799) );
	t.set( "equiv;", chr(8801) );
	t.set( "equivDD;", chr(10872) );
	t.set( "eqvparsl;", chr(10725) );
	t.set( "erDot;", chr(8787) );
	t.set( "erarr;", chr(10609) );
	t.set( "escr;", chr(8495) );
	t.set( "esdot;", chr(8784) );
	t.set( "esim;", chr(8770) );
	t.set( "eta;", chr(951) );
	t.set( "eth", chr(240) );
	t.set( "eth;", chr(240) );
	t.set( "euml", chr(235) );
	t.set( "euml;", chr(235) );
	t.set( "euro;", chr(8364) );
	t.set( "excl;", chr(33) );
	t.set( "exist;", chr(8707) );
	t.set( "expectation;", chr(8496) );
	t.set( "exponentiale;", chr(8519) );
	t.set( "fallingdotseq;", chr(8786) );
	t.set( "fcy;", chr(1092) );
	t.set( "female;", chr(9792) );
	t.set( "ffilig;", chr(64259) );
	t.set( "fflig;", chr(64256) );
	t.set( "ffllig;", chr(64260) );
	t.set( "ffr;", chr(120099) );
	t.set( "filig;", chr(64257) );
	t.set( "fjlig;", chr(102) _ chr(106) );
	t.set( "flat;", chr(9837) );
	t.set( "fllig;", chr(64258) );
	t.set( "fltns;", chr(9649) );
	t.set( "fnof;", chr(402) );
	t.set( "fopf;", chr(120151) );
	t.set( "forall;", chr(8704) );
	t.set( "fork;", chr(8916) );
	t.set( "forkv;", chr(10969) );
	t.set( "fpartint;", chr(10765) );
	t.set( "frac12", chr(189) );
	t.set( "frac12;", chr(189) );
	t.set( "frac13;", chr(8531) );
	t.set( "frac14", chr(188) );
	t.set( "frac14;", chr(188) );
	t.set( "frac15;", chr(8533) );
	t.set( "frac16;", chr(8537) );
	t.set( "frac18;", chr(8539) );
	t.set( "frac23;", chr(8532) );
	t.set( "frac25;", chr(8534) );
	t.set( "frac34", chr(190) );
	t.set( "frac34;", chr(190) );
	t.set( "frac35;", chr(8535) );
	t.set( "frac38;", chr(8540) );
	t.set( "frac45;", chr(8536) );
	t.set( "frac56;", chr(8538) );
	t.set( "frac58;", chr(8541) );
	t.set( "frac78;", chr(8542) );
	t.set( "frasl;", chr(8260) );
	t.set( "frown;", chr(8994) );
	t.set( "fscr;", chr(119995) );
	t.set( "gE;", chr(8807) );
	t.set( "gEl;", chr(10892) );
	t.set( "gacute;", chr(501) );
	t.set( "gamma;", chr(947) );
	t.set( "gammad;", chr(989) );
	t.set( "gap;", chr(10886) );
	t.set( "gbreve;", chr(287) );
	t.set( "gcirc;", chr(285) );
	t.set( "gcy;", chr(1075) );
	t.set( "gdot;", chr(289) );
	t.set( "ge;", chr(8805) );
	t.set( "gel;", chr(8923) );
	t.set( "geq;", chr(8805) );
	t.set( "geqq;", chr(8807) );
	t.set( "geqslant;", chr(10878) );
	t.set( "ges;", chr(10878) );
	t.set( "gescc;", chr(10921) );
	t.set( "gesdot;", chr(10880) );
	t.set( "gesdoto;", chr(10882) );
	t.set( "gesdotol;", chr(10884) );
	t.set( "gesl;", chr(8923) _ chr(65024) );
	t.set( "gesles;", chr(10900) );
	t.set( "gfr;", chr(120100) );
	t.set( "gg;", chr(8811) );
	t.set( "ggg;", chr(8921) );
	t.set( "gimel;", chr(8503) );
	t.set( "gjcy;", chr(1107) );
	t.set( "gl;", chr(8823) );
	t.set( "glE;", chr(10898) );
	t.set( "gla;", chr(10917) );
	t.set( "glj;", chr(10916) );
	t.set( "gnE;", chr(8809) );
	t.set( "gnap;", chr(10890) );
	t.set( "gnapprox;", chr(10890) );
	t.set( "gne;", chr(10888) );
	t.set( "gneq;", chr(10888) );
	t.set( "gneqq;", chr(8809) );
	t.set( "gnsim;", chr(8935) );
	t.set( "gopf;", chr(120152) );
	t.set( "grave;", chr(96) );
	t.set( "gscr;", chr(8458) );
	t.set( "gsim;", chr(8819) );
	t.set( "gsime;", chr(10894) );
	t.set( "gsiml;", chr(10896) );
	t.set( "gt", chr(62) );
	t.set( "gt;", chr(62) );
	t.set( "gtcc;", chr(10919) );
	t.set( "gtcir;", chr(10874) );
	t.set( "gtdot;", chr(8919) );
	t.set( "gtlPar;", chr(10645) );
	t.set( "gtquest;", chr(10876) );
	t.set( "gtrapprox;", chr(10886) );
	t.set( "gtrarr;", chr(10616) );
	t.set( "gtrdot;", chr(8919) );
	t.set( "gtreqless;", chr(8923) );
	t.set( "gtreqqless;", chr(10892) );
	t.set( "gtrless;", chr(8823) );
	t.set( "gtrsim;", chr(8819) );
	t.set( "gvertneqq;", chr(8809) _ chr(65024) );
	t.set( "gvnE;", chr(8809) _ chr(65024) );
	t.set( "hArr;", chr(8660) );
	t.set( "hairsp;", chr(8202) );
	t.set( "half;", chr(189) );
	t.set( "hamilt;", chr(8459) );
	t.set( "hardcy;", chr(1098) );
	t.set( "harr;", chr(8596) );
	t.set( "harrcir;", chr(10568) );
	t.set( "harrw;", chr(8621) );
	t.set( "hbar;", chr(8463) );
	t.set( "hcirc;", chr(293) );
	t.set( "hearts;", chr(9829) );
	t.set( "heartsuit;", chr(9829) );
	t.set( "hellip;", chr(8230) );
	t.set( "hercon;", chr(8889) );
	t.set( "hfr;", chr(120101) );
	t.set( "hksearow;", chr(10533) );
	t.set( "hkswarow;", chr(10534) );
	t.set( "hoarr;", chr(8703) );
	t.set( "homtht;", chr(8763) );
	t.set( "hookleftarrow;", chr(8617) );
	t.set( "hookrightarrow;", chr(8618) );
	t.set( "hopf;", chr(120153) );
	t.set( "horbar;", chr(8213) );
	t.set( "hscr;", chr(119997) );
	t.set( "hslash;", chr(8463) );
	t.set( "hstrok;", chr(295) );
	t.set( "hybull;", chr(8259) );
	t.set( "hyphen;", chr(8208) );
	t.set( "iacute", chr(237) );
	t.set( "iacute;", chr(237) );
	t.set( "ic;", chr(8291) );
	t.set( "icirc", chr(238) );
	t.set( "icirc;", chr(238) );
	t.set( "icy;", chr(1080) );
	t.set( "iecy;", chr(1077) );
	t.set( "iexcl", chr(161) );
	t.set( "iexcl;", chr(161) );
	t.set( "iff;", chr(8660) );
	t.set( "ifr;", chr(120102) );
	t.set( "igrave", chr(236) );
	t.set( "igrave;", chr(236) );
	t.set( "ii;", chr(8520) );
	t.set( "iiiint;", chr(10764) );
	t.set( "iiint;", chr(8749) );
	t.set( "iinfin;", chr(10716) );
	t.set( "iiota;", chr(8489) );
	t.set( "ijlig;", chr(307) );
	t.set( "imacr;", chr(299) );
	t.set( "image;", chr(8465) );
	t.set( "imagline;", chr(8464) );
	t.set( "imagpart;", chr(8465) );
	t.set( "imath;", chr(305) );
	t.set( "imof;", chr(8887) );
	t.set( "imped;", chr(437) );
	t.set( "in;", chr(8712) );
	t.set( "incare;", chr(8453) );
	t.set( "infin;", chr(8734) );
	t.set( "infintie;", chr(10717) );
	t.set( "inodot;", chr(305) );
	t.set( "int;", chr(8747) );
	t.set( "intcal;", chr(8890) );
	t.set( "integers;", chr(8484) );
	t.set( "intercal;", chr(8890) );
	t.set( "intlarhk;", chr(10775) );
	t.set( "intprod;", chr(10812) );
	t.set( "iocy;", chr(1105) );
	t.set( "iogon;", chr(303) );
	t.set( "iopf;", chr(120154) );
	t.set( "iota;", chr(953) );
	t.set( "iprod;", chr(10812) );
	t.set( "iquest", chr(191) );
	t.set( "iquest;", chr(191) );
	t.set( "iscr;", chr(119998) );
	t.set( "isin;", chr(8712) );
	t.set( "isinE;", chr(8953) );
	t.set( "isindot;", chr(8949) );
	t.set( "isins;", chr(8948) );
	t.set( "isinsv;", chr(8947) );
	t.set( "isinv;", chr(8712) );
	t.set( "it;", chr(8290) );
	t.set( "itilde;", chr(297) );
	t.set( "iukcy;", chr(1110) );
	t.set( "iuml", chr(239) );
	t.set( "iuml;", chr(239) );
	t.set( "jcirc;", chr(309) );
	t.set( "jcy;", chr(1081) );
	t.set( "jfr;", chr(120103) );
	t.set( "jmath;", chr(567) );
	t.set( "jopf;", chr(120155) );
	t.set( "jscr;", chr(119999) );
	t.set( "jsercy;", chr(1112) );
	t.set( "jukcy;", chr(1108) );
	t.set( "kappa;", chr(954) );
	t.set( "kappav;", chr(1008) );
	t.set( "kcedil;", chr(311) );
	t.set( "kcy;", chr(1082) );
	t.set( "kfr;", chr(120104) );
	t.set( "kgreen;", chr(312) );
	t.set( "khcy;", chr(1093) );
	t.set( "kjcy;", chr(1116) );
	t.set( "kopf;", chr(120156) );
	t.set( "kscr;", chr(120000) );
	t.set( "lAarr;", chr(8666) );
	t.set( "lArr;", chr(8656) );
	t.set( "lAtail;", chr(10523) );
	t.set( "lBarr;", chr(10510) );
	t.set( "lE;", chr(8806) );
	t.set( "lEg;", chr(10891) );
	t.set( "lHar;", chr(10594) );
	t.set( "lacute;", chr(314) );
	t.set( "laemptyv;", chr(10676) );
	t.set( "lagran;", chr(8466) );
	t.set( "lambda;", chr(955) );
	t.set( "lang;", chr(10216) );
	t.set( "langd;", chr(10641) );
	t.set( "langle;", chr(10216) );
	t.set( "lap;", chr(10885) );
	t.set( "laquo", chr(171) );
	t.set( "laquo;", chr(171) );
	t.set( "larr;", chr(8592) );
	t.set( "larrb;", chr(8676) );
	t.set( "larrbfs;", chr(10527) );
	t.set( "larrfs;", chr(10525) );
	t.set( "larrhk;", chr(8617) );
	t.set( "larrlp;", chr(8619) );
	t.set( "larrpl;", chr(10553) );
	t.set( "larrsim;", chr(10611) );
	t.set( "larrtl;", chr(8610) );
	t.set( "lat;", chr(10923) );
	t.set( "latail;", chr(10521) );
	t.set( "late;", chr(10925) );
	t.set( "lates;", chr(10925) _ chr(65024) );
	t.set( "lbarr;", chr(10508) );
	t.set( "lbbrk;", chr(10098) );
	t.set( "lbrace;", chr(123) );
	t.set( "lbrack;", chr(91) );
	t.set( "lbrke;", chr(10635) );
	t.set( "lbrksld;", chr(10639) );
	t.set( "lbrkslu;", chr(10637) );
	t.set( "lcaron;", chr(318) );
	t.set( "lcedil;", chr(316) );
	t.set( "lceil;", chr(8968) );
	t.set( "lcub;", chr(123) );
	t.set( "lcy;", chr(1083) );
	t.set( "ldca;", chr(10550) );
	t.set( "ldquo;", chr(8220) );
	t.set( "ldquor;", chr(8222) );
	t.set( "ldrdhar;", chr(10599) );
	t.set( "ldrushar;", chr(10571) );
	t.set( "ldsh;", chr(8626) );
	t.set( "le;", chr(8804) );
	t.set( "leftarrow;", chr(8592) );
	t.set( "leftarrowtail;", chr(8610) );
	t.set( "leftharpoondown;", chr(8637) );
	t.set( "leftharpoonup;", chr(8636) );
	t.set( "leftleftarrows;", chr(8647) );
	t.set( "leftrightarrow;", chr(8596) );
	t.set( "leftrightarrows;", chr(8646) );
	t.set( "leftrightharpoons;", chr(8651) );
	t.set( "leftrightsquigarrow;", chr(8621) );
	t.set( "leftthreetimes;", chr(8907) );
	t.set( "leg;", chr(8922) );
	t.set( "leq;", chr(8804) );
	t.set( "leqq;", chr(8806) );
	t.set( "leqslant;", chr(10877) );
	t.set( "les;", chr(10877) );
	t.set( "lescc;", chr(10920) );
	t.set( "lesdot;", chr(10879) );
	t.set( "lesdoto;", chr(10881) );
	t.set( "lesdotor;", chr(10883) );
	t.set( "lesg;", chr(8922) _ chr(65024) );
	t.set( "lesges;", chr(10899) );
	t.set( "lessapprox;", chr(10885) );
	t.set( "lessdot;", chr(8918) );
	t.set( "lesseqgtr;", chr(8922) );
	t.set( "lesseqqgtr;", chr(10891) );
	t.set( "lessgtr;", chr(8822) );
	t.set( "lesssim;", chr(8818) );
	t.set( "lfisht;", chr(10620) );
	t.set( "lfloor;", chr(8970) );
	t.set( "lfr;", chr(120105) );
	t.set( "lg;", chr(8822) );
	t.set( "lgE;", chr(10897) );
	t.set( "lhard;", chr(8637) );
	t.set( "lharu;", chr(8636) );
	t.set( "lharul;", chr(10602) );
	t.set( "lhblk;", chr(9604) );
	t.set( "ljcy;", chr(1113) );
	t.set( "ll;", chr(8810) );
	t.set( "llarr;", chr(8647) );
	t.set( "llcorner;", chr(8990) );
	t.set( "llhard;", chr(10603) );
	t.set( "lltri;", chr(9722) );
	t.set( "lmidot;", chr(320) );
	t.set( "lmoust;", chr(9136) );
	t.set( "lmoustache;", chr(9136) );
	t.set( "lnE;", chr(8808) );
	t.set( "lnap;", chr(10889) );
	t.set( "lnapprox;", chr(10889) );
	t.set( "lne;", chr(10887) );
	t.set( "lneq;", chr(10887) );
	t.set( "lneqq;", chr(8808) );
	t.set( "lnsim;", chr(8934) );
	t.set( "loang;", chr(10220) );
	t.set( "loarr;", chr(8701) );
	t.set( "lobrk;", chr(10214) );
	t.set( "longleftarrow;", chr(10229) );
	t.set( "longleftrightarrow;", chr(10231) );
	t.set( "longmapsto;", chr(10236) );
	t.set( "longrightarrow;", chr(10230) );
	t.set( "looparrowleft;", chr(8619) );
	t.set( "looparrowright;", chr(8620) );
	t.set( "lopar;", chr(10629) );
	t.set( "lopf;", chr(120157) );
	t.set( "loplus;", chr(10797) );
	t.set( "lotimes;", chr(10804) );
	t.set( "lowast;", chr(8727) );
	t.set( "lowbar;", chr(95) );
	t.set( "loz;", chr(9674) );
	t.set( "lozenge;", chr(9674) );
	t.set( "lozf;", chr(10731) );
	t.set( "lpar;", chr(40) );
	t.set( "lparlt;", chr(10643) );
	t.set( "lrarr;", chr(8646) );
	t.set( "lrcorner;", chr(8991) );
	t.set( "lrhar;", chr(8651) );
	t.set( "lrhard;", chr(10605) );
	t.set( "lrm;", chr(8206) );
	t.set( "lrtri;", chr(8895) );
	t.set( "lsaquo;", chr(8249) );
	t.set( "lscr;", chr(120001) );
	t.set( "lsh;", chr(8624) );
	t.set( "lsim;", chr(8818) );
	t.set( "lsime;", chr(10893) );
	t.set( "lsimg;", chr(10895) );
	t.set( "lsqb;", chr(91) );
	t.set( "lsquo;", chr(8216) );
	t.set( "lsquor;", chr(8218) );
	t.set( "lstrok;", chr(322) );
	t.set( "lt", chr(60) );
	t.set( "lt;", chr(60) );
	t.set( "ltcc;", chr(10918) );
	t.set( "ltcir;", chr(10873) );
	t.set( "ltdot;", chr(8918) );
	t.set( "lthree;", chr(8907) );
	t.set( "ltimes;", chr(8905) );
	t.set( "ltlarr;", chr(10614) );
	t.set( "ltquest;", chr(10875) );
	t.set( "ltrPar;", chr(10646) );
	t.set( "ltri;", chr(9667) );
	t.set( "ltrie;", chr(8884) );
	t.set( "ltrif;", chr(9666) );
	t.set( "lurdshar;", chr(10570) );
	t.set( "luruhar;", chr(10598) );
	t.set( "lvertneqq;", chr(8808) _ chr(65024) );
	t.set( "lvnE;", chr(8808) _ chr(65024) );
	t.set( "mDDot;", chr(8762) );
	t.set( "macr", chr(175) );
	t.set( "macr;", chr(175) );
	t.set( "male;", chr(9794) );
	t.set( "malt;", chr(10016) );
	t.set( "maltese;", chr(10016) );
	t.set( "map;", chr(8614) );
	t.set( "mapsto;", chr(8614) );
	t.set( "mapstodown;", chr(8615) );
	t.set( "mapstoleft;", chr(8612) );
	t.set( "mapstoup;", chr(8613) );
	t.set( "marker;", chr(9646) );
	t.set( "mcomma;", chr(10793) );
	t.set( "mcy;", chr(1084) );
	t.set( "mdash;", chr(8212) );
	t.set( "measuredangle;", chr(8737) );
	t.set( "mfr;", chr(120106) );
	t.set( "mho;", chr(8487) );
	t.set( "micro", chr(181) );
	t.set( "micro;", chr(181) );
	t.set( "mid;", chr(8739) );
	t.set( "midast;", chr(42) );
	t.set( "midcir;", chr(10992) );
	t.set( "middot", chr(183) );
	t.set( "middot;", chr(183) );
	t.set( "minus;", chr(8722) );
	t.set( "minusb;", chr(8863) );
	t.set( "minusd;", chr(8760) );
	t.set( "minusdu;", chr(10794) );
	t.set( "mlcp;", chr(10971) );
	t.set( "mldr;", chr(8230) );
	t.set( "mnplus;", chr(8723) );
	t.set( "models;", chr(8871) );
	t.set( "mopf;", chr(120158) );
	t.set( "mp;", chr(8723) );
	t.set( "mscr;", chr(120002) );
	t.set( "mstpos;", chr(8766) );
	t.set( "mu;", chr(956) );
	t.set( "multimap;", chr(8888) );
	t.set( "mumap;", chr(8888) );
	t.set( "nGg;", chr(8921) _ chr(824) );
	t.set( "nGt;", chr(8811) _ chr(8402) );
	t.set( "nGtv;", chr(8811) _ chr(824) );
	t.set( "nLeftarrow;", chr(8653) );
	t.set( "nLeftrightarrow;", chr(8654) );
	t.set( "nLl;", chr(8920) _ chr(824) );
	t.set( "nLt;", chr(8810) _ chr(8402) );
	t.set( "nLtv;", chr(8810) _ chr(824) );
	t.set( "nRightarrow;", chr(8655) );
	t.set( "nVDash;", chr(8879) );
	t.set( "nVdash;", chr(8878) );
	t.set( "nabla;", chr(8711) );
	t.set( "nacute;", chr(324) );
	t.set( "nang;", chr(8736) _ chr(8402) );
	t.set( "nap;", chr(8777) );
	t.set( "napE;", chr(10864) _ chr(824) );
	t.set( "napid;", chr(8779) _ chr(824) );
	t.set( "napos;", chr(329) );
	t.set( "napprox;", chr(8777) );
	t.set( "natur;", chr(9838) );
	t.set( "natural;", chr(9838) );
	t.set( "naturals;", chr(8469) );
	t.set( "nbsp", chr(160) );
	t.set( "nbsp;", chr(160) );
	t.set( "nbump;", chr(8782) _ chr(824) );
	t.set( "nbumpe;", chr(8783) _ chr(824) );
	t.set( "ncap;", chr(10819) );
	t.set( "ncaron;", chr(328) );
	t.set( "ncedil;", chr(326) );
	t.set( "ncong;", chr(8775) );
	t.set( "ncongdot;", chr(10861) _ chr(824) );
	t.set( "ncup;", chr(10818) );
	t.set( "ncy;", chr(1085) );
	t.set( "ndash;", chr(8211) );
	t.set( "ne;", chr(8800) );
	t.set( "neArr;", chr(8663) );
	t.set( "nearhk;", chr(10532) );
	t.set( "nearr;", chr(8599) );
	t.set( "nearrow;", chr(8599) );
	t.set( "nedot;", chr(8784) _ chr(824) );
	t.set( "nequiv;", chr(8802) );
	t.set( "nesear;", chr(10536) );
	t.set( "nesim;", chr(8770) _ chr(824) );
	t.set( "nexist;", chr(8708) );
	t.set( "nexists;", chr(8708) );
	t.set( "nfr;", chr(120107) );
	t.set( "ngE;", chr(8807) _ chr(824) );
	t.set( "nge;", chr(8817) );
	t.set( "ngeq;", chr(8817) );
	t.set( "ngeqq;", chr(8807) _ chr(824) );
	t.set( "ngeqslant;", chr(10878) _ chr(824) );
	t.set( "nges;", chr(10878) _ chr(824) );
	t.set( "ngsim;", chr(8821) );
	t.set( "ngt;", chr(8815) );
	t.set( "ngtr;", chr(8815) );
	t.set( "nhArr;", chr(8654) );
	t.set( "nharr;", chr(8622) );
	t.set( "nhpar;", chr(10994) );
	t.set( "ni;", chr(8715) );
	t.set( "nis;", chr(8956) );
	t.set( "nisd;", chr(8954) );
	t.set( "niv;", chr(8715) );
	t.set( "njcy;", chr(1114) );
	t.set( "nlArr;", chr(8653) );
	t.set( "nlE;", chr(8806) _ chr(824) );
	t.set( "nlarr;", chr(8602) );
	t.set( "nldr;", chr(8229) );
	t.set( "nle;", chr(8816) );
	t.set( "nleftarrow;", chr(8602) );
	t.set( "nleftrightarrow;", chr(8622) );
	t.set( "nleq;", chr(8816) );
	t.set( "nleqq;", chr(8806) _ chr(824) );
	t.set( "nleqslant;", chr(10877) _ chr(824) );
	t.set( "nles;", chr(10877) _ chr(824) );
	t.set( "nless;", chr(8814) );
	t.set( "nlsim;", chr(8820) );
	t.set( "nlt;", chr(8814) );
	t.set( "nltri;", chr(8938) );
	t.set( "nltrie;", chr(8940) );
	t.set( "nmid;", chr(8740) );
	t.set( "nopf;", chr(120159) );
	t.set( "not", chr(172) );
	t.set( "not;", chr(172) );
	t.set( "notin;", chr(8713) );
	t.set( "notinE;", chr(8953) _ chr(824) );
	t.set( "notindot;", chr(8949) _ chr(824) );
	t.set( "notinva;", chr(8713) );
	t.set( "notinvb;", chr(8951) );
	t.set( "notinvc;", chr(8950) );
	t.set( "notni;", chr(8716) );
	t.set( "notniva;", chr(8716) );
	t.set( "notnivb;", chr(8958) );
	t.set( "notnivc;", chr(8957) );
	t.set( "npar;", chr(8742) );
	t.set( "nparallel;", chr(8742) );
	t.set( "nparsl;", chr(11005) _ chr(8421) );
	t.set( "npart;", chr(8706) _ chr(824) );
	t.set( "npolint;", chr(10772) );
	t.set( "npr;", chr(8832) );
	t.set( "nprcue;", chr(8928) );
	t.set( "npre;", chr(10927) _ chr(824) );
	t.set( "nprec;", chr(8832) );
	t.set( "npreceq;", chr(10927) _ chr(824) );
	t.set( "nrArr;", chr(8655) );
	t.set( "nrarr;", chr(8603) );
	t.set( "nrarrc;", chr(10547) _ chr(824) );
	t.set( "nrarrw;", chr(8605) _ chr(824) );
	t.set( "nrightarrow;", chr(8603) );
	t.set( "nrtri;", chr(8939) );
	t.set( "nrtrie;", chr(8941) );
	t.set( "nsc;", chr(8833) );
	t.set( "nsccue;", chr(8929) );
	t.set( "nsce;", chr(10928) _ chr(824) );
	t.set( "nscr;", chr(120003) );
	t.set( "nshortmid;", chr(8740) );
	t.set( "nshortparallel;", chr(8742) );
	t.set( "nsim;", chr(8769) );
	t.set( "nsime;", chr(8772) );
	t.set( "nsimeq;", chr(8772) );
	t.set( "nsmid;", chr(8740) );
	t.set( "nspar;", chr(8742) );
	t.set( "nsqsube;", chr(8930) );
	t.set( "nsqsupe;", chr(8931) );
	t.set( "nsub;", chr(8836) );
	t.set( "nsubE;", chr(10949) _ chr(824) );
	t.set( "nsube;", chr(8840) );
	t.set( "nsubset;", chr(8834) _ chr(8402) );
	t.set( "nsubseteq;", chr(8840) );
	t.set( "nsubseteqq;", chr(10949) _ chr(824) );
	t.set( "nsucc;", chr(8833) );
	t.set( "nsucceq;", chr(10928) _ chr(824) );
	t.set( "nsup;", chr(8837) );
	t.set( "nsupE;", chr(10950) _ chr(824) );
	t.set( "nsupe;", chr(8841) );
	t.set( "nsupset;", chr(8835) _ chr(8402) );
	t.set( "nsupseteq;", chr(8841) );
	t.set( "nsupseteqq;", chr(10950) _ chr(824) );
	t.set( "ntgl;", chr(8825) );
	t.set( "ntilde", chr(241) );
	t.set( "ntilde;", chr(241) );
	t.set( "ntlg;", chr(8824) );
	t.set( "ntriangleleft;", chr(8938) );
	t.set( "ntrianglelefteq;", chr(8940) );
	t.set( "ntriangleright;", chr(8939) );
	t.set( "ntrianglerighteq;", chr(8941) );
	t.set( "nu;", chr(957) );
	t.set( "num;", chr(35) );
	t.set( "numero;", chr(8470) );
	t.set( "numsp;", chr(8199) );
	t.set( "nvDash;", chr(8877) );
	t.set( "nvHarr;", chr(10500) );
	t.set( "nvap;", chr(8781) _ chr(8402) );
	t.set( "nvdash;", chr(8876) );
	t.set( "nvge;", chr(8805) _ chr(8402) );
	t.set( "nvgt;", chr(62) _ chr(8402) );
	t.set( "nvinfin;", chr(10718) );
	t.set( "nvlArr;", chr(10498) );
	t.set( "nvle;", chr(8804) _ chr(8402) );
	t.set( "nvlt;", chr(60) _ chr(8402) );
	t.set( "nvltrie;", chr(8884) _ chr(8402) );
	t.set( "nvrArr;", chr(10499) );
	t.set( "nvrtrie;", chr(8885) _ chr(8402) );
	t.set( "nvsim;", chr(8764) _ chr(8402) );
	t.set( "nwArr;", chr(8662) );
	t.set( "nwarhk;", chr(10531) );
	t.set( "nwarr;", chr(8598) );
	t.set( "nwarrow;", chr(8598) );
	t.set( "nwnear;", chr(10535) );
	t.set( "oS;", chr(9416) );
	t.set( "oacute", chr(243) );
	t.set( "oacute;", chr(243) );
	t.set( "oast;", chr(8859) );
	t.set( "ocir;", chr(8858) );
	t.set( "ocirc", chr(244) );
	t.set( "ocirc;", chr(244) );
	t.set( "ocy;", chr(1086) );
	t.set( "odash;", chr(8861) );
	t.set( "odblac;", chr(337) );
	t.set( "odiv;", chr(10808) );
	t.set( "odot;", chr(8857) );
	t.set( "odsold;", chr(10684) );
	t.set( "oelig;", chr(339) );
	t.set( "ofcir;", chr(10687) );
	t.set( "ofr;", chr(120108) );
	t.set( "ogon;", chr(731) );
	t.set( "ograve", chr(242) );
	t.set( "ograve;", chr(242) );
	t.set( "ogt;", chr(10689) );
	t.set( "ohbar;", chr(10677) );
	t.set( "ohm;", chr(937) );
	t.set( "oint;", chr(8750) );
	t.set( "olarr;", chr(8634) );
	t.set( "olcir;", chr(10686) );
	t.set( "olcross;", chr(10683) );
	t.set( "oline;", chr(8254) );
	t.set( "olt;", chr(10688) );
	t.set( "omacr;", chr(333) );
	t.set( "omega;", chr(969) );
	t.set( "omicron;", chr(959) );
	t.set( "omid;", chr(10678) );
	t.set( "ominus;", chr(8854) );
	t.set( "oopf;", chr(120160) );
	t.set( "opar;", chr(10679) );
	t.set( "operp;", chr(10681) );
	t.set( "oplus;", chr(8853) );
	t.set( "or;", chr(8744) );
	t.set( "orarr;", chr(8635) );
	t.set( "ord;", chr(10845) );
	t.set( "order;", chr(8500) );
	t.set( "orderof;", chr(8500) );
	t.set( "ordf", chr(170) );
	t.set( "ordf;", chr(170) );
	t.set( "ordm", chr(186) );
	t.set( "ordm;", chr(186) );
	t.set( "origof;", chr(8886) );
	t.set( "oror;", chr(10838) );
	t.set( "orslope;", chr(10839) );
	t.set( "orv;", chr(10843) );
	t.set( "oscr;", chr(8500) );
	t.set( "oslash", chr(248) );
	t.set( "oslash;", chr(248) );
	t.set( "osol;", chr(8856) );
	t.set( "otilde", chr(245) );
	t.set( "otilde;", chr(245) );
	t.set( "otimes;", chr(8855) );
	t.set( "otimesas;", chr(10806) );
	t.set( "ouml", chr(246) );
	t.set( "ouml;", chr(246) );
	t.set( "ovbar;", chr(9021) );
	t.set( "par;", chr(8741) );
	t.set( "para", chr(182) );
	t.set( "para;", chr(182) );
	t.set( "parallel;", chr(8741) );
	t.set( "parsim;", chr(10995) );
	t.set( "parsl;", chr(11005) );
	t.set( "part;", chr(8706) );
	t.set( "pcy;", chr(1087) );
	t.set( "percnt;", chr(37) );
	t.set( "period;", chr(46) );
	t.set( "permil;", chr(8240) );
	t.set( "perp;", chr(8869) );
	t.set( "pertenk;", chr(8241) );
	t.set( "pfr;", chr(120109) );
	t.set( "phi;", chr(966) );
	t.set( "phiv;", chr(981) );
	t.set( "phmmat;", chr(8499) );
	t.set( "phone;", chr(9742) );
	t.set( "pi;", chr(960) );
	t.set( "pitchfork;", chr(8916) );
	t.set( "piv;", chr(982) );
	t.set( "planck;", chr(8463) );
	t.set( "planckh;", chr(8462) );
	t.set( "plankv;", chr(8463) );
	t.set( "plus;", chr(43) );
	t.set( "plusacir;", chr(10787) );
	t.set( "plusb;", chr(8862) );
	t.set( "pluscir;", chr(10786) );
	t.set( "plusdo;", chr(8724) );
	t.set( "plusdu;", chr(10789) );
	t.set( "pluse;", chr(10866) );
	t.set( "plusmn", chr(177) );
	t.set( "plusmn;", chr(177) );
	t.set( "plussim;", chr(10790) );
	t.set( "plustwo;", chr(10791) );
	t.set( "pm;", chr(177) );
	t.set( "pointint;", chr(10773) );
	t.set( "popf;", chr(120161) );
	t.set( "pound", chr(163) );
	t.set( "pound;", chr(163) );
	t.set( "pr;", chr(8826) );
	t.set( "prE;", chr(10931) );
	t.set( "prap;", chr(10935) );
	t.set( "prcue;", chr(8828) );
	t.set( "pre;", chr(10927) );
	t.set( "prec;", chr(8826) );
	t.set( "precapprox;", chr(10935) );
	t.set( "preccurlyeq;", chr(8828) );
	t.set( "preceq;", chr(10927) );
	t.set( "precnapprox;", chr(10937) );
	t.set( "precneqq;", chr(10933) );
	t.set( "precnsim;", chr(8936) );
	t.set( "precsim;", chr(8830) );
	t.set( "prime;", chr(8242) );
	t.set( "primes;", chr(8473) );
	t.set( "prnE;", chr(10933) );
	t.set( "prnap;", chr(10937) );
	t.set( "prnsim;", chr(8936) );
	t.set( "prod;", chr(8719) );
	t.set( "profalar;", chr(9006) );
	t.set( "profline;", chr(8978) );
	t.set( "profsurf;", chr(8979) );
	t.set( "prop;", chr(8733) );
	t.set( "propto;", chr(8733) );
	t.set( "prsim;", chr(8830) );
	t.set( "prurel;", chr(8880) );
	t.set( "pscr;", chr(120005) );
	t.set( "psi;", chr(968) );
	t.set( "puncsp;", chr(8200) );
	t.set( "qfr;", chr(120110) );
	t.set( "qint;", chr(10764) );
	t.set( "qopf;", chr(120162) );
	t.set( "qprime;", chr(8279) );
	t.set( "qscr;", chr(120006) );
	t.set( "quaternions;", chr(8461) );
	t.set( "quatint;", chr(10774) );
	t.set( "quest;", chr(63) );
	t.set( "questeq;", chr(8799) );
	t.set( "quot", chr(34) );
	t.set( "quot;", chr(34) );
	t.set( "rAarr;", chr(8667) );
	t.set( "rArr;", chr(8658) );
	t.set( "rAtail;", chr(10524) );
	t.set( "rBarr;", chr(10511) );
	t.set( "rHar;", chr(10596) );
	t.set( "race;", chr(8765) _ chr(817) );
	t.set( "racute;", chr(341) );
	t.set( "radic;", chr(8730) );
	t.set( "raemptyv;", chr(10675) );
	t.set( "rang;", chr(10217) );
	t.set( "rangd;", chr(10642) );
	t.set( "range;", chr(10661) );
	t.set( "rangle;", chr(10217) );
	t.set( "raquo", chr(187) );
	t.set( "raquo;", chr(187) );
	t.set( "rarr;", chr(8594) );
	t.set( "rarrap;", chr(10613) );
	t.set( "rarrb;", chr(8677) );
	t.set( "rarrbfs;", chr(10528) );
	t.set( "rarrc;", chr(10547) );
	t.set( "rarrfs;", chr(10526) );
	t.set( "rarrhk;", chr(8618) );
	t.set( "rarrlp;", chr(8620) );
	t.set( "rarrpl;", chr(10565) );
	t.set( "rarrsim;", chr(10612) );
	t.set( "rarrtl;", chr(8611) );
	t.set( "rarrw;", chr(8605) );
	t.set( "ratail;", chr(10522) );
	t.set( "ratio;", chr(8758) );
	t.set( "rationals;", chr(8474) );
	t.set( "rbarr;", chr(10509) );
	t.set( "rbbrk;", chr(10099) );
	t.set( "rbrace;", chr(125) );
	t.set( "rbrack;", chr(93) );
	t.set( "rbrke;", chr(10636) );
	t.set( "rbrksld;", chr(10638) );
	t.set( "rbrkslu;", chr(10640) );
	t.set( "rcaron;", chr(345) );
	t.set( "rcedil;", chr(343) );
	t.set( "rceil;", chr(8969) );
	t.set( "rcub;", chr(125) );
	t.set( "rcy;", chr(1088) );
	t.set( "rdca;", chr(10551) );
	t.set( "rdldhar;", chr(10601) );
	t.set( "rdquo;", chr(8221) );
	t.set( "rdquor;", chr(8221) );
	t.set( "rdsh;", chr(8627) );
	t.set( "real;", chr(8476) );
	t.set( "realine;", chr(8475) );
	t.set( "realpart;", chr(8476) );
	t.set( "reals;", chr(8477) );
	t.set( "rect;", chr(9645) );
	t.set( "reg", chr(174) );
	t.set( "reg;", chr(174) );
	t.set( "rfisht;", chr(10621) );
	t.set( "rfloor;", chr(8971) );
	t.set( "rfr;", chr(120111) );
	t.set( "rhard;", chr(8641) );
	t.set( "rharu;", chr(8640) );
	t.set( "rharul;", chr(10604) );
	t.set( "rho;", chr(961) );
	t.set( "rhov;", chr(1009) );
	t.set( "rightarrow;", chr(8594) );
	t.set( "rightarrowtail;", chr(8611) );
	t.set( "rightharpoondown;", chr(8641) );
	t.set( "rightharpoonup;", chr(8640) );
	t.set( "rightleftarrows;", chr(8644) );
	t.set( "rightleftharpoons;", chr(8652) );
	t.set( "rightrightarrows;", chr(8649) );
	t.set( "rightsquigarrow;", chr(8605) );
	t.set( "rightthreetimes;", chr(8908) );
	t.set( "ring;", chr(730) );
	t.set( "risingdotseq;", chr(8787) );
	t.set( "rlarr;", chr(8644) );
	t.set( "rlhar;", chr(8652) );
	t.set( "rlm;", chr(8207) );
	t.set( "rmoust;", chr(9137) );
	t.set( "rmoustache;", chr(9137) );
	t.set( "rnmid;", chr(10990) );
	t.set( "roang;", chr(10221) );
	t.set( "roarr;", chr(8702) );
	t.set( "robrk;", chr(10215) );
	t.set( "ropar;", chr(10630) );
	t.set( "ropf;", chr(120163) );
	t.set( "roplus;", chr(10798) );
	t.set( "rotimes;", chr(10805) );
	t.set( "rpar;", chr(41) );
	t.set( "rpargt;", chr(10644) );
	t.set( "rppolint;", chr(10770) );
	t.set( "rrarr;", chr(8649) );
	t.set( "rsaquo;", chr(8250) );
	t.set( "rscr;", chr(120007) );
	t.set( "rsh;", chr(8625) );
	t.set( "rsqb;", chr(93) );
	t.set( "rsquo;", chr(8217) );
	t.set( "rsquor;", chr(8217) );
	t.set( "rthree;", chr(8908) );
	t.set( "rtimes;", chr(8906) );
	t.set( "rtri;", chr(9657) );
	t.set( "rtrie;", chr(8885) );
	t.set( "rtrif;", chr(9656) );
	t.set( "rtriltri;", chr(10702) );
	t.set( "ruluhar;", chr(10600) );
	t.set( "rx;", chr(8478) );
	t.set( "sacute;", chr(347) );
	t.set( "sbquo;", chr(8218) );
	t.set( "sc;", chr(8827) );
	t.set( "scE;", chr(10932) );
	t.set( "scap;", chr(10936) );
	t.set( "scaron;", chr(353) );
	t.set( "sccue;", chr(8829) );
	t.set( "sce;", chr(10928) );
	t.set( "scedil;", chr(351) );
	t.set( "scirc;", chr(349) );
	t.set( "scnE;", chr(10934) );
	t.set( "scnap;", chr(10938) );
	t.set( "scnsim;", chr(8937) );
	t.set( "scpolint;", chr(10771) );
	t.set( "scsim;", chr(8831) );
	t.set( "scy;", chr(1089) );
	t.set( "sdot;", chr(8901) );
	t.set( "sdotb;", chr(8865) );
	t.set( "sdote;", chr(10854) );
	t.set( "seArr;", chr(8664) );
	t.set( "searhk;", chr(10533) );
	t.set( "searr;", chr(8600) );
	t.set( "searrow;", chr(8600) );
	t.set( "sect", chr(167) );
	t.set( "sect;", chr(167) );
	t.set( "semi;", chr(59) );
	t.set( "seswar;", chr(10537) );
	t.set( "setminus;", chr(8726) );
	t.set( "setmn;", chr(8726) );
	t.set( "sext;", chr(10038) );
	t.set( "sfr;", chr(120112) );
	t.set( "sfrown;", chr(8994) );
	t.set( "sharp;", chr(9839) );
	t.set( "shchcy;", chr(1097) );
	t.set( "shcy;", chr(1096) );
	t.set( "shortmid;", chr(8739) );
	t.set( "shortparallel;", chr(8741) );
	t.set( "shy", chr(173) );
	t.set( "shy;", chr(173) );
	t.set( "sigma;", chr(963) );
	t.set( "sigmaf;", chr(962) );
	t.set( "sigmav;", chr(962) );
	t.set( "sim;", chr(8764) );
	t.set( "simdot;", chr(10858) );
	t.set( "sime;", chr(8771) );
	t.set( "simeq;", chr(8771) );
	t.set( "simg;", chr(10910) );
	t.set( "simgE;", chr(10912) );
	t.set( "siml;", chr(10909) );
	t.set( "simlE;", chr(10911) );
	t.set( "simne;", chr(8774) );
	t.set( "simplus;", chr(10788) );
	t.set( "simrarr;", chr(10610) );
	t.set( "slarr;", chr(8592) );
	t.set( "smallsetminus;", chr(8726) );
	t.set( "smashp;", chr(10803) );
	t.set( "smeparsl;", chr(10724) );
	t.set( "smid;", chr(8739) );
	t.set( "smile;", chr(8995) );
	t.set( "smt;", chr(10922) );
	t.set( "smte;", chr(10924) );
	t.set( "smtes;", chr(10924) _ chr(65024) );
	t.set( "softcy;", chr(1100) );
	t.set( "sol;", chr(47) );
	t.set( "solb;", chr(10692) );
	t.set( "solbar;", chr(9023) );
	t.set( "sopf;", chr(120164) );
	t.set( "spades;", chr(9824) );
	t.set( "spadesuit;", chr(9824) );
	t.set( "spar;", chr(8741) );
	t.set( "sqcap;", chr(8851) );
	t.set( "sqcaps;", chr(8851) _ chr(65024) );
	t.set( "sqcup;", chr(8852) );
	t.set( "sqcups;", chr(8852) _ chr(65024) );
	t.set( "sqsub;", chr(8847) );
	t.set( "sqsube;", chr(8849) );
	t.set( "sqsubset;", chr(8847) );
	t.set( "sqsubseteq;", chr(8849) );
	t.set( "sqsup;", chr(8848) );
	t.set( "sqsupe;", chr(8850) );
	t.set( "sqsupset;", chr(8848) );
	t.set( "sqsupseteq;", chr(8850) );
	t.set( "squ;", chr(9633) );
	t.set( "square;", chr(9633) );
	t.set( "squarf;", chr(9642) );
	t.set( "squf;", chr(9642) );
	t.set( "srarr;", chr(8594) );
	t.set( "sscr;", chr(120008) );
	t.set( "ssetmn;", chr(8726) );
	t.set( "ssmile;", chr(8995) );
	t.set( "sstarf;", chr(8902) );
	t.set( "star;", chr(9734) );
	t.set( "starf;", chr(9733) );
	t.set( "straightepsilon;", chr(1013) );
	t.set( "straightphi;", chr(981) );
	t.set( "strns;", chr(175) );
	t.set( "sub;", chr(8834) );
	t.set( "subE;", chr(10949) );
	t.set( "subdot;", chr(10941) );
	t.set( "sube;", chr(8838) );
	t.set( "subedot;", chr(10947) );
	t.set( "submult;", chr(10945) );
	t.set( "subnE;", chr(10955) );
	t.set( "subne;", chr(8842) );
	t.set( "subplus;", chr(10943) );
	t.set( "subrarr;", chr(10617) );
	t.set( "subset;", chr(8834) );
	t.set( "subseteq;", chr(8838) );
	t.set( "subseteqq;", chr(10949) );
	t.set( "subsetneq;", chr(8842) );
	t.set( "subsetneqq;", chr(10955) );
	t.set( "subsim;", chr(10951) );
	t.set( "subsub;", chr(10965) );
	t.set( "subsup;", chr(10963) );
	t.set( "succ;", chr(8827) );
	t.set( "succapprox;", chr(10936) );
	t.set( "succcurlyeq;", chr(8829) );
	t.set( "succeq;", chr(10928) );
	t.set( "succnapprox;", chr(10938) );
	t.set( "succneqq;", chr(10934) );
	t.set( "succnsim;", chr(8937) );
	t.set( "succsim;", chr(8831) );
	t.set( "sum;", chr(8721) );
	t.set( "sung;", chr(9834) );
	t.set( "sup1", chr(185) );
	t.set( "sup1;", chr(185) );
	t.set( "sup2", chr(178) );
	t.set( "sup2;", chr(178) );
	t.set( "sup3", chr(179) );
	t.set( "sup3;", chr(179) );
	t.set( "sup;", chr(8835) );
	t.set( "supE;", chr(10950) );
	t.set( "supdot;", chr(10942) );
	t.set( "supdsub;", chr(10968) );
	t.set( "supe;", chr(8839) );
	t.set( "supedot;", chr(10948) );
	t.set( "suphsol;", chr(10185) );
	t.set( "suphsub;", chr(10967) );
	t.set( "suplarr;", chr(10619) );
	t.set( "supmult;", chr(10946) );
	t.set( "supnE;", chr(10956) );
	t.set( "supne;", chr(8843) );
	t.set( "supplus;", chr(10944) );
	t.set( "supset;", chr(8835) );
	t.set( "supseteq;", chr(8839) );
	t.set( "supseteqq;", chr(10950) );
	t.set( "supsetneq;", chr(8843) );
	t.set( "supsetneqq;", chr(10956) );
	t.set( "supsim;", chr(10952) );
	t.set( "supsub;", chr(10964) );
	t.set( "supsup;", chr(10966) );
	t.set( "swArr;", chr(8665) );
	t.set( "swarhk;", chr(10534) );
	t.set( "swarr;", chr(8601) );
	t.set( "swarrow;", chr(8601) );
	t.set( "swnwar;", chr(10538) );
	t.set( "szlig", chr(223) );
	t.set( "szlig;", chr(223) );
	t.set( "target;", chr(8982) );
	t.set( "tau;", chr(964) );
	t.set( "tbrk;", chr(9140) );
	t.set( "tcaron;", chr(357) );
	t.set( "tcedil;", chr(355) );
	t.set( "tcy;", chr(1090) );
	t.set( "tdot;", chr(8411) );
	t.set( "telrec;", chr(8981) );
	t.set( "tfr;", chr(120113) );
	t.set( "there4;", chr(8756) );
	t.set( "therefore;", chr(8756) );
	t.set( "theta;", chr(952) );
	t.set( "thetasym;", chr(977) );
	t.set( "thetav;", chr(977) );
	t.set( "thickapprox;", chr(8776) );
	t.set( "thicksim;", chr(8764) );
	t.set( "thinsp;", chr(8201) );
	t.set( "thkap;", chr(8776) );
	t.set( "thksim;", chr(8764) );
	t.set( "thorn", chr(254) );
	t.set( "thorn;", chr(254) );
	t.set( "tilde;", chr(732) );
	t.set( "times", chr(215) );
	t.set( "times;", chr(215) );
	t.set( "timesb;", chr(8864) );
	t.set( "timesbar;", chr(10801) );
	t.set( "timesd;", chr(10800) );
	t.set( "tint;", chr(8749) );
	t.set( "toea;", chr(10536) );
	t.set( "top;", chr(8868) );
	t.set( "topbot;", chr(9014) );
	t.set( "topcir;", chr(10993) );
	t.set( "topf;", chr(120165) );
	t.set( "topfork;", chr(10970) );
	t.set( "tosa;", chr(10537) );
	t.set( "tprime;", chr(8244) );
	t.set( "trade;", chr(8482) );
	t.set( "triangle;", chr(9653) );
	t.set( "triangledown;", chr(9663) );
	t.set( "triangleleft;", chr(9667) );
	t.set( "trianglelefteq;", chr(8884) );
	t.set( "triangleq;", chr(8796) );
	t.set( "triangleright;", chr(9657) );
	t.set( "trianglerighteq;", chr(8885) );
	t.set( "tridot;", chr(9708) );
	t.set( "trie;", chr(8796) );
	t.set( "triminus;", chr(10810) );
	t.set( "triplus;", chr(10809) );
	t.set( "trisb;", chr(10701) );
	t.set( "tritime;", chr(10811) );
	t.set( "trpezium;", chr(9186) );
	t.set( "tscr;", chr(120009) );
	t.set( "tscy;", chr(1094) );
	t.set( "tshcy;", chr(1115) );
	t.set( "tstrok;", chr(359) );
	t.set( "twixt;", chr(8812) );
	t.set( "twoheadleftarrow;", chr(8606) );
	t.set( "twoheadrightarrow;", chr(8608) );
	t.set( "uArr;", chr(8657) );
	t.set( "uHar;", chr(10595) );
	t.set( "uacute", chr(250) );
	t.set( "uacute;", chr(250) );
	t.set( "uarr;", chr(8593) );
	t.set( "ubrcy;", chr(1118) );
	t.set( "ubreve;", chr(365) );
	t.set( "ucirc", chr(251) );
	t.set( "ucirc;", chr(251) );
	t.set( "ucy;", chr(1091) );
	t.set( "udarr;", chr(8645) );
	t.set( "udblac;", chr(369) );
	t.set( "udhar;", chr(10606) );
	t.set( "ufisht;", chr(10622) );
	t.set( "ufr;", chr(120114) );
	t.set( "ugrave", chr(249) );
	t.set( "ugrave;", chr(249) );
	t.set( "uharl;", chr(8639) );
	t.set( "uharr;", chr(8638) );
	t.set( "uhblk;", chr(9600) );
	t.set( "ulcorn;", chr(8988) );
	t.set( "ulcorner;", chr(8988) );
	t.set( "ulcrop;", chr(8975) );
	t.set( "ultri;", chr(9720) );
	t.set( "umacr;", chr(363) );
	t.set( "uml", chr(168) );
	t.set( "uml;", chr(168) );
	t.set( "uogon;", chr(371) );
	t.set( "uopf;", chr(120166) );
	t.set( "uparrow;", chr(8593) );
	t.set( "updownarrow;", chr(8597) );
	t.set( "upharpoonleft;", chr(8639) );
	t.set( "upharpoonright;", chr(8638) );
	t.set( "uplus;", chr(8846) );
	t.set( "upsi;", chr(965) );
	t.set( "upsih;", chr(978) );
	t.set( "upsilon;", chr(965) );
	t.set( "upuparrows;", chr(8648) );
	t.set( "urcorn;", chr(8989) );
	t.set( "urcorner;", chr(8989) );
	t.set( "urcrop;", chr(8974) );
	t.set( "uring;", chr(367) );
	t.set( "urtri;", chr(9721) );
	t.set( "uscr;", chr(120010) );
	t.set( "utdot;", chr(8944) );
	t.set( "utilde;", chr(361) );
	t.set( "utri;", chr(9653) );
	t.set( "utrif;", chr(9652) );
	t.set( "uuarr;", chr(8648) );
	t.set( "uuml", chr(252) );
	t.set( "uuml;", chr(252) );
	t.set( "uwangle;", chr(10663) );
	t.set( "vArr;", chr(8661) );
	t.set( "vBar;", chr(10984) );
	t.set( "vBarv;", chr(10985) );
	t.set( "vDash;", chr(8872) );
	t.set( "vangrt;", chr(10652) );
	t.set( "varepsilon;", chr(1013) );
	t.set( "varkappa;", chr(1008) );
	t.set( "varnothing;", chr(8709) );
	t.set( "varphi;", chr(981) );
	t.set( "varpi;", chr(982) );
	t.set( "varpropto;", chr(8733) );
	t.set( "varr;", chr(8597) );
	t.set( "varrho;", chr(1009) );
	t.set( "varsigma;", chr(962) );
	t.set( "varsubsetneq;", chr(8842) _ chr(65024) );
	t.set( "varsubsetneqq;", chr(10955) _ chr(65024) );
	t.set( "varsupsetneq;", chr(8843) _ chr(65024) );
	t.set( "varsupsetneqq;", chr(10956) _ chr(65024) );
	t.set( "vartheta;", chr(977) );
	t.set( "vartriangleleft;", chr(8882) );
	t.set( "vartriangleright;", chr(8883) );
	t.set( "vcy;", chr(1074) );
	t.set( "vdash;", chr(8866) );
	t.set( "vee;", chr(8744) );
	t.set( "veebar;", chr(8891) );
	t.set( "veeeq;", chr(8794) );
	t.set( "vellip;", chr(8942) );
	t.set( "verbar;", chr(124) );
	t.set( "vert;", chr(124) );
	t.set( "vfr;", chr(120115) );
	t.set( "vltri;", chr(8882) );
	t.set( "vnsub;", chr(8834) _ chr(8402) );
	t.set( "vnsup;", chr(8835) _ chr(8402) );
	t.set( "vopf;", chr(120167) );
	t.set( "vprop;", chr(8733) );
	t.set( "vrtri;", chr(8883) );
	t.set( "vscr;", chr(120011) );
	t.set( "vsubnE;", chr(10955) _ chr(65024) );
	t.set( "vsubne;", chr(8842) _ chr(65024) );
	t.set( "vsupnE;", chr(10956) _ chr(65024) );
	t.set( "vsupne;", chr(8843) _ chr(65024) );
	t.set( "vzigzag;", chr(10650) );
	t.set( "wcirc;", chr(373) );
	t.set( "wedbar;", chr(10847) );
	t.set( "wedge;", chr(8743) );
	t.set( "wedgeq;", chr(8793) );
	t.set( "weierp;", chr(8472) );
	t.set( "wfr;", chr(120116) );
	t.set( "wopf;", chr(120168) );
	t.set( "wp;", chr(8472) );
	t.set( "wr;", chr(8768) );
	t.set( "wreath;", chr(8768) );
	t.set( "wscr;", chr(120012) );
	t.set( "xcap;", chr(8898) );
	t.set( "xcirc;", chr(9711) );
	t.set( "xcup;", chr(8899) );
	t.set( "xdtri;", chr(9661) );
	t.set( "xfr;", chr(120117) );
	t.set( "xhArr;", chr(10234) );
	t.set( "xharr;", chr(10231) );
	t.set( "xi;", chr(958) );
	t.set( "xlArr;", chr(10232) );
	t.set( "xlarr;", chr(10229) );
	t.set( "xmap;", chr(10236) );
	t.set( "xnis;", chr(8955) );
	t.set( "xodot;", chr(10752) );
	t.set( "xopf;", chr(120169) );
	t.set( "xoplus;", chr(10753) );
	t.set( "xotime;", chr(10754) );
	t.set( "xrArr;", chr(10233) );
	t.set( "xrarr;", chr(10230) );
	t.set( "xscr;", chr(120013) );
	t.set( "xsqcup;", chr(10758) );
	t.set( "xuplus;", chr(10756) );
	t.set( "xutri;", chr(9651) );
	t.set( "xvee;", chr(8897) );
	t.set( "xwedge;", chr(8896) );
	t.set( "yacute", chr(253) );
	t.set( "yacute;", chr(253) );
	t.set( "yacy;", chr(1103) );
	t.set( "ycirc;", chr(375) );
	t.set( "ycy;", chr(1099) );
	t.set( "yen", chr(165) );
	t.set( "yen;", chr(165) );
	t.set( "yfr;", chr(120118) );
	t.set( "yicy;", chr(1111) );
	t.set( "yopf;", chr(120170) );
	t.set( "yscr;", chr(120014) );
	t.set( "yucy;", chr(1102) );
	t.set( "yuml", chr(255) );
	t.set( "yuml;", chr(255) );
	t.set( "zacute;", chr(378) );
	t.set( "zcaron;", chr(382) );
	t.set( "zcy;", chr(1079) );
	t.set( "zdot;", chr(380) );
	t.set( "zeetrf;", chr(8488) );
	t.set( "zeta;", chr(950) );
	t.set( "zfr;", chr(120119) );
	t.set( "zhcy;", chr(1078) );
	t.set( "zigrarr;", chr(8669) );
	t.set( "zopf;", chr(120171) );
	t.set( "zscr;", chr(120015) );
	t.set( "zwj;", chr(8205) );
	t.set( "zwnj;", chr(8204) );
	return t;
}

// Longest first, so prefix matching finds the maximal reference.
function _html_tok_named_reference_max_length () {
	return 32;
}

class HTMLNamedCharacterReferences {
	static method table () {
		return _html_tok_named_references();
	}

	static method get ( String name ) {
		let table := _html_tok_named_references();
		return table.exists(name) ? table.get(name) : null;
	}

	static method isComplete () {
		return true;
	}

	static method coverage () {
		return "full";
	}
}

class HTMLParseError {
	let String _code := "";
	let String _message := "";
	let Number _line := 1;
	let Number _column := 1;
	let Number _offset := 0;
	let String _state := "data";

	method code () {
		return _code;
	}

	method message () {
		return _message;
	}

	method line () {
		return _line;
	}

	method column () {
		return _column;
	}

	method offset () {
		return _offset;
	}

	method state () {
		return _state;
	}

	method to_String () {
		return _code _ " at line " _ _line _ ", column "
			_ _column _ " in " _ _state;
	}
}

class HTMLToken {
	let String _type := "";
	let String _data := "";
	let String _tag_name := "";
	let Array _attributes := [];
	let Boolean _self_closing := false;
	let _public_id := null;
	let _system_id := null;
	let Boolean _force_quirks := false;

	method __build__ () {
		_attributes := [] if _attributes ≡ null;
		_tag_name := _html_tok_lc(_tag_name) if _tag_name ≢ null;
		_data := _html_tok_string(_data) if _data ≢ null;
	}

	method type () {
		return _type;
	}

	method data () {
		return _data;
	}

	method tagName () {
		return _tag_name;
	}

	method attributes () {
		return _html_tok_copy_attrs(_attributes);
	}

	method getAttribute ( String name ) {
		let wanted := _html_tok_lc(name);
		for ( let attr in _attributes ) {
			return attr{value} if attr{name} eq wanted;
		}
		return null;
	}

	method hasAttribute ( String name ) {
		let wanted := _html_tok_lc(name);
		for ( let attr in _attributes ) {
			return true if attr{name} eq wanted;
		}
		return false;
	}

	method selfClosing () {
		return _self_closing;
	}

	method publicId () {
		return _public_id;
	}

	method systemId () {
		return _system_id;
	}

	method forceQuirks () {
		return _force_quirks;
	}

	method _add_attribute ( String name, String value ) {
		_attributes.push( {
			name: _html_tok_lc(name),
			value: _html_tok_string(value),
		} );
		return self;
	}

	method _set_self_closing ( Boolean value ) {
		_self_closing := value;
		return self;
	}

	method toDebugString () {
		if ( _type eq "Character" ) {
			return "Character(" _ _data _ ")";
		}
		if ( _type eq "Comment" ) {
			return "Comment(" _ _data _ ")";
		}
		if ( _type eq "DOCTYPE" ) {
			return "DOCTYPE(" _ _tag_name _ ")";
		}
		if ( _type eq "StartTag" or _type eq "EndTag" ) {
			let attrs := [];
			for ( let attr in _attributes ) {
				attrs.push( attr{name} _ "=" _ attr{value} );
			}
			return _type _ "(" _ _tag_name _ (
				attrs.length() ? " " _ join( " ", attrs ) : ""
			) _ (_self_closing ? " /" : "") _ ")";
		}
		return _type;
	}
}

class HTMLInputStream {
	let String _input := "";
	let String _source := "";
	let Number _offset := 0;
	let Number _line := 1;
	let Number _column := 1;
	let Number _last_offset := 0;
	let Number _last_line := 1;
	let Number _last_column := 1;
	let String _last_char := "";
	let Boolean _reconsume := false;

	method __build__ () {
		self.reset(_input);
	}

	method _normalize ( String input ) {
		let out := replace( input, "\r\n", "\n", "g" );
		out := replace( out, "\r", "\n", "g" );
		return out;
	}

	method reset ( String input ) {
		_input := input;
		_source := self._normalize(_html_tok_string(input));
		_offset := 0;
		_line := 1;
		_column := 1;
		_last_offset := 0;
		_last_line := 1;
		_last_column := 1;
		_last_char := "";
		_reconsume := false;
		return self;
	}

	method source () {
		return _source;
	}

	method offset () {
		return _offset;
	}

	method line () {
		return _line;
	}

	method column () {
		return _column;
	}

	method lastOffset () {
		return _last_offset;
	}

	method lastLine () {
		return _last_line;
	}

	method lastColumn () {
		return _last_column;
	}

	method eof () {
		return _offset >= length _source and not _reconsume;
	}

	method consume () {
		if ( _reconsume ) {
			_reconsume := false;
			return _last_char;
		}
		return null if _offset >= length _source;

		let ch := substr( _source, _offset, 1 );
		_last_offset := _offset;
		_last_line := _line;
		_last_column := _column;
		_last_char := ch;
		_offset++;
		if ( ch eq "\n" ) {
			_line++;
			_column := 1;
		}
		else {
			_column++;
		}
		return ch;
	}

	method reconsume () {
		_reconsume := true if _last_char ne "";
		return self;
	}

	method peek ( Number n := 1 ) {
		return "" if _offset >= length _source;
		return substr( _source, _offset, n );
	}

	method match ( String text, Boolean case_insensitive := false ) {
		let got := self.peek(length text);
		return case_insensitive
			? lc(got) eq lc(text)
			: got eq text;
	}
}

class HTMLTokenizer {
	let String _input := "";
	let String _state := "data";
	let _last_start_tag_name := null;
	let _stream := null;
	let Array _tokens := [];
	let Array _errors := [];
	let Number _read_index := 0;
	let Boolean _tokenized := false;
	let Boolean _eof_emitted := false;
	let Boolean _allow_cdata := false;

	method __build__ () {
		self.reset( _input, _state );
		_last_start_tag_name := _html_tok_lc(_last_start_tag_name)
			unless _last_start_tag_name ≡ null;
	}

	method reset ( String input, String state := "data" ) {
		_input := _html_tok_string(input);
		_state := _html_tok_state_name(state);
		_stream := new HTMLInputStream( _input: _input );
		_tokens := [];
		_errors := [];
		_read_index := 0;
		_tokenized := false;
		_eof_emitted := false;
		_last_start_tag_name := null;
		_allow_cdata := false;
		return self;
	}

	method state () {
		return _state;
	}

	method setState ( String state ) {
		_state := _html_tok_state_name(state);
		return self;
	}

	method setLastStartTagName ( name ) {
		_last_start_tag_name := name ≡ null ? null : _html_tok_lc(name);
		return self;
	}

	method lastStartTagName () {
		return _last_start_tag_name;
	}

	method setAllowCDATA ( Boolean allow ) {
		_allow_cdata := allow ? true : false;
		return self;
	}

	method allowCDATA () {
		return _allow_cdata;
	}

	method errors () {
		let out := [];
		for ( let error in _errors ) {
			out.push(error);
		}
		return out;
	}

	method tokenize () {
		self._run() unless _tokenized;
		let out := [];
		for ( let token in _tokens ) {
			out.push(token);
		}
		return out;
	}

	method nextToken () {
		while ( _read_index >= _tokens.length() and not _eof_emitted ) {
			self._run_one_cycle();
		}
		return null if _read_index >= _tokens.length();
		let token := _tokens[_read_index];
		_read_index++;
		return token;
	}

	method _run () {
		while ( not _eof_emitted ) {
			self._run_one_cycle();
		}
		_tokenized := true;
		return self;
	}

	method _run_one_cycle () {
		return self if _eof_emitted;
		if ( not _stream.eof() ) {
			if ( _state eq "data" ) {
				self._tokenize_data();
			}
			else if ( _state eq "rcdata" ) {
				self._tokenize_text_mode( "rcdata", true );
			}
			else if ( _state eq "rawtext" ) {
				self._tokenize_text_mode( "rawtext", false );
			}
			else if ( _state eq "script_data" ) {
				self._tokenize_script_data();
			}
			else if ( _state eq "plaintext" ) {
				self._tokenize_plaintext();
			}
			else {
				self._parse_error(
					"unsupported-tokenizer-state",
					"Unsupported tokenizer state " _ _state,
				);
				self.setState("data");
			}
			return self;
		}
		if ( _state ne "data" and _state ne "plaintext" ) {
			self._parse_error(
				"eof-in-" _ _state,
				"End of file in " _ _state _ " state",
			);
		}
		self._emit(new HTMLToken( _type: "EOF" ));
		_eof_emitted := true;
		return self;
	}

	method _emit ( HTMLToken token ) {
		_tokens.push(token);
		return token;
	}

	method _emit_character ( String data ) {
		return null if data eq "";
		return self._emit(new HTMLToken( _type: "Character", _data: data ));
	}

	method _parse_error ( String code, String message ) {
		_errors.push(
			new HTMLParseError(
				_code: code,
				_message: message,
				_line: _stream.line(),
				_column: _stream.column(),
				_offset: _stream.offset(),
				_state: _state,
			),
		);
		return self;
	}

	method _parse_error_at_last ( String code, String message ) {
		_errors.push(
			new HTMLParseError(
				_code: code,
				_message: message,
				_line: _stream.lastLine(),
				_column: _stream.lastColumn(),
				_offset: _stream.lastOffset(),
				_state: _state,
			),
		);
		return self;
	}

	method _consume_string ( String text ) {
		let i := 0;
		while ( i < length text ) {
			_stream.consume();
			i++;
		}
		return text;
	}

	method _starts_with ( String text, Boolean ci := false ) {
		return _stream.match( text, ci );
	}

	method _skip_spaces () {
		while ( not _stream.eof() and _html_tok_is_space(_stream.peek()) ) {
			_stream.consume();
		}
		return self;
	}

	method _tokenize_data () {
		let text := "";
		while ( not _stream.eof() ) {
			if ( self._starts_with("<") or self._starts_with("&") ) {
				last;
			}
			let ch := _stream.consume();
			if ( ch eq chr(0) ) {
				// Data state: parse error, but the U+0000 itself is
				// emitted; the tree builder decides what to do with it.
				self._parse_error_at_last(
					"unexpected-null-character",
					"Unexpected null character",
				);
				text _= ch;
			}
			else {
				text _= ch;
			}
		}
		if ( text ne "" ) {
			return self._emit_character(text);
		}
		if ( _stream.eof() ) {
			return null;
		}
		if ( self._starts_with("&") ) {
			_stream.consume();
			return self._emit_character(self._consume_character_reference(false));
		}
		return self._consume_markup();
	}

	method _tokenize_plaintext () {
		let text := "";
		while ( not _stream.eof() ) {
			let ch := _stream.consume();
			if ( ch eq chr(0) ) {
				self._parse_error_at_last(
					"unexpected-null-character",
					"Unexpected null character",
				);
				text _= chr(65533);
			}
			else {
				text _= ch;
			}
		}
		self._emit_character(text);
		return self;
	}

	method _appropriate_end_tag_name () {
		return _last_start_tag_name ≢ null
			? _last_start_tag_name
			: (
				_state eq "rcdata" ? "textarea"
				: ( _state eq "rawtext" ? "style" : "script" )
			);
	}

	method _tokenize_text_mode ( String mode, Boolean expand_refs ) {
		let text := "";
		let tag := self._appropriate_end_tag_name();
		while ( not _stream.eof() ) {
			if (
				tag ne "" and
				self._starts_with("</" _ tag, true) and
				self._text_end_tag_follows(tag)
			) {
				last;
			}
			if ( expand_refs and self._starts_with("&") ) {
				_stream.consume();
				text _= self._consume_character_reference(false);
			}
			else {
				let ch := _stream.consume();
				if ( ch eq chr(0) ) {
					self._parse_error_at_last(
						"unexpected-null-character",
						"Unexpected null character",
					);
					text _= chr(65533);
				}
				else {
					text _= ch;
				}
			}
		}
		self._emit_character(text);
		if ( not _stream.eof() ) {
			self._consume_markup();
		}
		return self;
	}

	method _tokenize_script_data () {
		let state := "script_data";
		let text := "";
		let tag_name := "";
		let tag_text := "";
		let temp_buffer := "";
		while ( true ) {
			if ( _stream.eof() ) {
				if ( state eq "script_data_less_than_sign" ) {
					text _= "<";
				}
				else if ( state eq "script_data_end_tag_open" ) {
					text _= "</";
				}
				else if ( state eq "script_data_end_tag_name" ) {
					text _= "</" _ tag_text;
				}
				else if ( state eq "script_data_escaped_less_than_sign" ) {
					text _= "<";
				}
				else if ( state eq "script_data_escaped_end_tag_open" ) {
					text _= "</";
				}
				else if ( state eq "script_data_escaped_end_tag_name" ) {
					text _= "</" _ tag_text;
				}
				else if ( state eq "script_data_double_escaped_less_than_sign" ) {
					// The "<" was already appended on entry to this state.
				}
				else if ( state eq "script_data_double_escaped" ) {
					self._parse_error(
						"eof-in-script-html-comment-like-text",
						"EOF in script html comment-like text",
					);
				}
				else if ( state eq "script_data_escaped" ) {
					self._parse_error(
						"eof-in-script-html-comment-like-text",
						"EOF in script html comment-like text",
					);
				}
				else if ( state eq "script_data_escaped_dash" ) {
					self._parse_error(
						"eof-in-script-html-comment-like-text",
						"EOF in script html comment-like text",
					);
				}
				else if ( state eq "script_data_escaped_dash_dash" ) {
					self._parse_error(
						"eof-in-script-html-comment-like-text",
						"EOF in script html comment-like text",
					);
				}
				else if ( state eq "script_data_double_escaped" ) {
					self._parse_error(
						"eof-in-script-html-comment-like-text",
						"EOF in script html comment-like text",
					);
				}
				else if ( state eq "script_data_double_escaped_dash" ) {
					self._parse_error(
						"eof-in-script-html-comment-like-text",
						"EOF in script html comment-like text",
					);
				}
				else if ( state eq "script_data_double_escaped_dash_dash" ) {
					self._parse_error(
						"eof-in-script-html-comment-like-text",
						"EOF in script html comment-like text",
					);
				}
				else if ( state eq "script_data_double_escape_start" ) {
					self._parse_error(
						"eof-in-script-html-comment-like-text",
						"EOF in script html comment-like text",
					);
				}
				else if ( state eq "script_data_double_escape_end" ) {
					self._parse_error(
						"eof-in-script-html-comment-like-text",
						"EOF in script html comment-like text",
					);
			}
			self._emit_character(text) if text ne "";
			return self;
		}
			let ch := _stream.consume();
			if ( state eq "script_data" ) {
				if ( ch eq "<" ) {
					state := "script_data_less_than_sign";
					next;
				}
				if ( ch eq chr(0) ) {
					self._parse_error(
						"unexpected-null-character",
						"Unexpected null character",
					);
					text _= chr(65533);
					next;
				}
				text _= ch;
				next;
			}
			if ( state eq "script_data_less_than_sign" ) {
				if ( ch eq "/" ) {
					tag_name := "";
					state := "script_data_end_tag_open";
					next;
				}
				if ( ch eq "!" ) {
					text _= "<!";
					state := "script_data_escape_start";
					next;
				}
				text _= "<";
				_stream.reconsume();
				state := "script_data";
				next;
			}
			if ( state eq "script_data_end_tag_open" ) {
				if ( _html_tok_is_alpha(ch) ) {
					tag_name := _html_tok_ascii_lower_char(ch);
					tag_text := ch;
					state := "script_data_end_tag_name";
					next;
				}
				text _= "</";
				_stream.reconsume();
				state := "script_data";
				next;
			}
			if ( state eq "script_data_end_tag_name" ) {
				if ( _html_tok_is_alpha(ch) or _html_tok_is_digit(ch) ) {
					tag_name _= _html_tok_ascii_lower_char(ch);
					tag_text _= ch;
					next;
				}
				let target := self._appropriate_end_tag_name();
				if (
					tag_name eq target and
					( ch eq ">" or ch eq "/" or ch eq " " or
						ch eq "\n" or ch eq "\t" or ch eq chr(12) )
				) {
					// Skip anything up to the closing ">" (attributes on
					// an end tag are parse errors but the tag still ends
					// there), emit, and hand control back so the tree
					// builder can switch the tokenizer state.
					let extra := "";
					let closed := ch eq ">";
					while ( not closed and not _stream.eof() ) {
						let trailing := _stream.consume();
						closed := trailing eq ">";
						extra _= trailing unless closed;
					}
					if ( not closed ) {
						// EOF inside the end tag: eof-in-tag, the tag
						// characters are dropped.
						self._emit_character(text) if text ne "";
						return self;
					}
					self._emit_character(text) if text ne "";
					text := "";
					self._emit(new HTMLToken(
						_type: "EndTag",
						_tag_name: tag_name,
						_attributes: [],
					));
					return self;
				}
				text _= "</" _ tag_text;
				_stream.reconsume();
				tag_name := "";
				tag_text := "";
				state := "script_data";
				next;
			}
			if ( state eq "script_data_escape_start" ) {
				if ( ch eq "-" ) {
					text _= "-";
					state := "script_data_escape_start_dash";
					next;
				}
				_stream.reconsume();
				state := "script_data";
				next;
			}
			if ( state eq "script_data_escape_start_dash" ) {
				if ( ch eq "-" ) {
					text _= "-";
					state := "script_data_escaped_dash_dash";
					next;
				}
				_stream.reconsume();
				state := "script_data";
				next;
			}
			if ( state eq "script_data_escaped" ) {
				if ( ch eq "-" ) {
					text _= "-";
					state := "script_data_escaped_dash";
					next;
				}
				if ( ch eq "<" ) {
					state := "script_data_escaped_less_than_sign";
					next;
				}
				if ( ch eq chr(0) ) {
					self._parse_error(
						"unexpected-null-character",
						"Unexpected null character",
					);
					text _= chr(65533);
					state := "script_data_escaped";
					next;
				}
				text _= ch;
				state := "script_data_escaped";
				next;
			}
			if ( state eq "script_data_escaped_dash" ) {
				if ( ch eq "-" ) {
					text _= "-";
					state := "script_data_escaped_dash_dash";
					next;
				}
				if ( ch eq "<" ) {
					state := "script_data_escaped_less_than_sign";
					next;
				}
				if ( ch eq chr(0) ) {
					self._parse_error(
						"unexpected-null-character",
						"Unexpected null character",
					);
					text _= chr(65533);
					state := "script_data_escaped";
					next;
				}
				text _= ch;
				state := "script_data_escaped";
				next;
			}
			if ( state eq "script_data_escaped_dash_dash" ) {
				if ( ch eq "-" ) {
					text _= "-";
				}
				else if ( ch eq "<" ) {
					state := "script_data_escaped_less_than_sign";
					next;
				}
				else if ( ch eq ">" ) {
					text _= ">";
					state := "script_data";
					next;
				}
				else if ( ch eq chr(0) ) {
					self._parse_error(
						"unexpected-null-character",
						"Unexpected null character",
					);
					text _= chr(65533);
					state := "script_data_escaped";
					next;
				}
				else {
					text _= ch;
					state := "script_data_escaped";
				}
				next;
			}
			if ( state eq "script_data_escaped_less_than_sign" ) {
				if ( ch eq "/" ) {
					tag_name := "";
					state := "script_data_escaped_end_tag_open";
					next;
				}
				if ( _html_tok_is_alpha(ch) ) {
					temp_buffer := "";
					tag_name := "";
					text _= "<";
					_stream.reconsume();
					state := "script_data_double_escape_start";
					next;
				}
				text _= "<";
				_stream.reconsume();
				state := "script_data_escaped";
				next;
			}
			if ( state eq "script_data_escaped_end_tag_open" ) {
				if ( _html_tok_is_alpha(ch) ) {
					tag_name := _html_tok_ascii_lower_char(ch);
					tag_text := ch;
					state := "script_data_escaped_end_tag_name";
					next;
				}
				text _= "</";
				_stream.reconsume();
				state := "script_data_escaped";
				next;
			}
			if ( state eq "script_data_escaped_end_tag_name" ) {
				if ( _html_tok_is_alpha(ch) or _html_tok_is_digit(ch) ) {
					tag_name _= _html_tok_ascii_lower_char(ch);
					tag_text _= ch;
					next;
				}
				let target := self._appropriate_end_tag_name();
				if (
					tag_name eq target and
					( ch eq ">" or ch eq "/" or ch eq " " or
						ch eq "\n" or ch eq "\t" or ch eq chr(12) )
				) {
					// Skip anything up to the closing ">" (attributes on
					// an end tag are parse errors but the tag still ends
					// there), emit, and hand control back so the tree
					// builder can switch the tokenizer state.
					let extra := "";
					let closed := ch eq ">";
					while ( not closed and not _stream.eof() ) {
						let trailing := _stream.consume();
						closed := trailing eq ">";
						extra _= trailing unless closed;
					}
					if ( not closed ) {
						// EOF inside the end tag: eof-in-tag, the tag
						// characters are dropped.
						self._emit_character(text) if text ne "";
						return self;
					}
					self._emit_character(text) if text ne "";
					text := "";
					self._emit(new HTMLToken(
						_type: "EndTag",
						_tag_name: tag_name,
						_attributes: [],
					));
					return self;
				}
				text _= "</" _ tag_text;
				_stream.reconsume();
				tag_name := "";
				tag_text := "";
				state := "script_data_escaped";
				next;
			}
			if ( state eq "script_data_double_escape_start" ) {
				if (
					ch eq "\n" or ch eq "\t" or ch eq chr(12) or
					ch eq " " or ch eq "/" or ch eq ">"
				) {
					let target := temp_buffer;
					text _= ch;
					state := (
						target eq "script"
							? "script_data_double_escaped"
							: "script_data_escaped"
					);
					temp_buffer := "";
					next;
				}
				if ( _html_tok_is_alpha(ch) ) {
					temp_buffer _= _html_tok_ascii_lower_char(ch);
					text _= ch;
					next;
				}
				_stream.reconsume();
				state := "script_data_escaped";
				temp_buffer := "";
				next;
			}
			if ( state eq "script_data_double_escaped" ) {
				if ( ch eq "-" ) {
					text _= "-";
					state := "script_data_double_escaped_dash";
					next;
				}
				if ( ch eq "<" ) {
					text _= "<";
					state := "script_data_double_escaped_less_than_sign";
					next;
				}
				if ( ch eq chr(0) ) {
					self._parse_error(
						"unexpected-null-character",
						"Unexpected null character",
					);
					text _= chr(65533);
					next;
				}
				text _= ch;
				state := "script_data_double_escaped";
				next;
			}
			if ( state eq "script_data_double_escaped_dash" ) {
				if ( ch eq "-" ) {
					text _= "-";
					state := "script_data_double_escaped_dash_dash";
					next;
				}
				if ( ch eq "<" ) {
					text _= "<";
					state := "script_data_double_escaped_less_than_sign";
					next;
				}
				if ( ch eq chr(0) ) {
					self._parse_error(
						"unexpected-null-character",
						"Unexpected null character",
					);
					text _= chr(65533);
					state := "script_data_double_escaped";
					next;
				}
				text _= ch;
				state := "script_data_double_escaped";
				next;
			}
			if ( state eq "script_data_double_escaped_dash_dash" ) {
				if ( ch eq "-" ) {
					text _= "-";
				}
				else if ( ch eq "<" ) {
					text _= "<";
					state := "script_data_double_escaped_less_than_sign";
					next;
				}
				else if ( ch eq ">" ) {
					text _= ">";
					state := "script_data";
					next;
				}
				else if ( ch eq chr(0) ) {
					self._parse_error(
						"unexpected-null-character",
						"Unexpected null character",
					);
					text _= chr(65533);
					state := "script_data_double_escaped";
					next;
				}
				else {
					text _= ch;
					state := "script_data_double_escaped";
				}
				next;
			}
			if ( state eq "script_data_double_escaped_less_than_sign" ) {
				if ( ch eq "/" ) {
					text _= "/";
					temp_buffer := "";
					state := "script_data_double_escape_end";
					next;
				}
				_stream.reconsume();
				state := "script_data_double_escaped";
				next;
			}
			if ( state eq "script_data_double_escape_end" ) {
				if (
					ch eq "\n" or ch eq "\t" or ch eq chr(12) or
					ch eq " " or ch eq "/" or ch eq ">"
				) {
					let target := temp_buffer;
					text _= ch;
					state := (
						target eq "script"
							? "script_data_escaped"
							: "script_data_double_escaped"
					);
					temp_buffer := "";
					next;
				}
				if ( _html_tok_is_alpha(ch) ) {
					temp_buffer _= _html_tok_ascii_lower_char(ch);
					text _= ch;
					next;
				}
				_stream.reconsume();
				state := "script_data_double_escaped";
				temp_buffer := "";
				next;
			}
			state := "script_data";
		}
		if ( text ne "" ) {
			self._emit_character(text);
		}
		return self;
	}

	method _text_end_tag_follows ( String tag ) {
		let probe := _stream.peek(2 + length tag + 1);
		let after := substr( probe, 2 + length tag, 1 );
		return after eq "" or after eq ">" or _html_tok_is_space(after)
			or after eq "/";
	}

	method _consume_markup () {
		_stream.consume(); // <
		if ( _stream.eof() ) {
			self._parse_error_at_last(
				"eof-before-tag-name",
				"EOF before tag name",
			);
			return self._emit_character("<");
		}
		if ( self._starts_with("!--") ) {
			self._consume_string("!--");
			return self._parse_comment();
		}
		if ( self._starts_with("![CDATA[") and _allow_cdata ) {
			self._consume_string("![CDATA[");
			return self._parse_cdata_section();
		}
		if ( self._starts_with("!DOCTYPE", true) ) {
			self._consume_string(substr( _stream.peek(8), 0, 8 ));
			return self._parse_doctype();
		}
		if ( self._starts_with("!") ) {
			_stream.consume();
			self._parse_error(
				"incorrectly-opened-comment",
				"Markup declaration is not comment or doctype",
			);
			return self._parse_bogus_comment();
		}
		if ( self._starts_with("?") ) {
			// The "?" is reconsumed in the bogus comment state, so it
			// becomes part of the comment data.
			self._parse_error(
				"unexpected-question-mark-instead-of-tag-name",
				"Unexpected question mark instead of tag name",
			);
			return self._parse_bogus_comment();
		}
		if ( self._starts_with("/") ) {
			_stream.consume();
			return self._parse_end_tag();
		}
		if ( _html_tok_is_alpha(_stream.peek()) ) {
			return self._parse_start_tag();
		}
		self._parse_error(
			"invalid-first-character-of-tag-name",
			"Invalid first character of tag name",
		);
		return self._emit_character("<");
	}

	method _parse_cdata_section () {
		let data := "";
		while ( not _stream.eof() ) {
			if ( self._starts_with("]]>") ) {
				self._consume_string("]]>");
				return self._emit_character(data);
			}
			data _= _stream.consume();
		}
		self._parse_error(
			"eof-in-cdata",
			"EOF in CDATA section",
		);
		return self._emit_character(data);
	}

	method _parse_tag_name () {
		let name := "";
		while ( not _stream.eof() ) {
			let ch := _stream.peek();
			last if _html_tok_is_space(ch) or ch eq "/" or ch eq ">";
			if ( ch eq chr(0) ) {
				self._parse_error(
					"unexpected-null-character",
					"Unexpected null in tag name",
				);
				name _= chr(65533);
				_stream.consume();
			}
			else {
				name _= _html_tok_ascii_lower_char(_stream.consume());
			}
		}
		return name;
	}

	method _parse_start_tag () {
		let name := self._parse_tag_name();
		let token := new HTMLToken(
			_type: "StartTag",
			_tag_name: name,
			_attributes: [],
		);
		_last_start_tag_name := name;
		self._parse_attributes( token, false );
		return self._emit(token);
	}

	method _parse_end_tag () {
		if ( _stream.eof() ) {
			self._parse_error(
				"eof-before-tag-name",
				"EOF before end tag name",
			);
			return self._emit_character("</");
		}
		if ( not _html_tok_is_alpha(_stream.peek()) ) {
			self._parse_error(
				"invalid-first-character-of-tag-name",
				"Invalid first character of end tag name",
			);
			return self._parse_bogus_comment();
		}
		let name := self._parse_tag_name();
		let token := new HTMLToken(
			_type: "EndTag",
			_tag_name: name,
			_attributes: [],
		);
		self._parse_attributes( token, true );
		return self._emit(token);
	}

	method _parse_attributes ( HTMLToken token, Boolean end_tag ) {
		while ( not _stream.eof() ) {
			self._skip_spaces();
			last if _stream.eof();
			let ch := _stream.peek();
			if ( ch eq ">" ) {
				_stream.consume();
				return self;
			}
			if ( ch eq "/" ) {
				_stream.consume();
				if ( _stream.peek() eq ">" ) {
					_stream.consume();
					if ( end_tag ) {
						self._parse_error(
							"end-tag-with-trailing-solidus",
							"End tag has trailing solidus",
						);
					}
					else {
						token._set_self_closing(true);
					}
					return self;
				}
				self._parse_error(
					"unexpected-solidus-in-tag",
					"Unexpected solidus in tag",
				);
			}
			let name := self._parse_attribute_name();
			last if name eq "";
			let value := "";
			self._skip_spaces();
			if ( _stream.peek() eq "=" ) {
				_stream.consume();
				self._skip_spaces();
				value := self._parse_attribute_value();
			}
			if ( token.hasAttribute(name) ) {
				self._parse_error(
					"duplicate-attribute",
					"Duplicate attribute " _ name,
				);
			}
			else if ( end_tag ) {
				self._parse_error(
					"end-tag-with-attributes",
					"End tag has attributes",
				);
				token._add_attribute( name, value );
			}
			else {
				token._add_attribute( name, value );
			}
		}
		self._parse_error(
			"eof-in-tag",
			"EOF in tag",
		);
		return self;
	}

	method _parse_attribute_name () {
		let name := "";
		while ( not _stream.eof() ) {
			let ch := _stream.peek();
			last if _html_tok_is_space(ch) or ch eq "/" or ch eq ">"
				or ch eq "=";
			name _= _html_tok_ascii_lower_char(_stream.consume());
		}
		return name;
	}

	method _parse_attribute_value () {
		return "" if _stream.eof();
		let quote := _stream.peek();
		if ( quote eq "\"" or quote eq "'" ) {
			_stream.consume();
			let value := "";
			while ( not _stream.eof() ) {
				let ch := _stream.consume();
				return value if ch eq quote;
				if ( ch eq "&" ) {
					value _= self._consume_character_reference(true);
				}
				else if ( ch eq chr(0) ) {
					self._parse_error_at_last(
						"unexpected-null-character",
						"Unexpected null character",
					);
					value _= chr(65533);
				}
				else {
					value _= ch;
				}
			}
			self._parse_error(
				"eof-in-attribute-value",
				"EOF in quoted attribute value",
			);
			return value;
		}
		let value := "";
		while ( not _stream.eof() ) {
			let ch := _stream.peek();
			last if _html_tok_is_space(ch) or ch eq ">";
			// "/" is an ordinary character in an unquoted attribute
			// value; <foo bar=qux/> has the value "qux/".
			if ( ch eq "&" ) {
				_stream.consume();
				value _= self._consume_character_reference(true);
			}
			else {
				value _= _stream.consume();
			}
		}
		return value;
	}

	method _parse_comment () {
		let data := "";
		// Comment start state: ">" or "->" closes an (empty) comment
		// abruptly.
		if ( self._starts_with(">") ) {
			self._parse_error(
				"abrupt-closing-of-empty-comment",
				"Abrupt comment close",
			);
			_stream.consume();
			return self._emit(new HTMLToken( _type: "Comment", _data: "" ));
		}
		if ( self._starts_with("->") ) {
			self._parse_error(
				"abrupt-closing-of-empty-comment",
				"Abrupt comment close",
			);
			self._consume_string("->");
			return self._emit(new HTMLToken( _type: "Comment", _data: "" ));
		}
		while ( not _stream.eof() ) {
			if ( self._starts_with("-->") ) {
				self._consume_string("-->");
				return self._emit(new HTMLToken(
					_type: "Comment",
					_data: data,
				));
			}
			if ( self._starts_with("--!>") ) {
				self._parse_error(
					"abrupt-closing-of-empty-comment",
					"Abrupt comment close",
				);
				self._consume_string("--!>");
				return self._emit(new HTMLToken(
					_type: "Comment",
					_data: data,
				));
			}
			if ( self._starts_with("<!--") ) {
				self._parse_error(
					"nested-comment",
					"Nested comment opening",
				);
			}
			data _= _stream.consume();
		}
		self._parse_error(
			"eof-in-comment",
			"EOF in comment",
		);
		return self._emit(new HTMLToken(
			_type: "Comment",
			_data: data,
		));
	}

	method _parse_bogus_comment () {
		let data := "";
		while ( not _stream.eof() ) {
			let ch := _stream.consume();
			last if ch eq ">";
			if ( ch eq chr(0) ) {
				self._parse_error_at_last(
					"unexpected-null-character",
					"Unexpected null character",
				);
				data _= chr(65533);
				next;
			}
			data _= ch;
		}
		return self._emit(new HTMLToken(
			_type: "Comment",
			_data: data,
		));
	}

	method _parse_doctype () {
		self._skip_spaces();
		if ( _stream.eof() or _stream.peek() eq ">" ) {
			self._parse_error(
				"missing-doctype-name",
				"Missing doctype name",
			);
			_stream.consume() if _stream.peek() eq ">";
			return self._emit(new HTMLToken(
				_type: "DOCTYPE",
				_tag_name: "",
				_force_quirks: true,
			));
		}
		let name := "";
		while ( not _stream.eof() ) {
			let ch := _stream.peek();
			last if _html_tok_is_space(ch) or ch eq ">";
			name _= _html_tok_ascii_lower_char(_stream.consume());
		}
		self._skip_spaces();
		let public_id := null;
		let system_id := null;
		let force := false;
		if ( self._starts_with("PUBLIC", true) ) {
			self._consume_string(substr( _stream.peek(6), 0, 6 ));
			self._skip_spaces();
			public_id := self._parse_doctype_quoted();
			if ( public_id ≡ null ) {
				self._parse_error(
					"missing-doctype-public-identifier",
					"Missing doctype public identifier",
				);
				force := true;
			}
			self._skip_spaces();
			system_id := self._parse_doctype_quoted();
		}
		else if ( self._starts_with("SYSTEM", true) ) {
			self._consume_string(substr( _stream.peek(6), 0, 6 ));
			self._skip_spaces();
			system_id := self._parse_doctype_quoted();
			if ( system_id ≡ null ) {
				self._parse_error(
					"missing-doctype-system-identifier",
					"Missing doctype system identifier",
				);
				force := true;
			}
		}
		else if ( _stream.peek() ne ">" and not _stream.eof() ) {
			self._parse_error(
				"invalid-character-sequence-after-doctype-name",
				"Invalid text after doctype name",
			);
			force := true;
		}
		while ( not _stream.eof() and _stream.peek() ne ">" ) {
			_stream.consume();
		}
		if ( _stream.peek() eq ">" ) {
			_stream.consume();
		}
		else {
			self._parse_error(
				"eof-in-doctype",
				"EOF in doctype",
			);
			force := true;
		}
		return self._emit(new HTMLToken(
			_type: "DOCTYPE",
			_tag_name: name,
			_public_id: public_id,
			_system_id: system_id,
			_force_quirks: force,
		));
	}

	method _parse_doctype_quoted () {
		return null if _stream.eof();
		let quote := _stream.peek();
		return null unless quote eq "\"" or quote eq "'";
		_stream.consume();
		let value := "";
		while ( not _stream.eof() ) {
			let ch := _stream.consume();
			return value if ch eq quote;
			value _= ch;
		}
		self._parse_error(
			"eof-in-doctype",
			"EOF in doctype identifier",
		);
		return value;
	}

	method _consume_character_reference ( Boolean in_attribute ) {
		if ( _stream.eof() ) {
			return "&";
		}
		if ( _stream.peek() eq "#" ) {
			_stream.consume();
			return self._consume_numeric_character_reference();
		}
		return self._consume_named_character_reference(in_attribute);
	}

	method _consume_named_character_reference ( Boolean in_attribute ) {
		let table := _html_tok_named_references();
		let window := _stream.peek(_html_tok_named_reference_max_length());
		let len := length window;
		while ( len > 0 ) {
			let key := substr( window, 0, len );
			if ( table.exists(key) ) {
				let has_semicolon := substr( key, length key - 1, 1 ) eq ";";
				let after := substr( window, len, 1 );
				if (
					in_attribute and
					not has_semicolon and
					(_html_tok_is_alnum(after) or after eq "=")
				) {
					// Historical attribute exception: &not=... stays raw.
					len--;
					next;
				}
				self._consume_string(key);
				if ( not has_semicolon ) {
					self._parse_error(
						"missing-semicolon-after-character-reference",
						"Missing semicolon after named character reference",
					);
				}
				return table.get(key);
			}
			len--;
		}
		if ( _html_tok_is_alnum(_stream.peek()) ) {
			self._parse_error(
				"unknown-named-character-reference",
				"Unknown named character reference",
			);
		}
		return "&";
	}

	method _consume_numeric_character_reference () {
		let base := 10;
		let marker := "";
		if ( _stream.peek() eq "x" or _stream.peek() eq "X" ) {
			base := 16;
			marker := _stream.consume();
		}
		let digits := "";
		while ( not _stream.eof() ) {
			let ch := _stream.peek();
			last unless base == 16
				? _html_tok_is_hex_digit(ch)
				: _html_tok_is_digit(ch);
			digits _= _stream.consume();
		}
		if ( digits eq "" ) {
			self._parse_error(
				"absence-of-digits-in-numeric-character-reference",
				"No digits in numeric character reference",
			);
			return "&#" _ marker;
		}
		if ( _stream.peek() eq ";" ) {
			_stream.consume();
		}
		else {
			self._parse_error(
				"missing-semicolon-after-character-reference",
				"Missing semicolon after numeric character reference",
			);
		}
		let code := _html_tok_parse_int( digits, base );
		if ( code == 0 ) {
			self._parse_error(
				"null-character-reference",
				"Null character reference",
			);
			return chr(65533);
		}
		if ( code > 1114111 ) {
			self._parse_error(
				"character-reference-outside-unicode-range",
				"Character reference outside Unicode range",
			);
			return chr(65533);
		}
		if ( code >= 55296 and code <= 57343 ) {
			self._parse_error(
				"surrogate-character-reference",
				"Surrogate character reference",
			);
			return chr(65533);
		}
		let replacement := _html_tok_control_replacement(code);
		if ( replacement ≢ null ) {
			self._parse_error(
				"control-character-reference",
				"Control character reference",
			);
			return chr(replacement);
		}
		return chr(code);
	}
}