aboutsummaryrefslogtreecommitdiffhomepage
path: root/inc/3rdparty/libraries/html5
diff options
context:
space:
mode:
authorNicolas Lœuillet <nicolas.loeuillet@gmail.com>2013-12-23 02:28:56 -0800
committerNicolas Lœuillet <nicolas.loeuillet@gmail.com>2013-12-23 02:28:56 -0800
commit60fc4f4b1ab37fbfe9021f3fa1395d66a4424ed2 (patch)
tree515c4b9c8286ae363f77722c91acb878151dc386 /inc/3rdparty/libraries/html5
parentcbfd5a1019f47fadefd8490dae9f039ae894298d (diff)
parentda5fc42f615eeb45a702604970f94967507fb432 (diff)
downloadwallabag-60fc4f4b1ab37fbfe9021f3fa1395d66a4424ed2.tar.gz
wallabag-60fc4f4b1ab37fbfe9021f3fa1395d66a4424ed2.tar.zst
wallabag-60fc4f4b1ab37fbfe9021f3fa1395d66a4424ed2.zip
Merge pull request #363 from inthepoche/dev1.3.0
poche 1.3.0
Diffstat (limited to 'inc/3rdparty/libraries/html5')
-rw-r--r--inc/3rdparty/libraries/html5/Data.php114
-rw-r--r--inc/3rdparty/libraries/html5/InputStream.php284
-rw-r--r--inc/3rdparty/libraries/html5/Parser.php36
-rw-r--r--inc/3rdparty/libraries/html5/Tokenizer.php2422
-rw-r--r--inc/3rdparty/libraries/html5/TreeBuilder.php3840
-rw-r--r--inc/3rdparty/libraries/html5/named-character-references.ser1
6 files changed, 6697 insertions, 0 deletions
diff --git a/inc/3rdparty/libraries/html5/Data.php b/inc/3rdparty/libraries/html5/Data.php
new file mode 100644
index 00000000..497345f4
--- /dev/null
+++ b/inc/3rdparty/libraries/html5/Data.php
@@ -0,0 +1,114 @@
1<?php
2
3// warning: this file is encoded in UTF-8!
4
5class HTML5_Data
6{
7
8 // at some point this should be moved to a .ser file. Another
9 // possible optimization is to give UTF-8 bytes, not Unicode
10 // codepoints
11 // XXX: Not quite sure why it's named this; this is
12 // actually the numeric entity dereference table.
13 protected static $realCodepointTable = array(
14 0x00 => 0xFFFD, // REPLACEMENT CHARACTER
15 0x0D => 0x000A, // LINE FEED (LF)
16 0x80 => 0x20AC, // EURO SIGN ('€')
17 0x81 => 0x0081, // <control>
18 0x82 => 0x201A, // SINGLE LOW-9 QUOTATION MARK ('‚')
19 0x83 => 0x0192, // LATIN SMALL LETTER F WITH HOOK ('ƒ')
20 0x84 => 0x201E, // DOUBLE LOW-9 QUOTATION MARK ('„')
21 0x85 => 0x2026, // HORIZONTAL ELLIPSIS ('…')
22 0x86 => 0x2020, // DAGGER ('†')
23 0x87 => 0x2021, // DOUBLE DAGGER ('‡')
24 0x88 => 0x02C6, // MODIFIER LETTER CIRCUMFLEX ACCENT ('ˆ')
25 0x89 => 0x2030, // PER MILLE SIGN ('‰')
26 0x8A => 0x0160, // LATIN CAPITAL LETTER S WITH CARON ('Š')
27 0x8B => 0x2039, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK ('‹')
28 0x8C => 0x0152, // LATIN CAPITAL LIGATURE OE ('Œ')
29 0x8D => 0x008D, // <control>
30 0x8E => 0x017D, // LATIN CAPITAL LETTER Z WITH CARON ('Ž')
31 0x8F => 0x008F, // <control>
32 0x90 => 0x0090, // <control>
33 0x91 => 0x2018, // LEFT SINGLE QUOTATION MARK ('‘')
34 0x92 => 0x2019, // RIGHT SINGLE QUOTATION MARK ('’')
35 0x93 => 0x201C, // LEFT DOUBLE QUOTATION MARK ('“')
36 0x94 => 0x201D, // RIGHT DOUBLE QUOTATION MARK ('”')
37 0x95 => 0x2022, // BULLET ('•')
38 0x96 => 0x2013, // EN DASH ('–')
39 0x97 => 0x2014, // EM DASH ('—')
40 0x98 => 0x02DC, // SMALL TILDE ('˜')
41 0x99 => 0x2122, // TRADE MARK SIGN ('™')
42 0x9A => 0x0161, // LATIN SMALL LETTER S WITH CARON ('š')
43 0x9B => 0x203A, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK ('›')
44 0x9C => 0x0153, // LATIN SMALL LIGATURE OE ('œ')
45 0x9D => 0x009D, // <control>
46 0x9E => 0x017E, // LATIN SMALL LETTER Z WITH CARON ('ž')
47 0x9F => 0x0178, // LATIN CAPITAL LETTER Y WITH DIAERESIS ('Ÿ')
48 );
49
50 protected static $namedCharacterReferences;
51
52 protected static $namedCharacterReferenceMaxLength;
53
54 /**
55 * Returns the "real" Unicode codepoint of a malformed character
56 * reference.
57 */
58 public static function getRealCodepoint($ref) {
59 if (!isset(self::$realCodepointTable[$ref])) return false;
60 else return self::$realCodepointTable[$ref];
61 }
62
63 public static function getNamedCharacterReferences() {
64 if (!self::$namedCharacterReferences) {
65 self::$namedCharacterReferences = unserialize(
66 file_get_contents(dirname(__FILE__) . '/named-character-references.ser'));
67 }
68 return self::$namedCharacterReferences;
69 }
70
71 /**
72 * Converts a Unicode codepoint to sequence of UTF-8 bytes.
73 * @note Shamelessly stolen from HTML Purifier, which is also
74 * shamelessly stolen from Feyd (which is in public domain).
75 */
76 public static function utf8chr($code) {
77 /* We don't care: we live dangerously
78 * if($code > 0x10FFFF or $code < 0x0 or
79 ($code >= 0xD800 and $code <= 0xDFFF) ) {
80 // bits are set outside the "valid" range as defined
81 // by UNICODE 4.1.0
82 return "\xEF\xBF\xBD";
83 }*/
84
85 $x = $y = $z = $w = 0;
86 if ($code < 0x80) {
87 // regular ASCII character
88 $x = $code;
89 } else {
90 // set up bits for UTF-8
91 $x = ($code & 0x3F) | 0x80;
92 if ($code < 0x800) {
93 $y = (($code & 0x7FF) >> 6) | 0xC0;
94 } else {
95 $y = (($code & 0xFC0) >> 6) | 0x80;
96 if($code < 0x10000) {
97 $z = (($code >> 12) & 0x0F) | 0xE0;
98 } else {
99 $z = (($code >> 12) & 0x3F) | 0x80;
100 $w = (($code >> 18) & 0x07) | 0xF0;
101 }
102 }
103 }
104 // set up the actual character
105 $ret = '';
106 if($w) $ret .= chr($w);
107 if($z) $ret .= chr($z);
108 if($y) $ret .= chr($y);
109 $ret .= chr($x);
110
111 return $ret;
112 }
113
114}
diff --git a/inc/3rdparty/libraries/html5/InputStream.php b/inc/3rdparty/libraries/html5/InputStream.php
new file mode 100644
index 00000000..f98b4272
--- /dev/null
+++ b/inc/3rdparty/libraries/html5/InputStream.php
@@ -0,0 +1,284 @@
1<?php
2
3/*
4
5Copyright 2009 Geoffrey Sneddon <http://gsnedders.com/>
6
7Permission is hereby granted, free of charge, to any person obtaining a
8copy of this software and associated documentation files (the
9"Software"), to deal in the Software without restriction, including
10without limitation the rights to use, copy, modify, merge, publish,
11distribute, sublicense, and/or sell copies of the Software, and to
12permit persons to whom the Software is furnished to do so, subject to
13the following conditions:
14
15The above copyright notice and this permission notice shall be included
16in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26*/
27
28// Some conventions:
29// /* */ indicates verbatim text from the HTML 5 specification
30// // indicates regular comments
31
32class HTML5_InputStream {
33 /**
34 * The string data we're parsing.
35 */
36 private $data;
37
38 /**
39 * The current integer byte position we are in $data
40 */
41 private $char;
42
43 /**
44 * Length of $data; when $char === $data, we are at the end-of-file.
45 */
46 private $EOF;
47
48 /**
49 * Parse errors.
50 */
51 public $errors = array();
52
53 /**
54 * @param $data Data to parse
55 */
56 public function __construct($data) {
57
58 /* Given an encoding, the bytes in the input stream must be
59 converted to Unicode characters for the tokeniser, as
60 described by the rules for that encoding, except that the
61 leading U+FEFF BYTE ORDER MARK character, if any, must not
62 be stripped by the encoding layer (it is stripped by the rule below).
63
64 Bytes or sequences of bytes in the original byte stream that
65 could not be converted to Unicode characters must be converted
66 to U+FFFD REPLACEMENT CHARACTER code points. */
67
68 // XXX currently assuming input data is UTF-8; once we
69 // build encoding detection this will no longer be the case
70 //
71 // We previously had an mbstring implementation here, but that
72 // implementation is heavily non-conforming, so it's been
73 // omitted.
74 if (extension_loaded('iconv')) {
75 // non-conforming
76 $data = @iconv('UTF-8', 'UTF-8//IGNORE', $data);
77 } else {
78 // we can make a conforming native implementation
79 throw new Exception('Not implemented, please install mbstring or iconv');
80 }
81
82 /* One leading U+FEFF BYTE ORDER MARK character must be
83 ignored if any are present. */
84 if (substr($data, 0, 3) === "\xEF\xBB\xBF") {
85 $data = substr($data, 3);
86 }
87
88 /* All U+0000 NULL characters in the input must be replaced
89 by U+FFFD REPLACEMENT CHARACTERs. Any occurrences of such
90 characters is a parse error. */
91 for ($i = 0, $count = substr_count($data, "\0"); $i < $count; $i++) {
92 $this->errors[] = array(
93 'type' => HTML5_Tokenizer::PARSEERROR,
94 'data' => 'null-character'
95 );
96 }
97 /* U+000D CARRIAGE RETURN (CR) characters and U+000A LINE FEED
98 (LF) characters are treated specially. Any CR characters
99 that are followed by LF characters must be removed, and any
100 CR characters not followed by LF characters must be converted
101 to LF characters. Thus, newlines in HTML DOMs are represented
102 by LF characters, and there are never any CR characters in the
103 input to the tokenization stage. */
104 $data = str_replace(
105 array(
106 "\0",
107 "\r\n",
108 "\r"
109 ),
110 array(
111 "\xEF\xBF\xBD",
112 "\n",
113 "\n"
114 ),
115 $data
116 );
117
118 /* Any occurrences of any characters in the ranges U+0001 to
119 U+0008, U+000B, U+000E to U+001F, U+007F to U+009F,
120 U+D800 to U+DFFF , U+FDD0 to U+FDEF, and
121 characters U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, U+2FFFE, U+2FFFF,
122 U+3FFFE, U+3FFFF, U+4FFFE, U+4FFFF, U+5FFFE, U+5FFFF, U+6FFFE,
123 U+6FFFF, U+7FFFE, U+7FFFF, U+8FFFE, U+8FFFF, U+9FFFE, U+9FFFF,
124 U+AFFFE, U+AFFFF, U+BFFFE, U+BFFFF, U+CFFFE, U+CFFFF, U+DFFFE,
125 U+DFFFF, U+EFFFE, U+EFFFF, U+FFFFE, U+FFFFF, U+10FFFE, and
126 U+10FFFF are parse errors. (These are all control characters
127 or permanently undefined Unicode characters.) */
128 // Check PCRE is loaded.
129 if (extension_loaded('pcre')) {
130 $count = preg_match_all(
131 '/(?:
132 [\x01-\x08\x0B\x0E-\x1F\x7F] # U+0001 to U+0008, U+000B, U+000E to U+001F and U+007F
133 |
134 \xC2[\x80-\x9F] # U+0080 to U+009F
135 |
136 \xED(?:\xA0[\x80-\xFF]|[\xA1-\xBE][\x00-\xFF]|\xBF[\x00-\xBF]) # U+D800 to U+DFFFF
137 |
138 \xEF\xB7[\x90-\xAF] # U+FDD0 to U+FDEF
139 |
140 \xEF\xBF[\xBE\xBF] # U+FFFE and U+FFFF
141 |
142 [\xF0-\xF4][\x8F-\xBF]\xBF[\xBE\xBF] # U+nFFFE and U+nFFFF (1 <= n <= 10_{16})
143 )/x',
144 $data,
145 $matches
146 );
147 for ($i = 0; $i < $count; $i++) {
148 $this->errors[] = array(
149 'type' => HTML5_Tokenizer::PARSEERROR,
150 'data' => 'invalid-codepoint'
151 );
152 }
153 } else {
154 // XXX: Need non-PCRE impl, probably using substr_count
155 }
156
157 $this->data = $data;
158 $this->char = 0;
159 $this->EOF = strlen($data);
160 }
161
162 /**
163 * Returns the current line that the tokenizer is at.
164 */
165 public function getCurrentLine() {
166 // Check the string isn't empty
167 if($this->EOF) {
168 // Add one to $this->char because we want the number for the next
169 // byte to be processed.
170 return substr_count($this->data, "\n", 0, min($this->char, $this->EOF)) + 1;
171 } else {
172 // If the string is empty, we are on the first line (sorta).
173 return 1;
174 }
175 }
176
177 /**
178 * Returns the current column of the current line that the tokenizer is at.
179 */
180 public function getColumnOffset() {
181 // strrpos is weird, and the offset needs to be negative for what we
182 // want (i.e., the last \n before $this->char). This needs to not have
183 // one (to make it point to the next character, the one we want the
184 // position of) added to it because strrpos's behaviour includes the
185 // final offset byte.
186 $lastLine = strrpos($this->data, "\n", $this->char - 1 - strlen($this->data));
187
188 // However, for here we want the length up until the next byte to be
189 // processed, so add one to the current byte ($this->char).
190 if($lastLine !== false) {
191 $findLengthOf = substr($this->data, $lastLine + 1, $this->char - 1 - $lastLine);
192 } else {
193 $findLengthOf = substr($this->data, 0, $this->char);
194 }
195
196 // Get the length for the string we need.
197 if(extension_loaded('iconv')) {
198 return iconv_strlen($findLengthOf, 'utf-8');
199 } elseif(extension_loaded('mbstring')) {
200 return mb_strlen($findLengthOf, 'utf-8');
201 } elseif(extension_loaded('xml')) {
202 return strlen(utf8_decode($findLengthOf));
203 } else {
204 $count = count_chars($findLengthOf);
205 // 0x80 = 0x7F - 0 + 1 (one added to get inclusive range)
206 // 0x33 = 0xF4 - 0x2C + 1 (one added to get inclusive range)
207 return array_sum(array_slice($count, 0, 0x80)) +
208 array_sum(array_slice($count, 0xC2, 0x33));
209 }
210 }
211
212 /**
213 * Retrieve the currently consume character.
214 * @note This performs bounds checking
215 */
216 public function char() {
217 return ($this->char++ < $this->EOF)
218 ? $this->data[$this->char - 1]
219 : false;
220 }
221
222 /**
223 * Get all characters until EOF.
224 * @note This performs bounds checking
225 */
226 public function remainingChars() {
227 if($this->char < $this->EOF) {
228 $data = substr($this->data, $this->char);
229 $this->char = $this->EOF;
230 return $data;
231 } else {
232 return false;
233 }
234 }
235
236 /**
237 * Matches as far as possible until we reach a certain set of bytes
238 * and returns the matched substring.
239 * @param $bytes Bytes to match.
240 */
241 public function charsUntil($bytes, $max = null) {
242 if ($this->char < $this->EOF) {
243 if ($max === 0 || $max) {
244 $len = strcspn($this->data, $bytes, $this->char, $max);
245 } else {
246 $len = strcspn($this->data, $bytes, $this->char);
247 }
248 $string = (string) substr($this->data, $this->char, $len);
249 $this->char += $len;
250 return $string;
251 } else {
252 return false;
253 }
254 }
255
256 /**
257 * Matches as far as possible with a certain set of bytes
258 * and returns the matched substring.
259 * @param $bytes Bytes to match.
260 */
261 public function charsWhile($bytes, $max = null) {
262 if ($this->char < $this->EOF) {
263 if ($max === 0 || $max) {
264 $len = strspn($this->data, $bytes, $this->char, $max);
265 } else {
266 $len = strspn($this->data, $bytes, $this->char);
267 }
268 $string = (string) substr($this->data, $this->char, $len);
269 $this->char += $len;
270 return $string;
271 } else {
272 return false;
273 }
274 }
275
276 /**
277 * Unconsume one character.
278 */
279 public function unget() {
280 if ($this->char <= $this->EOF) {
281 $this->char--;
282 }
283 }
284}
diff --git a/inc/3rdparty/libraries/html5/Parser.php b/inc/3rdparty/libraries/html5/Parser.php
new file mode 100644
index 00000000..5f9ca560
--- /dev/null
+++ b/inc/3rdparty/libraries/html5/Parser.php
@@ -0,0 +1,36 @@
1<?php
2
3require_once dirname(__FILE__) . '/Data.php';
4require_once dirname(__FILE__) . '/InputStream.php';
5require_once dirname(__FILE__) . '/TreeBuilder.php';
6require_once dirname(__FILE__) . '/Tokenizer.php';
7
8/**
9 * Outwards facing interface for HTML5.
10 */
11class HTML5_Parser
12{
13 /**
14 * Parses a full HTML document.
15 * @param $text HTML text to parse
16 * @param $builder Custom builder implementation
17 * @return Parsed HTML as DOMDocument
18 */
19 static public function parse($text, $builder = null) {
20 $tokenizer = new HTML5_Tokenizer($text, $builder);
21 $tokenizer->parse();
22 return $tokenizer->save();
23 }
24 /**
25 * Parses an HTML fragment.
26 * @param $text HTML text to parse
27 * @param $context String name of context element to pretend parsing is in.
28 * @param $builder Custom builder implementation
29 * @return Parsed HTML as DOMDocument
30 */
31 static public function parseFragment($text, $context = null, $builder = null) {
32 $tokenizer = new HTML5_Tokenizer($text, $builder);
33 $tokenizer->parseFragment($context);
34 return $tokenizer->save();
35 }
36}
diff --git a/inc/3rdparty/libraries/html5/Tokenizer.php b/inc/3rdparty/libraries/html5/Tokenizer.php
new file mode 100644
index 00000000..0af07164
--- /dev/null
+++ b/inc/3rdparty/libraries/html5/Tokenizer.php
@@ -0,0 +1,2422 @@
1<?php
2
3/*
4
5Copyright 2007 Jeroen van der Meer <http://jero.net/>
6Copyright 2008 Edward Z. Yang <http://htmlpurifier.org/>
7Copyright 2009 Geoffrey Sneddon <http://gsnedders.com/>
8
9Permission is hereby granted, free of charge, to any person obtaining a
10copy of this software and associated documentation files (the
11"Software"), to deal in the Software without restriction, including
12without limitation the rights to use, copy, modify, merge, publish,
13distribute, sublicense, and/or sell copies of the Software, and to
14permit persons to whom the Software is furnished to do so, subject to
15the following conditions:
16
17The above copyright notice and this permission notice shall be included
18in all copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28*/
29
30// Some conventions:
31// /* */ indicates verbatim text from the HTML 5 specification
32// // indicates regular comments
33
34// all flags are in hyphenated form
35
36class HTML5_Tokenizer {
37 /**
38 * Points to an InputStream object.
39 */
40 protected $stream;
41
42 /**
43 * Tree builder that the tokenizer emits token to.
44 */
45 private $tree;
46
47 /**
48 * Current content model we are parsing as.
49 */
50 protected $content_model;
51
52 /**
53 * Current token that is being built, but not yet emitted. Also
54 * is the last token emitted, if applicable.
55 */
56 protected $token;
57
58 // These are constants describing the content model
59 const PCDATA = 0;
60 const RCDATA = 1;
61 const CDATA = 2;
62 const PLAINTEXT = 3;
63
64 // These are constants describing tokens
65 // XXX should probably be moved somewhere else, probably the
66 // HTML5 class.
67 const DOCTYPE = 0;
68 const STARTTAG = 1;
69 const ENDTAG = 2;
70 const COMMENT = 3;
71 const CHARACTER = 4;
72 const SPACECHARACTER = 5;
73 const EOF = 6;
74 const PARSEERROR = 7;
75
76 // These are constants representing bunches of characters.
77 const ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
78 const UPPER_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
79 const LOWER_ALPHA = 'abcdefghijklmnopqrstuvwxyz';
80 const DIGIT = '0123456789';
81 const HEX = '0123456789ABCDEFabcdef';
82 const WHITESPACE = "\t\n\x0c ";
83
84 /**
85 * @param $data Data to parse
86 */
87 public function __construct($data, $builder = null) {
88 $this->stream = new HTML5_InputStream($data);
89 if (!$builder) $this->tree = new HTML5_TreeBuilder;
90 else $this->tree = $builder;
91 $this->content_model = self::PCDATA;
92 }
93
94 public function parseFragment($context = null) {
95 $this->tree->setupContext($context);
96 if ($this->tree->content_model) {
97 $this->content_model = $this->tree->content_model;
98 $this->tree->content_model = null;
99 }
100 $this->parse();
101 }
102
103 // XXX maybe convert this into an iterator? regardless, this function
104 // and the save function should go into a Parser facade of some sort
105 /**
106 * Performs the actual parsing of the document.
107 */
108 public function parse() {
109 // Current state
110 $state = 'data';
111 // This is used to avoid having to have look-behind in the data state.
112 $lastFourChars = '';
113 /**
114 * Escape flag as specified by the HTML5 specification: "used to
115 * control the behavior of the tokeniser. It is either true or
116 * false, and initially must be set to the false state."
117 */
118 $escape = false;
119 //echo "\n\n";
120 while($state !== null) {
121
122 /*echo $state . ' ';
123 switch ($this->content_model) {
124 case self::PCDATA: echo 'PCDATA'; break;
125 case self::RCDATA: echo 'RCDATA'; break;
126 case self::CDATA: echo 'CDATA'; break;
127 case self::PLAINTEXT: echo 'PLAINTEXT'; break;
128 }
129 if ($escape) echo " escape";
130 echo "\n";*/
131
132 switch($state) {
133 case 'data':
134
135 /* Consume the next input character */
136 $char = $this->stream->char();
137 $lastFourChars .= $char;
138 if (strlen($lastFourChars) > 4) $lastFourChars = substr($lastFourChars, -4);
139
140 // see below for meaning
141 $hyp_cond =
142 !$escape &&
143 (
144 $this->content_model === self::RCDATA ||
145 $this->content_model === self::CDATA
146 );
147 $amp_cond =
148 !$escape &&
149 (
150 $this->content_model === self::PCDATA ||
151 $this->content_model === self::RCDATA
152 );
153 $lt_cond =
154 $this->content_model === self::PCDATA ||
155 (
156 (
157 $this->content_model === self::RCDATA ||
158 $this->content_model === self::CDATA
159 ) &&
160 !$escape
161 );
162 $gt_cond =
163 $escape &&
164 (
165 $this->content_model === self::RCDATA ||
166 $this->content_model === self::CDATA
167 );
168
169 if($char === '&' && $amp_cond) {
170 /* U+0026 AMPERSAND (&)
171 When the content model flag is set to one of the PCDATA or RCDATA
172 states and the escape flag is false: switch to the
173 character reference data state. Otherwise: treat it as per
174 the "anything else" entry below. */
175 $state = 'character reference data';
176
177 } elseif(
178 $char === '-' &&
179 $hyp_cond &&
180 $lastFourChars === '<!--'
181 ) {
182 /*
183 U+002D HYPHEN-MINUS (-)
184 If the content model flag is set to either the RCDATA state or
185 the CDATA state, and the escape flag is false, and there are at
186 least three characters before this one in the input stream, and the
187 last four characters in the input stream, including this one, are
188 U+003C LESS-THAN SIGN, U+0021 EXCLAMATION MARK, U+002D HYPHEN-MINUS,
189 and U+002D HYPHEN-MINUS ("<!--"), then set the escape flag to true. */
190 $escape = true;
191
192 /* In any case, emit the input character as a character token. Stay
193 in the data state. */
194 $this->emitToken(array(
195 'type' => self::CHARACTER,
196 'data' => '-'
197 ));
198 // We do the "any case" part as part of "anything else".
199
200 /* U+003C LESS-THAN SIGN (<) */
201 } elseif($char === '<' && $lt_cond) {
202 /* When the content model flag is set to the PCDATA state: switch
203 to the tag open state.
204
205 When the content model flag is set to either the RCDATA state or
206 the CDATA state and the escape flag is false: switch to the tag
207 open state.
208
209 Otherwise: treat it as per the "anything else" entry below. */
210 $state = 'tag open';
211
212 /* U+003E GREATER-THAN SIGN (>) */
213 } elseif(
214 $char === '>' &&
215 $gt_cond &&
216 substr($lastFourChars, 1) === '-->'
217 ) {
218 /* If the content model flag is set to either the RCDATA state or
219 the CDATA state, and the escape flag is true, and the last three
220 characters in the input stream including this one are U+002D
221 HYPHEN-MINUS, U+002D HYPHEN-MINUS, U+003E GREATER-THAN SIGN ("-->"),
222 set the escape flag to false. */
223 $escape = false;
224
225 /* In any case, emit the input character as a character token.
226 Stay in the data state. */
227 $this->emitToken(array(
228 'type' => self::CHARACTER,
229 'data' => '>'
230 ));
231 // We do the "any case" part as part of "anything else".
232
233 } elseif($char === false) {
234 /* EOF
235 Emit an end-of-file token. */
236 $state = null;
237 $this->tree->emitToken(array(
238 'type' => self::EOF
239 ));
240
241 } elseif($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
242 // Directly after emitting a token you switch back to the "data
243 // state". At that point spaceCharacters are important so they are
244 // emitted separately.
245 $chars = $this->stream->charsWhile(self::WHITESPACE);
246 $this->emitToken(array(
247 'type' => self::SPACECHARACTER,
248 'data' => $char . $chars
249 ));
250 $lastFourChars .= $chars;
251 if (strlen($lastFourChars) > 4) $lastFourChars = substr($lastFourChars, -4);
252
253 } else {
254 /* Anything else
255 THIS IS AN OPTIMIZATION: Get as many character that
256 otherwise would also be treated as a character token and emit it
257 as a single character token. Stay in the data state. */
258
259 $mask = '';
260 if ($hyp_cond) $mask .= '-';
261 if ($amp_cond) $mask .= '&';
262 if ($lt_cond) $mask .= '<';
263 if ($gt_cond) $mask .= '>';
264
265 if ($mask === '') {
266 $chars = $this->stream->remainingChars();
267 } else {
268 $chars = $this->stream->charsUntil($mask);
269 }
270
271 $this->emitToken(array(
272 'type' => self::CHARACTER,
273 'data' => $char . $chars
274 ));
275
276 $lastFourChars .= $chars;
277 if (strlen($lastFourChars) > 4) $lastFourChars = substr($lastFourChars, -4);
278
279 $state = 'data';
280 }
281 break;
282
283 case 'character reference data':
284 /* (This cannot happen if the content model flag
285 is set to the CDATA state.) */
286
287 /* Attempt to consume a character reference, with no
288 additional allowed character. */
289 $entity = $this->consumeCharacterReference();
290
291 /* If nothing is returned, emit a U+0026 AMPERSAND
292 character token. Otherwise, emit the character token that
293 was returned. */
294 // This is all done when consuming the character reference.
295 $this->emitToken(array(
296 'type' => self::CHARACTER,
297 'data' => $entity
298 ));
299
300 /* Finally, switch to the data state. */
301 $state = 'data';
302 break;
303
304 case 'tag open':
305 $char = $this->stream->char();
306
307 switch($this->content_model) {
308 case self::RCDATA:
309 case self::CDATA:
310 /* Consume the next input character. If it is a
311 U+002F SOLIDUS (/) character, switch to the close
312 tag open state. Otherwise, emit a U+003C LESS-THAN
313 SIGN character token and reconsume the current input
314 character in the data state. */
315 // We consumed above.
316
317 if($char === '/') {
318 $state = 'close tag open';
319
320 } else {
321 $this->emitToken(array(
322 'type' => self::CHARACTER,
323 'data' => '<'
324 ));
325
326 $this->stream->unget();
327
328 $state = 'data';
329 }
330 break;
331
332 case self::PCDATA:
333 /* If the content model flag is set to the PCDATA state
334 Consume the next input character: */
335 // We consumed above.
336
337 if($char === '!') {
338 /* U+0021 EXCLAMATION MARK (!)
339 Switch to the markup declaration open state. */
340 $state = 'markup declaration open';
341
342 } elseif($char === '/') {
343 /* U+002F SOLIDUS (/)
344 Switch to the close tag open state. */
345 $state = 'close tag open';
346
347 } elseif('A' <= $char && $char <= 'Z') {
348 /* U+0041 LATIN LETTER A through to U+005A LATIN LETTER Z
349 Create a new start tag token, set its tag name to the lowercase
350 version of the input character (add 0x0020 to the character's code
351 point), then switch to the tag name state. (Don't emit the token
352 yet; further details will be filled in before it is emitted.) */
353 $this->token = array(
354 'name' => strtolower($char),
355 'type' => self::STARTTAG,
356 'attr' => array()
357 );
358
359 $state = 'tag name';
360
361 } elseif('a' <= $char && $char <= 'z') {
362 /* U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
363 Create a new start tag token, set its tag name to the input
364 character, then switch to the tag name state. (Don't emit
365 the token yet; further details will be filled in before it
366 is emitted.) */
367 $this->token = array(
368 'name' => $char,
369 'type' => self::STARTTAG,
370 'attr' => array()
371 );
372
373 $state = 'tag name';
374
375 } elseif($char === '>') {
376 /* U+003E GREATER-THAN SIGN (>)
377 Parse error. Emit a U+003C LESS-THAN SIGN character token and a
378 U+003E GREATER-THAN SIGN character token. Switch to the data state. */
379 $this->emitToken(array(
380 'type' => self::PARSEERROR,
381 'data' => 'expected-tag-name-but-got-right-bracket'
382 ));
383 $this->emitToken(array(
384 'type' => self::CHARACTER,
385 'data' => '<>'
386 ));
387
388 $state = 'data';
389
390 } elseif($char === '?') {
391 /* U+003F QUESTION MARK (?)
392 Parse error. Switch to the bogus comment state. */
393 $this->emitToken(array(
394 'type' => self::PARSEERROR,
395 'data' => 'expected-tag-name-but-got-question-mark'
396 ));
397 $this->token = array(
398 'data' => '?',
399 'type' => self::COMMENT
400 );
401 $state = 'bogus comment';
402
403 } else {
404 /* Anything else
405 Parse error. Emit a U+003C LESS-THAN SIGN character token and
406 reconsume the current input character in the data state. */
407 $this->emitToken(array(
408 'type' => self::PARSEERROR,
409 'data' => 'expected-tag-name'
410 ));
411 $this->emitToken(array(
412 'type' => self::CHARACTER,
413 'data' => '<'
414 ));
415
416 $state = 'data';
417 $this->stream->unget();
418 }
419 break;
420 }
421 break;
422
423 case 'close tag open':
424 if (
425 $this->content_model === self::RCDATA ||
426 $this->content_model === self::CDATA
427 ) {
428 /* If the content model flag is set to the RCDATA or CDATA
429 states... */
430 $name = strtolower($this->stream->charsWhile(self::ALPHA));
431 $following = $this->stream->char();
432 $this->stream->unget();
433 if (
434 !$this->token ||
435 $this->token['name'] !== $name ||
436 $this->token['name'] === $name && !in_array($following, array("\x09", "\x0A", "\x0C", "\x20", "\x3E", "\x2F", false))
437 ) {
438 /* if no start tag token has ever been emitted by this instance
439 of the tokenizer (fragment case), or, if the next few
440 characters do not match the tag name of the last start tag
441 token emitted (compared in an ASCII case-insensitive manner),
442 or if they do but they are not immediately followed by one of
443 the following characters:
444
445 * U+0009 CHARACTER TABULATION
446 * U+000A LINE FEED (LF)
447 * U+000C FORM FEED (FF)
448 * U+0020 SPACE
449 * U+003E GREATER-THAN SIGN (>)
450 * U+002F SOLIDUS (/)
451 * EOF
452
453 ...then emit a U+003C LESS-THAN SIGN character token, a
454 U+002F SOLIDUS character token, and switch to the data
455 state to process the next input character. */
456 // XXX: Probably ought to replace in_array with $following === x ||...
457
458 // We also need to emit $name now we've consumed that, as we
459 // know it'll just be emitted as a character token.
460 $this->emitToken(array(
461 'type' => self::CHARACTER,
462 'data' => '</' . $name
463 ));
464
465 $state = 'data';
466 } else {
467 // This matches what would happen if we actually did the
468 // otherwise below (but we can't because we've consumed too
469 // much).
470
471 // Start the end tag token with the name we already have.
472 $this->token = array(
473 'name' => $name,
474 'type' => self::ENDTAG
475 );
476
477 // Change to tag name state.
478 $state = 'tag name';
479 }
480 } elseif ($this->content_model === self::PCDATA) {
481 /* Otherwise, if the content model flag is set to the PCDATA
482 state [...]: */
483 $char = $this->stream->char();
484
485 if ('A' <= $char && $char <= 'Z') {
486 /* U+0041 LATIN LETTER A through to U+005A LATIN LETTER Z
487 Create a new end tag token, set its tag name to the lowercase version
488 of the input character (add 0x0020 to the character's code point), then
489 switch to the tag name state. (Don't emit the token yet; further details
490 will be filled in before it is emitted.) */
491 $this->token = array(
492 'name' => strtolower($char),
493 'type' => self::ENDTAG
494 );
495
496 $state = 'tag name';
497
498 } elseif ('a' <= $char && $char <= 'z') {
499 /* U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z
500 Create a new end tag token, set its tag name to the
501 input character, then switch to the tag name state.
502 (Don't emit the token yet; further details will be
503 filled in before it is emitted.) */
504 $this->token = array(
505 'name' => $char,
506 'type' => self::ENDTAG
507 );
508
509 $state = 'tag name';
510
511 } elseif($char === '>') {
512 /* U+003E GREATER-THAN SIGN (>)
513 Parse error. Switch to the data state. */
514 $this->emitToken(array(
515 'type' => self::PARSEERROR,
516 'data' => 'expected-closing-tag-but-got-right-bracket'
517 ));
518 $state = 'data';
519
520 } elseif($char === false) {
521 /* EOF
522 Parse error. Emit a U+003C LESS-THAN SIGN character token and a U+002F
523 SOLIDUS character token. Reconsume the EOF character in the data state. */
524 $this->emitToken(array(
525 'type' => self::PARSEERROR,
526 'data' => 'expected-closing-tag-but-got-eof'
527 ));
528 $this->emitToken(array(
529 'type' => self::CHARACTER,
530 'data' => '</'
531 ));
532
533 $this->stream->unget();
534 $state = 'data';
535
536 } else {
537 /* Parse error. Switch to the bogus comment state. */
538 $this->emitToken(array(
539 'type' => self::PARSEERROR,
540 'data' => 'expected-closing-tag-but-got-char'
541 ));
542 $this->token = array(
543 'data' => $char,
544 'type' => self::COMMENT
545 );
546 $state = 'bogus comment';
547 }
548 }
549 break;
550
551 case 'tag name':
552 /* Consume the next input character: */
553 $char = $this->stream->char();
554
555 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
556 /* U+0009 CHARACTER TABULATION
557 U+000A LINE FEED (LF)
558 U+000C FORM FEED (FF)
559 U+0020 SPACE
560 Switch to the before attribute name state. */
561 $state = 'before attribute name';
562
563 } elseif($char === '/') {
564 /* U+002F SOLIDUS (/)
565 Switch to the self-closing start tag state. */
566 $state = 'self-closing start tag';
567
568 } elseif($char === '>') {
569 /* U+003E GREATER-THAN SIGN (>)
570 Emit the current tag token. Switch to the data state. */
571 $this->emitToken($this->token);
572 $state = 'data';
573
574 } elseif('A' <= $char && $char <= 'Z') {
575 /* U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
576 Append the lowercase version of the current input
577 character (add 0x0020 to the character's code point) to
578 the current tag token's tag name. Stay in the tag name state. */
579 $chars = $this->stream->charsWhile(self::UPPER_ALPHA);
580
581 $this->token['name'] .= strtolower($char . $chars);
582 $state = 'tag name';
583
584 } elseif($char === false) {
585 /* EOF
586 Parse error. Reconsume the EOF character in the data state. */
587 $this->emitToken(array(
588 'type' => self::PARSEERROR,
589 'data' => 'eof-in-tag-name'
590 ));
591
592 $this->stream->unget();
593 $state = 'data';
594
595 } else {
596 /* Anything else
597 Append the current input character to the current tag token's tag name.
598 Stay in the tag name state. */
599 $chars = $this->stream->charsUntil("\t\n\x0C />" . self::UPPER_ALPHA);
600
601 $this->token['name'] .= $char . $chars;
602 $state = 'tag name';
603 }
604 break;
605
606 case 'before attribute name':
607 /* Consume the next input character: */
608 $char = $this->stream->char();
609
610 // this conditional is optimized, check bottom
611 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
612 /* U+0009 CHARACTER TABULATION
613 U+000A LINE FEED (LF)
614 U+000C FORM FEED (FF)
615 U+0020 SPACE
616 Stay in the before attribute name state. */
617 $state = 'before attribute name';
618
619 } elseif($char === '/') {
620 /* U+002F SOLIDUS (/)
621 Switch to the self-closing start tag state. */
622 $state = 'self-closing start tag';
623
624 } elseif($char === '>') {
625 /* U+003E GREATER-THAN SIGN (>)
626 Emit the current tag token. Switch to the data state. */
627 $this->emitToken($this->token);
628 $state = 'data';
629
630 } elseif('A' <= $char && $char <= 'Z') {
631 /* U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
632 Start a new attribute in the current tag token. Set that
633 attribute's name to the lowercase version of the current
634 input character (add 0x0020 to the character's code
635 point), and its value to the empty string. Switch to the
636 attribute name state.*/
637 $this->token['attr'][] = array(
638 'name' => strtolower($char),
639 'value' => ''
640 );
641
642 $state = 'attribute name';
643
644 } elseif($char === false) {
645 /* EOF
646 Parse error. Reconsume the EOF character in the data state. */
647 $this->emitToken(array(
648 'type' => self::PARSEERROR,
649 'data' => 'expected-attribute-name-but-got-eof'
650 ));
651
652 $this->stream->unget();
653 $state = 'data';
654
655 } else {
656 /* U+0022 QUOTATION MARK (")
657 U+0027 APOSTROPHE (')
658 U+003C LESS-THAN SIGN (<)
659 U+003D EQUALS SIGN (=)
660 Parse error. Treat it as per the "anything else" entry
661 below. */
662 if($char === '"' || $char === "'" || $char === '<' || $char === '=') {
663 $this->emitToken(array(
664 'type' => self::PARSEERROR,
665 'data' => 'invalid-character-in-attribute-name'
666 ));
667 }
668
669 /* Anything else
670 Start a new attribute in the current tag token. Set that attribute's
671 name to the current input character, and its value to the empty string.
672 Switch to the attribute name state. */
673 $this->token['attr'][] = array(
674 'name' => $char,
675 'value' => ''
676 );
677
678 $state = 'attribute name';
679 }
680 break;
681
682 case 'attribute name':
683 // Consume the next input character:
684 $char = $this->stream->char();
685
686 // this conditional is optimized, check bottom
687 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
688 /* U+0009 CHARACTER TABULATION
689 U+000A LINE FEED (LF)
690 U+000C FORM FEED (FF)
691 U+0020 SPACE
692 Switch to the after attribute name state. */
693 $state = 'after attribute name';
694
695 } elseif($char === '/') {
696 /* U+002F SOLIDUS (/)
697 Switch to the self-closing start tag state. */
698 $state = 'self-closing start tag';
699
700 } elseif($char === '=') {
701 /* U+003D EQUALS SIGN (=)
702 Switch to the before attribute value state. */
703 $state = 'before attribute value';
704
705 } elseif($char === '>') {
706 /* U+003E GREATER-THAN SIGN (>)
707 Emit the current tag token. Switch to the data state. */
708 $this->emitToken($this->token);
709 $state = 'data';
710
711 } elseif('A' <= $char && $char <= 'Z') {
712 /* U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
713 Append the lowercase version of the current input
714 character (add 0x0020 to the character's code point) to
715 the current attribute's name. Stay in the attribute name
716 state. */
717 $chars = $this->stream->charsWhile(self::UPPER_ALPHA);
718
719 $last = count($this->token['attr']) - 1;
720 $this->token['attr'][$last]['name'] .= strtolower($char . $chars);
721
722 $state = 'attribute name';
723
724 } elseif($char === false) {
725 /* EOF
726 Parse error. Reconsume the EOF character in the data state. */
727 $this->emitToken(array(
728 'type' => self::PARSEERROR,
729 'data' => 'eof-in-attribute-name'
730 ));
731
732 $this->stream->unget();
733 $state = 'data';
734
735 } else {
736 /* U+0022 QUOTATION MARK (")
737 U+0027 APOSTROPHE (')
738 U+003C LESS-THAN SIGN (<)
739 Parse error. Treat it as per the "anything else"
740 entry below. */
741 if($char === '"' || $char === "'" || $char === '<') {
742 $this->emitToken(array(
743 'type' => self::PARSEERROR,
744 'data' => 'invalid-character-in-attribute-name'
745 ));
746 }
747
748 /* Anything else
749 Append the current input character to the current attribute's name.
750 Stay in the attribute name state. */
751 $chars = $this->stream->charsUntil("\t\n\x0C /=>\"'" . self::UPPER_ALPHA);
752
753 $last = count($this->token['attr']) - 1;
754 $this->token['attr'][$last]['name'] .= $char . $chars;
755
756 $state = 'attribute name';
757 }
758
759 /* When the user agent leaves the attribute name state
760 (and before emitting the tag token, if appropriate), the
761 complete attribute's name must be compared to the other
762 attributes on the same token; if there is already an
763 attribute on the token with the exact same name, then this
764 is a parse error and the new attribute must be dropped, along
765 with the value that gets associated with it (if any). */
766 // this might be implemented in the emitToken method
767 break;
768
769 case 'after attribute name':
770 // Consume the next input character:
771 $char = $this->stream->char();
772
773 // this is an optimized conditional, check the bottom
774 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
775 /* U+0009 CHARACTER TABULATION
776 U+000A LINE FEED (LF)
777 U+000C FORM FEED (FF)
778 U+0020 SPACE
779 Stay in the after attribute name state. */
780 $state = 'after attribute name';
781
782 } elseif($char === '/') {
783 /* U+002F SOLIDUS (/)
784 Switch to the self-closing start tag state. */
785 $state = 'self-closing start tag';
786
787 } elseif($char === '=') {
788 /* U+003D EQUALS SIGN (=)
789 Switch to the before attribute value state. */
790 $state = 'before attribute value';
791
792 } elseif($char === '>') {
793 /* U+003E GREATER-THAN SIGN (>)
794 Emit the current tag token. Switch to the data state. */
795 $this->emitToken($this->token);
796 $state = 'data';
797
798 } elseif('A' <= $char && $char <= 'Z') {
799 /* U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
800 Start a new attribute in the current tag token. Set that
801 attribute's name to the lowercase version of the current
802 input character (add 0x0020 to the character's code
803 point), and its value to the empty string. Switch to the
804 attribute name state. */
805 $this->token['attr'][] = array(
806 'name' => strtolower($char),
807 'value' => ''
808 );
809
810 $state = 'attribute name';
811
812 } elseif($char === false) {
813 /* EOF
814 Parse error. Reconsume the EOF character in the data state. */
815 $this->emitToken(array(
816 'type' => self::PARSEERROR,
817 'data' => 'expected-end-of-tag-but-got-eof'
818 ));
819
820 $this->stream->unget();
821 $state = 'data';
822
823 } else {
824 /* U+0022 QUOTATION MARK (")
825 U+0027 APOSTROPHE (')
826 U+003C LESS-THAN SIGN(<)
827 Parse error. Treat it as per the "anything else"
828 entry below. */
829 if($char === '"' || $char === "'" || $char === "<") {
830 $this->emitToken(array(
831 'type' => self::PARSEERROR,
832 'data' => 'invalid-character-after-attribute-name'
833 ));
834 }
835
836 /* Anything else
837 Start a new attribute in the current tag token. Set that attribute's
838 name to the current input character, and its value to the empty string.
839 Switch to the attribute name state. */
840 $this->token['attr'][] = array(
841 'name' => $char,
842 'value' => ''
843 );
844
845 $state = 'attribute name';
846 }
847 break;
848
849 case 'before attribute value':
850 // Consume the next input character:
851 $char = $this->stream->char();
852
853 // this is an optimized conditional
854 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
855 /* U+0009 CHARACTER TABULATION
856 U+000A LINE FEED (LF)
857 U+000C FORM FEED (FF)
858 U+0020 SPACE
859 Stay in the before attribute value state. */
860 $state = 'before attribute value';
861
862 } elseif($char === '"') {
863 /* U+0022 QUOTATION MARK (")
864 Switch to the attribute value (double-quoted) state. */
865 $state = 'attribute value (double-quoted)';
866
867 } elseif($char === '&') {
868 /* U+0026 AMPERSAND (&)
869 Switch to the attribute value (unquoted) state and reconsume
870 this input character. */
871 $this->stream->unget();
872 $state = 'attribute value (unquoted)';
873
874 } elseif($char === '\'') {
875 /* U+0027 APOSTROPHE (')
876 Switch to the attribute value (single-quoted) state. */
877 $state = 'attribute value (single-quoted)';
878
879 } elseif($char === '>') {
880 /* U+003E GREATER-THAN SIGN (>)
881 Parse error. Emit the current tag token. Switch to the data state. */
882 $this->emitToken(array(
883 'type' => self::PARSEERROR,
884 'data' => 'expected-attribute-value-but-got-right-bracket'
885 ));
886 $this->emitToken($this->token);
887 $state = 'data';
888
889 } elseif($char === false) {
890 /* EOF
891 Parse error. Reconsume the EOF character in the data state. */
892 $this->emitToken(array(
893 'type' => self::PARSEERROR,
894 'data' => 'expected-attribute-value-but-got-eof'
895 ));
896 $this->stream->unget();
897 $state = 'data';
898
899 } else {
900 /* U+003D EQUALS SIGN (=)
901 * U+003C LESS-THAN SIGN (<)
902 Parse error. Treat it as per the "anything else" entry below. */
903 if($char === '=' || $char === '<') {
904 $this->emitToken(array(
905 'type' => self::PARSEERROR,
906 'data' => 'equals-in-unquoted-attribute-value'
907 ));
908 }
909
910 /* Anything else
911 Append the current input character to the current attribute's value.
912 Switch to the attribute value (unquoted) state. */
913 $last = count($this->token['attr']) - 1;
914 $this->token['attr'][$last]['value'] .= $char;
915
916 $state = 'attribute value (unquoted)';
917 }
918 break;
919
920 case 'attribute value (double-quoted)':
921 // Consume the next input character:
922 $char = $this->stream->char();
923
924 if($char === '"') {
925 /* U+0022 QUOTATION MARK (")
926 Switch to the after attribute value (quoted) state. */
927 $state = 'after attribute value (quoted)';
928
929 } elseif($char === '&') {
930 /* U+0026 AMPERSAND (&)
931 Switch to the character reference in attribute value
932 state, with the additional allowed character
933 being U+0022 QUOTATION MARK ("). */
934 $this->characterReferenceInAttributeValue('"');
935
936 } elseif($char === false) {
937 /* EOF
938 Parse error. Reconsume the EOF character in the data state. */
939 $this->emitToken(array(
940 'type' => self::PARSEERROR,
941 'data' => 'eof-in-attribute-value-double-quote'
942 ));
943
944 $this->stream->unget();
945 $state = 'data';
946
947 } else {
948 /* Anything else
949 Append the current input character to the current attribute's value.
950 Stay in the attribute value (double-quoted) state. */
951 $chars = $this->stream->charsUntil('"&');
952
953 $last = count($this->token['attr']) - 1;
954 $this->token['attr'][$last]['value'] .= $char . $chars;
955
956 $state = 'attribute value (double-quoted)';
957 }
958 break;
959
960 case 'attribute value (single-quoted)':
961 // Consume the next input character:
962 $char = $this->stream->char();
963
964 if($char === "'") {
965 /* U+0022 QUOTATION MARK (')
966 Switch to the after attribute value state. */
967 $state = 'after attribute value (quoted)';
968
969 } elseif($char === '&') {
970 /* U+0026 AMPERSAND (&)
971 Switch to the entity in attribute value state. */
972 $this->characterReferenceInAttributeValue("'");
973
974 } elseif($char === false) {
975 /* EOF
976 Parse error. Reconsume the EOF character in the data state. */
977 $this->emitToken(array(
978 'type' => self::PARSEERROR,
979 'data' => 'eof-in-attribute-value-single-quote'
980 ));
981
982 $this->stream->unget();
983 $state = 'data';
984
985 } else {
986 /* Anything else
987 Append the current input character to the current attribute's value.
988 Stay in the attribute value (single-quoted) state. */
989 $chars = $this->stream->charsUntil("'&");
990
991 $last = count($this->token['attr']) - 1;
992 $this->token['attr'][$last]['value'] .= $char . $chars;
993
994 $state = 'attribute value (single-quoted)';
995 }
996 break;
997
998 case 'attribute value (unquoted)':
999 // Consume the next input character:
1000 $char = $this->stream->char();
1001
1002 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
1003 /* U+0009 CHARACTER TABULATION
1004 U+000A LINE FEED (LF)
1005 U+000C FORM FEED (FF)
1006 U+0020 SPACE
1007 Switch to the before attribute name state. */
1008 $state = 'before attribute name';
1009
1010 } elseif($char === '&') {
1011 /* U+0026 AMPERSAND (&)
1012 Switch to the entity in attribute value state, with the
1013 additional allowed character being U+003E
1014 GREATER-THAN SIGN (>). */
1015 $this->characterReferenceInAttributeValue('>');
1016
1017 } elseif($char === '>') {
1018 /* U+003E GREATER-THAN SIGN (>)
1019 Emit the current tag token. Switch to the data state. */
1020 $this->emitToken($this->token);
1021 $state = 'data';
1022
1023 } elseif ($char === false) {
1024 /* EOF
1025 Parse error. Reconsume the EOF character in the data state. */
1026 $this->emitToken(array(
1027 'type' => self::PARSEERROR,
1028 'data' => 'eof-in-attribute-value-no-quotes'
1029 ));
1030 $this->stream->unget();
1031 $state = 'data';
1032
1033 } else {
1034 /* U+0022 QUOTATION MARK (")
1035 U+0027 APOSTROPHE (')
1036 U+003C LESS-THAN SIGN (<)
1037 U+003D EQUALS SIGN (=)
1038 Parse error. Treat it as per the "anything else"
1039 entry below. */
1040 if($char === '"' || $char === "'" || $char === '=' || $char == '<') {
1041 $this->emitToken(array(
1042 'type' => self::PARSEERROR,
1043 'data' => 'unexpected-character-in-unquoted-attribute-value'
1044 ));
1045 }
1046
1047 /* Anything else
1048 Append the current input character to the current attribute's value.
1049 Stay in the attribute value (unquoted) state. */
1050 $chars = $this->stream->charsUntil("\t\n\x0c &>\"'=");
1051
1052 $last = count($this->token['attr']) - 1;
1053 $this->token['attr'][$last]['value'] .= $char . $chars;
1054
1055 $state = 'attribute value (unquoted)';
1056 }
1057 break;
1058
1059 case 'after attribute value (quoted)':
1060 /* Consume the next input character: */
1061 $char = $this->stream->char();
1062
1063 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
1064 /* U+0009 CHARACTER TABULATION
1065 U+000A LINE FEED (LF)
1066 U+000C FORM FEED (FF)
1067 U+0020 SPACE
1068 Switch to the before attribute name state. */
1069 $state = 'before attribute name';
1070
1071 } elseif ($char === '/') {
1072 /* U+002F SOLIDUS (/)
1073 Switch to the self-closing start tag state. */
1074 $state = 'self-closing start tag';
1075
1076 } elseif ($char === '>') {
1077 /* U+003E GREATER-THAN SIGN (>)
1078 Emit the current tag token. Switch to the data state. */
1079 $this->emitToken($this->token);
1080 $state = 'data';
1081
1082 } elseif ($char === false) {
1083 /* EOF
1084 Parse error. Reconsume the EOF character in the data state. */
1085 $this->emitToken(array(
1086 'type' => self::PARSEERROR,
1087 'data' => 'unexpected-EOF-after-attribute-value'
1088 ));
1089 $this->stream->unget();
1090 $state = 'data';
1091
1092 } else {
1093 /* Anything else
1094 Parse error. Reconsume the character in the before attribute
1095 name state. */
1096 $this->emitToken(array(
1097 'type' => self::PARSEERROR,
1098 'data' => 'unexpected-character-after-attribute-value'
1099 ));
1100 $this->stream->unget();
1101 $state = 'before attribute name';
1102 }
1103 break;
1104
1105 case 'self-closing start tag':
1106 /* Consume the next input character: */
1107 $char = $this->stream->char();
1108
1109 if ($char === '>') {
1110 /* U+003E GREATER-THAN SIGN (>)
1111 Set the self-closing flag of the current tag token.
1112 Emit the current tag token. Switch to the data state. */
1113 // not sure if this is the name we want
1114 $this->token['self-closing'] = true;
1115 $this->emitToken($this->token);
1116 $state = 'data';
1117
1118 } elseif ($char === false) {
1119 /* EOF
1120 Parse error. Reconsume the EOF character in the data state. */
1121 $this->emitToken(array(
1122 'type' => self::PARSEERROR,
1123 'data' => 'unexpected-eof-after-self-closing'
1124 ));
1125 $this->stream->unget();
1126 $state = 'data';
1127
1128 } else {
1129 /* Anything else
1130 Parse error. Reconsume the character in the before attribute name state. */
1131 $this->emitToken(array(
1132 'type' => self::PARSEERROR,
1133 'data' => 'unexpected-character-after-self-closing'
1134 ));
1135 $this->stream->unget();
1136 $state = 'before attribute name';
1137 }
1138 break;
1139
1140 case 'bogus comment':
1141 /* (This can only happen if the content model flag is set to the PCDATA state.) */
1142 /* Consume every character up to the first U+003E GREATER-THAN SIGN
1143 character (>) or the end of the file (EOF), whichever comes first. Emit
1144 a comment token whose data is the concatenation of all the characters
1145 starting from and including the character that caused the state machine
1146 to switch into the bogus comment state, up to and including the last
1147 consumed character before the U+003E character, if any, or up to the
1148 end of the file otherwise. (If the comment was started by the end of
1149 the file (EOF), the token is empty.) */
1150 $this->token['data'] .= (string) $this->stream->charsUntil('>');
1151 $this->stream->char();
1152
1153 $this->emitToken($this->token);
1154
1155 /* Switch to the data state. */
1156 $state = 'data';
1157 break;
1158
1159 case 'markup declaration open':
1160 // Consume for below
1161 $hyphens = $this->stream->charsWhile('-', 2);
1162 if ($hyphens === '-') {
1163 $this->stream->unget();
1164 }
1165 if ($hyphens !== '--') {
1166 $alpha = $this->stream->charsWhile(self::ALPHA, 7);
1167 }
1168
1169 /* If the next two characters are both U+002D HYPHEN-MINUS (-)
1170 characters, consume those two characters, create a comment token whose
1171 data is the empty string, and switch to the comment state. */
1172 if($hyphens === '--') {
1173 $state = 'comment start';
1174 $this->token = array(
1175 'data' => '',
1176 'type' => self::COMMENT
1177 );
1178
1179 /* Otherwise if the next seven characters are a case-insensitive match
1180 for the word "DOCTYPE", then consume those characters and switch to the
1181 DOCTYPE state. */
1182 } elseif(strtoupper($alpha) === 'DOCTYPE') {
1183 $state = 'DOCTYPE';
1184
1185 // XXX not implemented
1186 /* Otherwise, if the insertion mode is "in foreign content"
1187 and the current node is not an element in the HTML namespace
1188 and the next seven characters are an ASCII case-sensitive
1189 match for the string "[CDATA[" (the five uppercase letters
1190 "CDATA" with a U+005B LEFT SQUARE BRACKET character before
1191 and after), then consume those characters and switch to the
1192 CDATA section state (which is unrelated to the content model
1193 flag's CDATA state). */
1194
1195 /* Otherwise, is is a parse error. Switch to the bogus comment state.
1196 The next character that is consumed, if any, is the first character
1197 that will be in the comment. */
1198 } else {
1199 $this->emitToken(array(
1200 'type' => self::PARSEERROR,
1201 'data' => 'expected-dashes-or-doctype'
1202 ));
1203 $this->token = array(
1204 'data' => (string) $alpha,
1205 'type' => self::COMMENT
1206 );
1207 $state = 'bogus comment';
1208 }
1209 break;
1210
1211 case 'comment start':
1212 /* Consume the next input character: */
1213 $char = $this->stream->char();
1214
1215 if ($char === '-') {
1216 /* U+002D HYPHEN-MINUS (-)
1217 Switch to the comment start dash state. */
1218 $state = 'comment start dash';
1219 } elseif ($char === '>') {
1220 /* U+003E GREATER-THAN SIGN (>)
1221 Parse error. Emit the comment token. Switch to the
1222 data state. */
1223 $this->emitToken(array(
1224 'type' => self::PARSEERROR,
1225 'data' => 'incorrect-comment'
1226 ));
1227 $this->emitToken($this->token);
1228 $state = 'data';
1229 } elseif ($char === false) {
1230 /* EOF
1231 Parse error. Emit the comment token. Reconsume the
1232 EOF character in the data state. */
1233 $this->emitToken(array(
1234 'type' => self::PARSEERROR,
1235 'data' => 'eof-in-comment'
1236 ));
1237 $this->emitToken($this->token);
1238 $this->stream->unget();
1239 $state = 'data';
1240 } else {
1241 /* Anything else
1242 Append the input character to the comment token's
1243 data. Switch to the comment state. */
1244 $this->token['data'] .= $char;
1245 $state = 'comment';
1246 }
1247 break;
1248
1249 case 'comment start dash':
1250 /* Consume the next input character: */
1251 $char = $this->stream->char();
1252 if ($char === '-') {
1253 /* U+002D HYPHEN-MINUS (-)
1254 Switch to the comment end state */
1255 $state = 'comment end';
1256 } elseif ($char === '>') {
1257 /* U+003E GREATER-THAN SIGN (>)
1258 Parse error. Emit the comment token. Switch to the
1259 data state. */
1260 $this->emitToken(array(
1261 'type' => self::PARSEERROR,
1262 'data' => 'incorrect-comment'
1263 ));
1264 $this->emitToken($this->token);
1265 $state = 'data';
1266 } elseif ($char === false) {
1267 /* Parse error. Emit the comment token. Reconsume the
1268 EOF character in the data state. */
1269 $this->emitToken(array(
1270 'type' => self::PARSEERROR,
1271 'data' => 'eof-in-comment'
1272 ));
1273 $this->emitToken($this->token);
1274 $this->stream->unget();
1275 $state = 'data';
1276 } else {
1277 $this->token['data'] .= '-' . $char;
1278 $state = 'comment';
1279 }
1280 break;
1281
1282 case 'comment':
1283 /* Consume the next input character: */
1284 $char = $this->stream->char();
1285
1286 if($char === '-') {
1287 /* U+002D HYPHEN-MINUS (-)
1288 Switch to the comment end dash state */
1289 $state = 'comment end dash';
1290
1291 } elseif($char === false) {
1292 /* EOF
1293 Parse error. Emit the comment token. Reconsume the EOF character
1294 in the data state. */
1295 $this->emitToken(array(
1296 'type' => self::PARSEERROR,
1297 'data' => 'eof-in-comment'
1298 ));
1299 $this->emitToken($this->token);
1300 $this->stream->unget();
1301 $state = 'data';
1302
1303 } else {
1304 /* Anything else
1305 Append the input character to the comment token's data. Stay in
1306 the comment state. */
1307 $chars = $this->stream->charsUntil('-');
1308
1309 $this->token['data'] .= $char . $chars;
1310 }
1311 break;
1312
1313 case 'comment end dash':
1314 /* Consume the next input character: */
1315 $char = $this->stream->char();
1316
1317 if($char === '-') {
1318 /* U+002D HYPHEN-MINUS (-)
1319 Switch to the comment end state */
1320 $state = 'comment end';
1321
1322 } elseif($char === false) {
1323 /* EOF
1324 Parse error. Emit the comment token. Reconsume the EOF character
1325 in the data state. */
1326 $this->emitToken(array(
1327 'type' => self::PARSEERROR,
1328 'data' => 'eof-in-comment-end-dash'
1329 ));
1330 $this->emitToken($this->token);
1331 $this->stream->unget();
1332 $state = 'data';
1333
1334 } else {
1335 /* Anything else
1336 Append a U+002D HYPHEN-MINUS (-) character and the input
1337 character to the comment token's data. Switch to the comment state. */
1338 $this->token['data'] .= '-'.$char;
1339 $state = 'comment';
1340 }
1341 break;
1342
1343 case 'comment end':
1344 /* Consume the next input character: */
1345 $char = $this->stream->char();
1346
1347 if($char === '>') {
1348 /* U+003E GREATER-THAN SIGN (>)
1349 Emit the comment token. Switch to the data state. */
1350 $this->emitToken($this->token);
1351 $state = 'data';
1352
1353 } elseif($char === '-') {
1354 /* U+002D HYPHEN-MINUS (-)
1355 Parse error. Append a U+002D HYPHEN-MINUS (-) character
1356 to the comment token's data. Stay in the comment end
1357 state. */
1358 $this->emitToken(array(
1359 'type' => self::PARSEERROR,
1360 'data' => 'unexpected-dash-after-double-dash-in-comment'
1361 ));
1362 $this->token['data'] .= '-';
1363
1364 } elseif($char === "\t" || $char === "\n" || $char === "\x0a" || $char === ' ') {
1365 $this->emitToken(array(
1366 'type' => self::PARSEERROR,
1367 'data' => 'unexpected-space-after-double-dash-in-comment'
1368 ));
1369 $this->token['data'] .= '--' . $char;
1370 $state = 'comment end space';
1371
1372 } elseif($char === '!') {
1373 $this->emitToken(array(
1374 'type' => self::PARSEERROR,
1375 'data' => 'unexpected-bang-after-double-dash-in-comment'
1376 ));
1377 $state = 'comment end bang';
1378
1379 } elseif($char === false) {
1380 /* EOF
1381 Parse error. Emit the comment token. Reconsume the
1382 EOF character in the data state. */
1383 $this->emitToken(array(
1384 'type' => self::PARSEERROR,
1385 'data' => 'eof-in-comment-double-dash'
1386 ));
1387 $this->emitToken($this->token);
1388 $this->stream->unget();
1389 $state = 'data';
1390
1391 } else {
1392 /* Anything else
1393 Parse error. Append two U+002D HYPHEN-MINUS (-)
1394 characters and the input character to the comment token's
1395 data. Switch to the comment state. */
1396 $this->emitToken(array(
1397 'type' => self::PARSEERROR,
1398 'data' => 'unexpected-char-in-comment'
1399 ));
1400 $this->token['data'] .= '--'.$char;
1401 $state = 'comment';
1402 }
1403 break;
1404
1405 case 'comment end bang':
1406 $char = $this->stream->char();
1407 if ($char === '>') {
1408 $this->emitToken($this->token);
1409 $state = 'data';
1410 } elseif ($char === "-") {
1411 $this->token['data'] .= '--!';
1412 $state = 'comment end dash';
1413 } elseif ($char === false) {
1414 $this->emitToken(array(
1415 'type' => self::PARSEERROR,
1416 'data' => 'eof-in-comment-end-bang'
1417 ));
1418 $this->emitToken($this->token);
1419 $this->stream->unget();
1420 $state = 'data';
1421 } else {
1422 $this->token['data'] .= '--!' . $char;
1423 $state = 'comment';
1424 }
1425 break;
1426
1427 case 'comment end space':
1428 $char = $this->stream->char();
1429 if ($char === '>') {
1430 $this->emitToken($this->token);
1431 $state = 'data';
1432 } elseif ($char === '-') {
1433 $state = 'comment end dash';
1434 } elseif ($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
1435 $this->token['data'] .= $char;
1436 } elseif ($char === false) {
1437 $this->emitToken(array(
1438 'type' => self::PARSEERROR,
1439 'data' => 'unexpected-eof-in-comment-end-space',
1440 ));
1441 $this->emitToken($this->token);
1442 $this->stream->unget();
1443 $state = 'data';
1444 } else {
1445 $this->token['data'] .= $char;
1446 $state = 'comment';
1447 }
1448 break;
1449
1450 case 'DOCTYPE':
1451 /* Consume the next input character: */
1452 $char = $this->stream->char();
1453
1454 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
1455 /* U+0009 CHARACTER TABULATION
1456 U+000A LINE FEED (LF)
1457 U+000C FORM FEED (FF)
1458 U+0020 SPACE
1459 Switch to the before DOCTYPE name state. */
1460 $state = 'before DOCTYPE name';
1461
1462 } elseif($char === false) {
1463 /* EOF
1464 Parse error. Create a new DOCTYPE token. Set its
1465 force-quirks flag to on. Emit the token. Reconsume the
1466 EOF character in the data state. */
1467 $this->emitToken(array(
1468 'type' => self::PARSEERROR,
1469 'data' => 'need-space-after-doctype-but-got-eof'
1470 ));
1471 $this->emitToken(array(
1472 'name' => '',
1473 'type' => self::DOCTYPE,
1474 'force-quirks' => true,
1475 'error' => true
1476 ));
1477 $this->stream->unget();
1478 $state = 'data';
1479
1480 } else {
1481 /* Anything else
1482 Parse error. Reconsume the current character in the
1483 before DOCTYPE name state. */
1484 $this->emitToken(array(
1485 'type' => self::PARSEERROR,
1486 'data' => 'need-space-after-doctype'
1487 ));
1488 $this->stream->unget();
1489 $state = 'before DOCTYPE name';
1490 }
1491 break;
1492
1493 case 'before DOCTYPE name':
1494 /* Consume the next input character: */
1495 $char = $this->stream->char();
1496
1497 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
1498 /* U+0009 CHARACTER TABULATION
1499 U+000A LINE FEED (LF)
1500 U+000C FORM FEED (FF)
1501 U+0020 SPACE
1502 Stay in the before DOCTYPE name state. */
1503
1504 } elseif($char === '>') {
1505 /* U+003E GREATER-THAN SIGN (>)
1506 Parse error. Create a new DOCTYPE token. Set its
1507 force-quirks flag to on. Emit the token. Switch to the
1508 data state. */
1509 $this->emitToken(array(
1510 'type' => self::PARSEERROR,
1511 'data' => 'expected-doctype-name-but-got-right-bracket'
1512 ));
1513 $this->emitToken(array(
1514 'name' => '',
1515 'type' => self::DOCTYPE,
1516 'force-quirks' => true,
1517 'error' => true
1518 ));
1519
1520 $state = 'data';
1521
1522 } elseif('A' <= $char && $char <= 'Z') {
1523 /* U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
1524 Create a new DOCTYPE token. Set the token's name to the
1525 lowercase version of the input character (add 0x0020 to
1526 the character's code point). Switch to the DOCTYPE name
1527 state. */
1528 $this->token = array(
1529 'name' => strtolower($char),
1530 'type' => self::DOCTYPE,
1531 'error' => true
1532 );
1533
1534 $state = 'DOCTYPE name';
1535
1536 } elseif($char === false) {
1537 /* EOF
1538 Parse error. Create a new DOCTYPE token. Set its
1539 force-quirks flag to on. Emit the token. Reconsume the
1540 EOF character in the data state. */
1541 $this->emitToken(array(
1542 'type' => self::PARSEERROR,
1543 'data' => 'expected-doctype-name-but-got-eof'
1544 ));
1545 $this->emitToken(array(
1546 'name' => '',
1547 'type' => self::DOCTYPE,
1548 'force-quirks' => true,
1549 'error' => true
1550 ));
1551
1552 $this->stream->unget();
1553 $state = 'data';
1554
1555 } else {
1556 /* Anything else
1557 Create a new DOCTYPE token. Set the token's name to the
1558 current input character. Switch to the DOCTYPE name state. */
1559 $this->token = array(
1560 'name' => $char,
1561 'type' => self::DOCTYPE,
1562 'error' => true
1563 );
1564
1565 $state = 'DOCTYPE name';
1566 }
1567 break;
1568
1569 case 'DOCTYPE name':
1570 /* Consume the next input character: */
1571 $char = $this->stream->char();
1572
1573 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
1574 /* U+0009 CHARACTER TABULATION
1575 U+000A LINE FEED (LF)
1576 U+000C FORM FEED (FF)
1577 U+0020 SPACE
1578 Switch to the after DOCTYPE name state. */
1579 $state = 'after DOCTYPE name';
1580
1581 } elseif($char === '>') {
1582 /* U+003E GREATER-THAN SIGN (>)
1583 Emit the current DOCTYPE token. Switch to the data state. */
1584 $this->emitToken($this->token);
1585 $state = 'data';
1586
1587 } elseif('A' <= $char && $char <= 'Z') {
1588 /* U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z
1589 Append the lowercase version of the input character
1590 (add 0x0020 to the character's code point) to the current
1591 DOCTYPE token's name. Stay in the DOCTYPE name state. */
1592 $this->token['name'] .= strtolower($char);
1593
1594 } elseif($char === false) {
1595 /* EOF
1596 Parse error. Set the DOCTYPE token's force-quirks flag
1597 to on. Emit that DOCTYPE token. Reconsume the EOF
1598 character in the data state. */
1599 $this->emitToken(array(
1600 'type' => self::PARSEERROR,
1601 'data' => 'eof-in-doctype-name'
1602 ));
1603 $this->token['force-quirks'] = true;
1604 $this->emitToken($this->token);
1605 $this->stream->unget();
1606 $state = 'data';
1607
1608 } else {
1609 /* Anything else
1610 Append the current input character to the current
1611 DOCTYPE token's name. Stay in the DOCTYPE name state. */
1612 $this->token['name'] .= $char;
1613 }
1614
1615 // XXX this is probably some sort of quirks mode designation,
1616 // check tree-builder to be sure. In general 'error' needs
1617 // to be specc'ified, this probably means removing it at the end
1618 $this->token['error'] = ($this->token['name'] === 'HTML')
1619 ? false
1620 : true;
1621 break;
1622
1623 case 'after DOCTYPE name':
1624 /* Consume the next input character: */
1625 $char = $this->stream->char();
1626
1627 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
1628 /* U+0009 CHARACTER TABULATION
1629 U+000A LINE FEED (LF)
1630 U+000C FORM FEED (FF)
1631 U+0020 SPACE
1632 Stay in the after DOCTYPE name state. */
1633
1634 } elseif($char === '>') {
1635 /* U+003E GREATER-THAN SIGN (>)
1636 Emit the current DOCTYPE token. Switch to the data state. */
1637 $this->emitToken($this->token);
1638 $state = 'data';
1639
1640 } elseif($char === false) {
1641 /* EOF
1642 Parse error. Set the DOCTYPE token's force-quirks flag
1643 to on. Emit that DOCTYPE token. Reconsume the EOF
1644 character in the data state. */
1645 $this->emitToken(array(
1646 'type' => self::PARSEERROR,
1647 'data' => 'eof-in-doctype'
1648 ));
1649 $this->token['force-quirks'] = true;
1650 $this->emitToken($this->token);
1651 $this->stream->unget();
1652 $state = 'data';
1653
1654 } else {
1655 /* Anything else */
1656
1657 $nextSix = strtoupper($char . $this->stream->charsWhile(self::ALPHA, 5));
1658 if ($nextSix === 'PUBLIC') {
1659 /* If the next six characters are an ASCII
1660 case-insensitive match for the word "PUBLIC", then
1661 consume those characters and switch to the before
1662 DOCTYPE public identifier state. */
1663 $state = 'before DOCTYPE public identifier';
1664
1665 } elseif ($nextSix === 'SYSTEM') {
1666 /* Otherwise, if the next six characters are an ASCII
1667 case-insensitive match for the word "SYSTEM", then
1668 consume those characters and switch to the before
1669 DOCTYPE system identifier state. */
1670 $state = 'before DOCTYPE system identifier';
1671
1672 } else {
1673 /* Otherwise, this is the parse error. Set the DOCTYPE
1674 token's force-quirks flag to on. Switch to the bogus
1675 DOCTYPE state. */
1676 $this->emitToken(array(
1677 'type' => self::PARSEERROR,
1678 'data' => 'expected-space-or-right-bracket-in-doctype'
1679 ));
1680 $this->token['force-quirks'] = true;
1681 $this->token['error'] = true;
1682 $state = 'bogus DOCTYPE';
1683 }
1684 }
1685 break;
1686
1687 case 'before DOCTYPE public identifier':
1688 /* Consume the next input character: */
1689 $char = $this->stream->char();
1690
1691 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
1692 /* U+0009 CHARACTER TABULATION
1693 U+000A LINE FEED (LF)
1694 U+000C FORM FEED (FF)
1695 U+0020 SPACE
1696 Stay in the before DOCTYPE public identifier state. */
1697 } elseif ($char === '"') {
1698 /* U+0022 QUOTATION MARK (")
1699 Set the DOCTYPE token's public identifier to the empty
1700 string (not missing), then switch to the DOCTYPE public
1701 identifier (double-quoted) state. */
1702 $this->token['public'] = '';
1703 $state = 'DOCTYPE public identifier (double-quoted)';
1704 } elseif ($char === "'") {
1705 /* U+0027 APOSTROPHE (')
1706 Set the DOCTYPE token's public identifier to the empty
1707 string (not missing), then switch to the DOCTYPE public
1708 identifier (single-quoted) state. */
1709 $this->token['public'] = '';
1710 $state = 'DOCTYPE public identifier (single-quoted)';
1711 } elseif ($char === '>') {
1712 /* Parse error. Set the DOCTYPE token's force-quirks flag
1713 to on. Emit that DOCTYPE token. Switch to the data state. */
1714 $this->emitToken(array(
1715 'type' => self::PARSEERROR,
1716 'data' => 'unexpected-end-of-doctype'
1717 ));
1718 $this->token['force-quirks'] = true;
1719 $this->emitToken($this->token);
1720 $state = 'data';
1721 } elseif ($char === false) {
1722 /* Parse error. Set the DOCTYPE token's force-quirks
1723 flag to on. Emit that DOCTYPE token. Reconsume the EOF
1724 character in the data state. */
1725 $this->emitToken(array(
1726 'type' => self::PARSEERROR,
1727 'data' => 'eof-in-doctype'
1728 ));
1729 $this->token['force-quirks'] = true;
1730 $this->emitToken($this->token);
1731 $this->stream->unget();
1732 $state = 'data';
1733 } else {
1734 /* Parse error. Set the DOCTYPE token's force-quirks flag
1735 to on. Switch to the bogus DOCTYPE state. */
1736 $this->emitToken(array(
1737 'type' => self::PARSEERROR,
1738 'data' => 'unexpected-char-in-doctype'
1739 ));
1740 $this->token['force-quirks'] = true;
1741 $state = 'bogus DOCTYPE';
1742 }
1743 break;
1744
1745 case 'DOCTYPE public identifier (double-quoted)':
1746 /* Consume the next input character: */
1747 $char = $this->stream->char();
1748
1749 if ($char === '"') {
1750 /* U+0022 QUOTATION MARK (")
1751 Switch to the after DOCTYPE public identifier state. */
1752 $state = 'after DOCTYPE public identifier';
1753 } elseif ($char === '>') {
1754 /* U+003E GREATER-THAN SIGN (>)
1755 Parse error. Set the DOCTYPE token's force-quirks flag
1756 to on. Emit that DOCTYPE token. Switch to the data state. */
1757 $this->emitToken(array(
1758 'type' => self::PARSEERROR,
1759 'data' => 'unexpected-end-of-doctype'
1760 ));
1761 $this->token['force-quirks'] = true;
1762 $this->emitToken($this->token);
1763 $state = 'data';
1764 } elseif ($char === false) {
1765 /* EOF
1766 Parse error. Set the DOCTYPE token's force-quirks flag
1767 to on. Emit that DOCTYPE token. Reconsume the EOF
1768 character in the data state. */
1769 $this->emitToken(array(
1770 'type' => self::PARSEERROR,
1771 'data' => 'eof-in-doctype'
1772 ));
1773 $this->token['force-quirks'] = true;
1774 $this->emitToken($this->token);
1775 $this->stream->unget();
1776 $state = 'data';
1777 } else {
1778 /* Anything else
1779 Append the current input character to the current
1780 DOCTYPE token's public identifier. Stay in the DOCTYPE
1781 public identifier (double-quoted) state. */
1782 $this->token['public'] .= $char;
1783 }
1784 break;
1785
1786 case 'DOCTYPE public identifier (single-quoted)':
1787 /* Consume the next input character: */
1788 $char = $this->stream->char();
1789
1790 if ($char === "'") {
1791 /* U+0027 APOSTROPHE (')
1792 Switch to the after DOCTYPE public identifier state. */
1793 $state = 'after DOCTYPE public identifier';
1794 } elseif ($char === '>') {
1795 /* U+003E GREATER-THAN SIGN (>)
1796 Parse error. Set the DOCTYPE token's force-quirks flag
1797 to on. Emit that DOCTYPE token. Switch to the data state. */
1798 $this->emitToken(array(
1799 'type' => self::PARSEERROR,
1800 'data' => 'unexpected-end-of-doctype'
1801 ));
1802 $this->token['force-quirks'] = true;
1803 $this->emitToken($this->token);
1804 $state = 'data';
1805 } elseif ($char === false) {
1806 /* EOF
1807 Parse error. Set the DOCTYPE token's force-quirks flag
1808 to on. Emit that DOCTYPE token. Reconsume the EOF
1809 character in the data state. */
1810 $this->emitToken(array(
1811 'type' => self::PARSEERROR,
1812 'data' => 'eof-in-doctype'
1813 ));
1814 $this->token['force-quirks'] = true;
1815 $this->emitToken($this->token);
1816 $this->stream->unget();
1817 $state = 'data';
1818 } else {
1819 /* Anything else
1820 Append the current input character to the current
1821 DOCTYPE token's public identifier. Stay in the DOCTYPE
1822 public identifier (double-quoted) state. */
1823 $this->token['public'] .= $char;
1824 }
1825 break;
1826
1827 case 'after DOCTYPE public identifier':
1828 /* Consume the next input character: */
1829 $char = $this->stream->char();
1830
1831 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
1832 /* U+0009 CHARACTER TABULATION
1833 U+000A LINE FEED (LF)
1834 U+000C FORM FEED (FF)
1835 U+0020 SPACE
1836 Stay in the after DOCTYPE public identifier state. */
1837 } elseif ($char === '"') {
1838 /* U+0022 QUOTATION MARK (")
1839 Set the DOCTYPE token's system identifier to the
1840 empty string (not missing), then switch to the DOCTYPE
1841 system identifier (double-quoted) state. */
1842 $this->token['system'] = '';
1843 $state = 'DOCTYPE system identifier (double-quoted)';
1844 } elseif ($char === "'") {
1845 /* U+0027 APOSTROPHE (')
1846 Set the DOCTYPE token's system identifier to the
1847 empty string (not missing), then switch to the DOCTYPE
1848 system identifier (single-quoted) state. */
1849 $this->token['system'] = '';
1850 $state = 'DOCTYPE system identifier (single-quoted)';
1851 } elseif ($char === '>') {
1852 /* U+003E GREATER-THAN SIGN (>)
1853 Emit the current DOCTYPE token. Switch to the data state. */
1854 $this->emitToken($this->token);
1855 $state = 'data';
1856 } elseif ($char === false) {
1857 /* Parse error. Set the DOCTYPE token's force-quirks
1858 flag to on. Emit that DOCTYPE token. Reconsume the EOF
1859 character in the data state. */
1860 $this->emitToken(array(
1861 'type' => self::PARSEERROR,
1862 'data' => 'eof-in-doctype'
1863 ));
1864 $this->token['force-quirks'] = true;
1865 $this->emitToken($this->token);
1866 $this->stream->unget();
1867 $state = 'data';
1868 } else {
1869 /* Anything else
1870 Parse error. Set the DOCTYPE token's force-quirks flag
1871 to on. Switch to the bogus DOCTYPE state. */
1872 $this->emitToken(array(
1873 'type' => self::PARSEERROR,
1874 'data' => 'unexpected-char-in-doctype'
1875 ));
1876 $this->token['force-quirks'] = true;
1877 $state = 'bogus DOCTYPE';
1878 }
1879 break;
1880
1881 case 'before DOCTYPE system identifier':
1882 /* Consume the next input character: */
1883 $char = $this->stream->char();
1884
1885 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
1886 /* U+0009 CHARACTER TABULATION
1887 U+000A LINE FEED (LF)
1888 U+000C FORM FEED (FF)
1889 U+0020 SPACE
1890 Stay in the before DOCTYPE system identifier state. */
1891 } elseif ($char === '"') {
1892 /* U+0022 QUOTATION MARK (")
1893 Set the DOCTYPE token's system identifier to the empty
1894 string (not missing), then switch to the DOCTYPE system
1895 identifier (double-quoted) state. */
1896 $this->token['system'] = '';
1897 $state = 'DOCTYPE system identifier (double-quoted)';
1898 } elseif ($char === "'") {
1899 /* U+0027 APOSTROPHE (')
1900 Set the DOCTYPE token's system identifier to the empty
1901 string (not missing), then switch to the DOCTYPE system
1902 identifier (single-quoted) state. */
1903 $this->token['system'] = '';
1904 $state = 'DOCTYPE system identifier (single-quoted)';
1905 } elseif ($char === '>') {
1906 /* Parse error. Set the DOCTYPE token's force-quirks flag
1907 to on. Emit that DOCTYPE token. Switch to the data state. */
1908 $this->emitToken(array(
1909 'type' => self::PARSEERROR,
1910 'data' => 'unexpected-char-in-doctype'
1911 ));
1912 $this->token['force-quirks'] = true;
1913 $this->emitToken($this->token);
1914 $state = 'data';
1915 } elseif ($char === false) {
1916 /* Parse error. Set the DOCTYPE token's force-quirks
1917 flag to on. Emit that DOCTYPE token. Reconsume the EOF
1918 character in the data state. */
1919 $this->emitToken(array(
1920 'type' => self::PARSEERROR,
1921 'data' => 'eof-in-doctype'
1922 ));
1923 $this->token['force-quirks'] = true;
1924 $this->emitToken($this->token);
1925 $this->stream->unget();
1926 $state = 'data';
1927 } else {
1928 /* Parse error. Set the DOCTYPE token's force-quirks flag
1929 to on. Switch to the bogus DOCTYPE state. */
1930 $this->emitToken(array(
1931 'type' => self::PARSEERROR,
1932 'data' => 'unexpected-char-in-doctype'
1933 ));
1934 $this->token['force-quirks'] = true;
1935 $state = 'bogus DOCTYPE';
1936 }
1937 break;
1938
1939 case 'DOCTYPE system identifier (double-quoted)':
1940 /* Consume the next input character: */
1941 $char = $this->stream->char();
1942
1943 if ($char === '"') {
1944 /* U+0022 QUOTATION MARK (")
1945 Switch to the after DOCTYPE system identifier state. */
1946 $state = 'after DOCTYPE system identifier';
1947 } elseif ($char === '>') {
1948 /* U+003E GREATER-THAN SIGN (>)
1949 Parse error. Set the DOCTYPE token's force-quirks flag
1950 to on. Emit that DOCTYPE token. Switch to the data state. */
1951 $this->emitToken(array(
1952 'type' => self::PARSEERROR,
1953 'data' => 'unexpected-end-of-doctype'
1954 ));
1955 $this->token['force-quirks'] = true;
1956 $this->emitToken($this->token);
1957 $state = 'data';
1958 } elseif ($char === false) {
1959 /* EOF
1960 Parse error. Set the DOCTYPE token's force-quirks flag
1961 to on. Emit that DOCTYPE token. Reconsume the EOF
1962 character in the data state. */
1963 $this->emitToken(array(
1964 'type' => self::PARSEERROR,
1965 'data' => 'eof-in-doctype'
1966 ));
1967 $this->token['force-quirks'] = true;
1968 $this->emitToken($this->token);
1969 $this->stream->unget();
1970 $state = 'data';
1971 } else {
1972 /* Anything else
1973 Append the current input character to the current
1974 DOCTYPE token's system identifier. Stay in the DOCTYPE
1975 system identifier (double-quoted) state. */
1976 $this->token['system'] .= $char;
1977 }
1978 break;
1979
1980 case 'DOCTYPE system identifier (single-quoted)':
1981 /* Consume the next input character: */
1982 $char = $this->stream->char();
1983
1984 if ($char === "'") {
1985 /* U+0027 APOSTROPHE (')
1986 Switch to the after DOCTYPE system identifier state. */
1987 $state = 'after DOCTYPE system identifier';
1988 } elseif ($char === '>') {
1989 /* U+003E GREATER-THAN SIGN (>)
1990 Parse error. Set the DOCTYPE token's force-quirks flag
1991 to on. Emit that DOCTYPE token. Switch to the data state. */
1992 $this->emitToken(array(
1993 'type' => self::PARSEERROR,
1994 'data' => 'unexpected-end-of-doctype'
1995 ));
1996 $this->token['force-quirks'] = true;
1997 $this->emitToken($this->token);
1998 $state = 'data';
1999 } elseif ($char === false) {
2000 /* EOF
2001 Parse error. Set the DOCTYPE token's force-quirks flag
2002 to on. Emit that DOCTYPE token. Reconsume the EOF
2003 character in the data state. */
2004 $this->emitToken(array(
2005 'type' => self::PARSEERROR,
2006 'data' => 'eof-in-doctype'
2007 ));
2008 $this->token['force-quirks'] = true;
2009 $this->emitToken($this->token);
2010 $this->stream->unget();
2011 $state = 'data';
2012 } else {
2013 /* Anything else
2014 Append the current input character to the current
2015 DOCTYPE token's system identifier. Stay in the DOCTYPE
2016 system identifier (double-quoted) state. */
2017 $this->token['system'] .= $char;
2018 }
2019 break;
2020
2021 case 'after DOCTYPE system identifier':
2022 /* Consume the next input character: */
2023 $char = $this->stream->char();
2024
2025 if($char === "\t" || $char === "\n" || $char === "\x0c" || $char === ' ') {
2026 /* U+0009 CHARACTER TABULATION
2027 U+000A LINE FEED (LF)
2028 U+000C FORM FEED (FF)
2029 U+0020 SPACE
2030 Stay in the after DOCTYPE system identifier state. */
2031 } elseif ($char === '>') {
2032 /* U+003E GREATER-THAN SIGN (>)
2033 Emit the current DOCTYPE token. Switch to the data state. */
2034 $this->emitToken($this->token);
2035 $state = 'data';
2036 } elseif ($char === false) {
2037 /* Parse error. Set the DOCTYPE token's force-quirks
2038 flag to on. Emit that DOCTYPE token. Reconsume the EOF
2039 character in the data state. */
2040 $this->emitToken(array(
2041 'type' => self::PARSEERROR,
2042 'data' => 'eof-in-doctype'
2043 ));
2044 $this->token['force-quirks'] = true;
2045 $this->emitToken($this->token);
2046 $this->stream->unget();
2047 $state = 'data';
2048 } else {
2049 /* Anything else
2050 Parse error. Switch to the bogus DOCTYPE state.
2051 (This does not set the DOCTYPE token's force-quirks
2052 flag to on.) */
2053 $this->emitToken(array(
2054 'type' => self::PARSEERROR,
2055 'data' => 'unexpected-char-in-doctype'
2056 ));
2057 $state = 'bogus DOCTYPE';
2058 }
2059 break;
2060
2061 case 'bogus DOCTYPE':
2062 /* Consume the next input character: */
2063 $char = $this->stream->char();
2064
2065 if ($char === '>') {
2066 /* U+003E GREATER-THAN SIGN (>)
2067 Emit the DOCTYPE token. Switch to the data state. */
2068 $this->emitToken($this->token);
2069 $state = 'data';
2070
2071 } elseif($char === false) {
2072 /* EOF
2073 Emit the DOCTYPE token. Reconsume the EOF character in
2074 the data state. */
2075 $this->emitToken($this->token);
2076 $this->stream->unget();
2077 $state = 'data';
2078
2079 } else {
2080 /* Anything else
2081 Stay in the bogus DOCTYPE state. */
2082 }
2083 break;
2084
2085 // case 'cdataSection':
2086
2087 }
2088 }
2089 }
2090
2091 /**
2092 * Returns a serialized representation of the tree.
2093 */
2094 public function save() {
2095 return $this->tree->save();
2096 }
2097
2098 /**
2099 * Returns the input stream.
2100 */
2101 public function stream() {
2102 return $this->stream;
2103 }
2104
2105 private function consumeCharacterReference($allowed = false, $inattr = false) {
2106 // This goes quite far against spec, and is far closer to the Python
2107 // impl., mainly because we don't do the large unconsuming the spec
2108 // requires.
2109
2110 // All consumed characters.
2111 $chars = $this->stream->char();
2112
2113 /* This section defines how to consume a character
2114 reference. This definition is used when parsing character
2115 references in text and in attributes.
2116
2117 The behavior depends on the identity of the next character
2118 (the one immediately after the U+0026 AMPERSAND character): */
2119
2120 if (
2121 $chars[0] === "\x09" ||
2122 $chars[0] === "\x0A" ||
2123 $chars[0] === "\x0C" ||
2124 $chars[0] === "\x20" ||
2125 $chars[0] === '<' ||
2126 $chars[0] === '&' ||
2127 $chars === false ||
2128 $chars[0] === $allowed
2129 ) {
2130 /* U+0009 CHARACTER TABULATION
2131 U+000A LINE FEED (LF)
2132 U+000C FORM FEED (FF)
2133 U+0020 SPACE
2134 U+003C LESS-THAN SIGN
2135 U+0026 AMPERSAND
2136 EOF
2137 The additional allowed character, if there is one
2138 Not a character reference. No characters are consumed,
2139 and nothing is returned. (This is not an error, either.) */
2140 // We already consumed, so unconsume.
2141 $this->stream->unget();
2142 return '&';
2143 } elseif ($chars[0] === '#') {
2144 /* Consume the U+0023 NUMBER SIGN. */
2145 // Um, yeah, we already did that.
2146 /* The behavior further depends on the character after
2147 the U+0023 NUMBER SIGN: */
2148 $chars .= $this->stream->char();
2149 if (isset($chars[1]) && ($chars[1] === 'x' || $chars[1] === 'X')) {
2150 /* U+0078 LATIN SMALL LETTER X
2151 U+0058 LATIN CAPITAL LETTER X */
2152 /* Consume the X. */
2153 // Um, yeah, we already did that.
2154 /* Follow the steps below, but using the range of
2155 characters U+0030 DIGIT ZERO through to U+0039 DIGIT
2156 NINE, U+0061 LATIN SMALL LETTER A through to U+0066
2157 LATIN SMALL LETTER F, and U+0041 LATIN CAPITAL LETTER
2158 A, through to U+0046 LATIN CAPITAL LETTER F (in other
2159 words, 0123456789, ABCDEF, abcdef). */
2160 $char_class = self::HEX;
2161 /* When it comes to interpreting the
2162 number, interpret it as a hexadecimal number. */
2163 $hex = true;
2164 } else {
2165 /* Anything else */
2166 // Unconsume because we shouldn't have consumed this.
2167 $chars = $chars[0];
2168 $this->stream->unget();
2169 /* Follow the steps below, but using the range of
2170 characters U+0030 DIGIT ZERO through to U+0039 DIGIT
2171 NINE (i.e. just 0123456789). */
2172 $char_class = self::DIGIT;
2173 /* When it comes to interpreting the number,
2174 interpret it as a decimal number. */
2175 $hex = false;
2176 }
2177
2178 /* Consume as many characters as match the range of characters given above. */
2179 $consumed = $this->stream->charsWhile($char_class);
2180 if ($consumed === '' || $consumed === false) {
2181 /* If no characters match the range, then don't consume
2182 any characters (and unconsume the U+0023 NUMBER SIGN
2183 character and, if appropriate, the X character). This
2184 is a parse error; nothing is returned. */
2185 $this->emitToken(array(
2186 'type' => self::PARSEERROR,
2187 'data' => 'expected-numeric-entity'
2188 ));
2189 return '&' . $chars;
2190 } else {
2191 /* Otherwise, if the next character is a U+003B SEMICOLON,
2192 consume that too. If it isn't, there is a parse error. */
2193 if ($this->stream->char() !== ';') {
2194 $this->stream->unget();
2195 $this->emitToken(array(
2196 'type' => self::PARSEERROR,
2197 'data' => 'numeric-entity-without-semicolon'
2198 ));
2199 }
2200
2201 /* If one or more characters match the range, then take
2202 them all and interpret the string of characters as a number
2203 (either hexadecimal or decimal as appropriate). */
2204 $codepoint = $hex ? hexdec($consumed) : (int) $consumed;
2205
2206 /* If that number is one of the numbers in the first column
2207 of the following table, then this is a parse error. Find the
2208 row with that number in the first column, and return a
2209 character token for the Unicode character given in the
2210 second column of that row. */
2211 $new_codepoint = HTML5_Data::getRealCodepoint($codepoint);
2212 if ($new_codepoint) {
2213 $this->emitToken(array(
2214 'type' => self::PARSEERROR,
2215 'data' => 'illegal-windows-1252-entity'
2216 ));
2217 return HTML5_Data::utf8chr($new_codepoint);
2218 } else {
2219 /* Otherwise, if the number is greater than 0x10FFFF, then
2220 * this is a parse error. Return a U+FFFD REPLACEMENT
2221 * CHARACTER. */
2222 if ($codepoint > 0x10FFFF) {
2223 $this->emitToken(array(
2224 'type' => self::PARSEERROR,
2225 'data' => 'overlong-character-entity' // XXX probably not correct
2226 ));
2227 return "\xEF\xBF\xBD";
2228 }
2229 /* Otherwise, return a character token for the Unicode
2230 * character whose code point is that number. If the
2231 * number is in the range 0x0001 to 0x0008, 0x000E to
2232 * 0x001F, 0x007F to 0x009F, 0xD800 to 0xDFFF, 0xFDD0 to
2233 * 0xFDEF, or is one of 0x000B, 0xFFFE, 0xFFFF, 0x1FFFE,
2234 * 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF, 0x4FFFE,
2235 * 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE,
2236 * 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE,
2237 * 0xAFFFF, 0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE,
2238 * 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE,
2239 * or 0x10FFFF, then this is a parse error. */
2240 // && has higher precedence than ||
2241 if (
2242 $codepoint >= 0x0000 && $codepoint <= 0x0008 ||
2243 $codepoint === 0x000B ||
2244 $codepoint >= 0x000E && $codepoint <= 0x001F ||
2245 $codepoint >= 0x007F && $codepoint <= 0x009F ||
2246 $codepoint >= 0xD800 && $codepoint <= 0xDFFF ||
2247 $codepoint >= 0xFDD0 && $codepoint <= 0xFDEF ||
2248 ($codepoint & 0xFFFE) === 0xFFFE ||
2249 $codepoint == 0x10FFFF || $codepoint == 0x10FFFE
2250 ) {
2251 $this->emitToken(array(
2252 'type' => self::PARSEERROR,
2253 'data' => 'illegal-codepoint-for-numeric-entity'
2254 ));
2255 }
2256 return HTML5_Data::utf8chr($codepoint);
2257 }
2258 }
2259
2260 } else {
2261 /* Anything else */
2262
2263 /* Consume the maximum number of characters possible,
2264 with the consumed characters matching one of the
2265 identifiers in the first column of the named character
2266 references table (in a case-sensitive manner). */
2267 // What we actually do here is consume as much as we can while it
2268 // matches the start of one of the identifiers in the first column.
2269
2270 $refs = HTML5_Data::getNamedCharacterReferences();
2271
2272 // Get the longest string which is the start of an identifier
2273 // ($chars) as well as the longest identifier which matches ($id)
2274 // and its codepoint ($codepoint).
2275 $codepoint = false;
2276 $char = $chars;
2277 while ($char !== false && isset($refs[$char])) {
2278 $refs = $refs[$char];
2279 if (isset($refs['codepoint'])) {
2280 $id = $chars;
2281 $codepoint = $refs['codepoint'];
2282 }
2283 $chars .= $char = $this->stream->char();
2284 }
2285
2286 // Unconsume the one character we just took which caused the while
2287 // statement to fail. This could be anything and could cause state
2288 // changes (as if it matches the while loop it must be
2289 // alphanumeric so we can just concat it to whatever we get later).
2290 $this->stream->unget();
2291 if ($char !== false) {
2292 $chars = substr($chars, 0, -1);
2293 }
2294
2295 /* If no match can be made, then this is a parse error.
2296 No characters are consumed, and nothing is returned. */
2297 if (!$codepoint) {
2298 $this->emitToken(array(
2299 'type' => self::PARSEERROR,
2300 'data' => 'expected-named-entity'
2301 ));
2302 return '&' . $chars;
2303 }
2304
2305 /* If the last character matched is not a U+003B SEMICOLON
2306 (;), there is a parse error. */
2307 $semicolon = true;
2308 if (substr($id, -1) !== ';') {
2309 $this->emitToken(array(
2310 'type' => self::PARSEERROR,
2311 'data' => 'named-entity-without-semicolon'
2312 ));
2313 $semicolon = false;
2314 }
2315
2316 /* If the character reference is being consumed as part of
2317 an attribute, and the last character matched is not a
2318 U+003B SEMICOLON (;), and the next character is in the
2319 range U+0030 DIGIT ZERO to U+0039 DIGIT NINE, U+0041
2320 LATIN CAPITAL LETTER A to U+005A LATIN CAPITAL LETTER Z,
2321 or U+0061 LATIN SMALL LETTER A to U+007A LATIN SMALL LETTER Z,
2322 then, for historical reasons, all the characters that were
2323 matched after the U+0026 AMPERSAND (&) must be unconsumed,
2324 and nothing is returned. */
2325 if ($inattr && !$semicolon) {
2326 // The next character is either the next character in $chars or in the stream.
2327 if (strlen($chars) > strlen($id)) {
2328 $next = substr($chars, strlen($id), 1);
2329 } else {
2330 $next = $this->stream->char();
2331 $this->stream->unget();
2332 }
2333 if (
2334 '0' <= $next && $next <= '9' ||
2335 'A' <= $next && $next <= 'Z' ||
2336 'a' <= $next && $next <= 'z'
2337 ) {
2338 return '&' . $chars;
2339 }
2340 }
2341
2342 /* Otherwise, return a character token for the character
2343 corresponding to the character reference name (as given
2344 by the second column of the named character references table). */
2345 return HTML5_Data::utf8chr($codepoint) . substr($chars, strlen($id));
2346 }
2347 }
2348
2349 private function characterReferenceInAttributeValue($allowed = false) {
2350 /* Attempt to consume a character reference. */
2351 $entity = $this->consumeCharacterReference($allowed, true);
2352
2353 /* If nothing is returned, append a U+0026 AMPERSAND
2354 character to the current attribute's value.
2355
2356 Otherwise, append the returned character token to the
2357 current attribute's value. */
2358 $char = (!$entity)
2359 ? '&'
2360 : $entity;
2361
2362 $last = count($this->token['attr']) - 1;
2363 $this->token['attr'][$last]['value'] .= $char;
2364
2365 /* Finally, switch back to the attribute value state that you
2366 were in when were switched into this state. */
2367 }
2368
2369 /**
2370 * Emits a token, passing it on to the tree builder.
2371 */
2372 protected function emitToken($token, $checkStream = true, $dry = false) {
2373 if ($checkStream) {
2374 // Emit errors from input stream.
2375 while ($this->stream->errors) {
2376 $this->emitToken(array_shift($this->stream->errors), false);
2377 }
2378 }
2379 if($token['type'] === self::ENDTAG && !empty($token['attr'])) {
2380 for ($i = 0; $i < count($token['attr']); $i++) {
2381 $this->emitToken(array(
2382 'type' => self::PARSEERROR,
2383 'data' => 'attributes-in-end-tag'
2384 ));
2385 }
2386 }
2387 if($token['type'] === self::ENDTAG && !empty($token['self-closing'])) {
2388 $this->emitToken(array(
2389 'type' => self::PARSEERROR,
2390 'data' => 'self-closing-flag-on-end-tag',
2391 ));
2392 }
2393 if($token['type'] === self::STARTTAG) {
2394 // This could be changed to actually pass the tree-builder a hash
2395 $hash = array();
2396 foreach ($token['attr'] as $keypair) {
2397 if (isset($hash[$keypair['name']])) {
2398 $this->emitToken(array(
2399 'type' => self::PARSEERROR,
2400 'data' => 'duplicate-attribute',
2401 ));
2402 } else {
2403 $hash[$keypair['name']] = $keypair['value'];
2404 }
2405 }
2406 }
2407
2408 if(!$dry) {
2409 // the current structure of attributes is not a terribly good one
2410 $this->tree->emitToken($token);
2411 }
2412
2413 if(!$dry && is_int($this->tree->content_model)) {
2414 $this->content_model = $this->tree->content_model;
2415 $this->tree->content_model = null;
2416
2417 } elseif($token['type'] === self::ENDTAG) {
2418 $this->content_model = self::PCDATA;
2419 }
2420 }
2421}
2422
diff --git a/inc/3rdparty/libraries/html5/TreeBuilder.php b/inc/3rdparty/libraries/html5/TreeBuilder.php
new file mode 100644
index 00000000..2f5244f9
--- /dev/null
+++ b/inc/3rdparty/libraries/html5/TreeBuilder.php
@@ -0,0 +1,3840 @@
1<?php
2
3/*
4
5Copyright 2007 Jeroen van der Meer <http://jero.net/>
6Copyright 2009 Edward Z. Yang <edwardzyang@thewritingpot.com>
7
8Permission is hereby granted, free of charge, to any person obtaining a
9copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sublicense, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice shall be included
17in all copies or substantial portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27*/
28
29// Tags for FIX ME!!!: (in order of priority)
30// XXX - should be fixed NAO!
31// XERROR - with regards to parse errors
32// XSCRIPT - with regards to scripting mode
33// XENCODING - with regards to encoding (for reparsing tests)
34// XDOM - DOM specific code (tagName is explicitly not marked).
35// this is not (yet) in helper functions.
36
37class HTML5_TreeBuilder {
38 public $stack = array();
39 public $content_model;
40
41 private $mode;
42 private $original_mode;
43 private $secondary_mode;
44 private $dom;
45 // Whether or not normal insertion of nodes should actually foster
46 // parent (used in one case in spec)
47 private $foster_parent = false;
48 private $a_formatting = array();
49
50 private $head_pointer = null;
51 private $form_pointer = null;
52
53 private $flag_frameset_ok = true;
54 private $flag_force_quirks = false;
55 private $ignored = false;
56 private $quirks_mode = null;
57 // this gets to 2 when we want to ignore the next lf character, and
58 // is decrement at the beginning of each processed token (this way,
59 // code can check for (bool)$ignore_lf_token, but it phases out
60 // appropriately)
61 private $ignore_lf_token = 0;
62 private $fragment = false;
63 private $root;
64
65 private $scoping = array('applet','button','caption','html','marquee','object','table','td','th', 'svg:foreignObject');
66 private $formatting = array('a','b','big','code','em','font','i','nobr','s','small','strike','strong','tt','u');
67 // dl and ds are speculative
68 private $special = array('address','area','article','aside','base','basefont','bgsound',
69 'blockquote','body','br','center','col','colgroup','command','dc','dd','details','dir','div','dl','ds',
70 'dt','embed','fieldset','figure','footer','form','frame','frameset','h1','h2','h3','h4','h5',
71 'h6','head','header','hgroup','hr','iframe','img','input','isindex','li','link',
72 'listing','menu','meta','nav','noembed','noframes','noscript','ol',
73 'p','param','plaintext','pre','script','select','spacer','style',
74 'tbody','textarea','tfoot','thead','title','tr','ul','wbr');
75
76 private $pendingTableCharacters;
77 private $pendingTableCharactersDirty;
78
79 // Tree construction modes
80 const INITIAL = 0;
81 const BEFORE_HTML = 1;
82 const BEFORE_HEAD = 2;
83 const IN_HEAD = 3;
84 const IN_HEAD_NOSCRIPT = 4;
85 const AFTER_HEAD = 5;
86 const IN_BODY = 6;
87 const IN_CDATA_RCDATA = 7;
88 const IN_TABLE = 8;
89 const IN_TABLE_TEXT = 9;
90 const IN_CAPTION = 10;
91 const IN_COLUMN_GROUP = 11;
92 const IN_TABLE_BODY = 12;
93 const IN_ROW = 13;
94 const IN_CELL = 14;
95 const IN_SELECT = 15;
96 const IN_SELECT_IN_TABLE= 16;
97 const IN_FOREIGN_CONTENT= 17;
98 const AFTER_BODY = 18;
99 const IN_FRAMESET = 19;
100 const AFTER_FRAMESET = 20;
101 const AFTER_AFTER_BODY = 21;
102 const AFTER_AFTER_FRAMESET = 22;
103
104 /**
105 * Converts a magic number to a readable name. Use for debugging.
106 */
107 private function strConst($number) {
108 static $lookup;
109 if (!$lookup) {
110 $lookup = array();
111 $r = new ReflectionClass('HTML5_TreeBuilder');
112 $consts = $r->getConstants();
113 foreach ($consts as $const => $num) {
114 if (!is_int($num)) continue;
115 $lookup[$num] = $const;
116 }
117 }
118 return $lookup[$number];
119 }
120
121 // The different types of elements.
122 const SPECIAL = 100;
123 const SCOPING = 101;
124 const FORMATTING = 102;
125 const PHRASING = 103;
126
127 // Quirks modes in $quirks_mode
128 const NO_QUIRKS = 200;
129 const QUIRKS_MODE = 201;
130 const LIMITED_QUIRKS_MODE = 202;
131
132 // Marker to be placed in $a_formatting
133 const MARKER = 300;
134
135 // Namespaces for foreign content
136 const NS_HTML = null; // to prevent DOM from requiring NS on everything
137 const NS_MATHML = 'http://www.w3.org/1998/Math/MathML';
138 const NS_SVG = 'http://www.w3.org/2000/svg';
139 const NS_XLINK = 'http://www.w3.org/1999/xlink';
140 const NS_XML = 'http://www.w3.org/XML/1998/namespace';
141 const NS_XMLNS = 'http://www.w3.org/2000/xmlns/';
142
143 // Different types of scopes to test for elements
144 const SCOPE = 0;
145 const SCOPE_LISTITEM = 1;
146 const SCOPE_TABLE = 2;
147
148 public function __construct() {
149 $this->mode = self::INITIAL;
150 $this->dom = new DOMDocument;
151
152 $this->dom->encoding = 'UTF-8';
153 $this->dom->preserveWhiteSpace = true;
154 $this->dom->substituteEntities = true;
155 $this->dom->strictErrorChecking = false;
156 }
157
158 // Process tag tokens
159 public function emitToken($token, $mode = null) {
160 // XXX: ignore parse errors... why are we emitting them, again?
161 if ($token['type'] === HTML5_Tokenizer::PARSEERROR) return;
162 if ($mode === null) $mode = $this->mode;
163
164 /*
165 $backtrace = debug_backtrace();
166 if ($backtrace[1]['class'] !== 'HTML5_TreeBuilder') echo "--\n";
167 echo $this->strConst($mode);
168 if ($this->original_mode) echo " (originally ".$this->strConst($this->original_mode).")";
169 echo "\n ";
170 token_dump($token);
171 $this->printStack();
172 $this->printActiveFormattingElements();
173 if ($this->foster_parent) echo " -> this is a foster parent mode\n";
174 if ($this->flag_frameset_ok) echo " -> frameset ok\n";
175 */
176
177 if ($this->ignore_lf_token) $this->ignore_lf_token--;
178 $this->ignored = false;
179 // indenting is a little wonky, this can be changed later on
180 switch ($mode) {
181
182 case self::INITIAL:
183
184 /* A character token that is one of U+0009 CHARACTER TABULATION,
185 * U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020 SPACE */
186 if ($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
187 /* Ignore the token. */
188 $this->ignored = true;
189 } elseif ($token['type'] === HTML5_Tokenizer::DOCTYPE) {
190 if (
191 $token['name'] !== 'html' || !empty($token['public']) ||
192 !empty($token['system']) || $token !== 'about:legacy-compat'
193 ) {
194 /* If the DOCTYPE token's name is not a case-sensitive match
195 * for the string "html", or if the token's public identifier
196 * is not missing, or if the token's system identifier is
197 * neither missing nor a case-sensitive match for the string
198 * "about:legacy-compat", then there is a parse error (this
199 * is the DOCTYPE parse error). */
200 // DOCTYPE parse error
201 }
202 /* Append a DocumentType node to the Document node, with the name
203 * attribute set to the name given in the DOCTYPE token, or the
204 * empty string if the name was missing; the publicId attribute
205 * set to the public identifier given in the DOCTYPE token, or
206 * the empty string if the public identifier was missing; the
207 * systemId attribute set to the system identifier given in the
208 * DOCTYPE token, or the empty string if the system identifier
209 * was missing; and the other attributes specific to
210 * DocumentType objects set to null and empty lists as
211 * appropriate. Associate the DocumentType node with the
212 * Document object so that it is returned as the value of the
213 * doctype attribute of the Document object. */
214 if (!isset($token['public'])) $token['public'] = null;
215 if (!isset($token['system'])) $token['system'] = null;
216 // XDOM
217 // Yes this is hacky. I'm kind of annoyed that I can't appendChild
218 // a doctype to DOMDocument. Maybe I haven't chanted the right
219 // syllables.
220 $impl = new DOMImplementation();
221 // This call can fail for particularly pathological cases (namely,
222 // the qualifiedName parameter ($token['name']) could be missing.
223 if ($token['name']) {
224 $doctype = $impl->createDocumentType($token['name'], $token['public'], $token['system']);
225 $this->dom->appendChild($doctype);
226 } else {
227 // It looks like libxml's not actually *able* to express this case.
228 // So... don't.
229 $this->dom->emptyDoctype = true;
230 }
231 $public = is_null($token['public']) ? false : strtolower($token['public']);
232 $system = is_null($token['system']) ? false : strtolower($token['system']);
233 $publicStartsWithForQuirks = array(
234 "+//silmaril//dtd html pro v0r11 19970101//",
235 "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
236 "-//as//dtd html 3.0 aswedit + extensions//",
237 "-//ietf//dtd html 2.0 level 1//",
238 "-//ietf//dtd html 2.0 level 2//",
239 "-//ietf//dtd html 2.0 strict level 1//",
240 "-//ietf//dtd html 2.0 strict level 2//",
241 "-//ietf//dtd html 2.0 strict//",
242 "-//ietf//dtd html 2.0//",
243 "-//ietf//dtd html 2.1e//",
244 "-//ietf//dtd html 3.0//",
245 "-//ietf//dtd html 3.2 final//",
246 "-//ietf//dtd html 3.2//",
247 "-//ietf//dtd html 3//",
248 "-//ietf//dtd html level 0//",
249 "-//ietf//dtd html level 1//",
250 "-//ietf//dtd html level 2//",
251 "-//ietf//dtd html level 3//",
252 "-//ietf//dtd html strict level 0//",
253 "-//ietf//dtd html strict level 1//",
254 "-//ietf//dtd html strict level 2//",
255 "-//ietf//dtd html strict level 3//",
256 "-//ietf//dtd html strict//",
257 "-//ietf//dtd html//",
258 "-//metrius//dtd metrius presentational//",
259 "-//microsoft//dtd internet explorer 2.0 html strict//",
260 "-//microsoft//dtd internet explorer 2.0 html//",
261 "-//microsoft//dtd internet explorer 2.0 tables//",
262 "-//microsoft//dtd internet explorer 3.0 html strict//",
263 "-//microsoft//dtd internet explorer 3.0 html//",
264 "-//microsoft//dtd internet explorer 3.0 tables//",
265 "-//netscape comm. corp.//dtd html//",
266 "-//netscape comm. corp.//dtd strict html//",
267 "-//o'reilly and associates//dtd html 2.0//",
268 "-//o'reilly and associates//dtd html extended 1.0//",
269 "-//o'reilly and associates//dtd html extended relaxed 1.0//",
270 "-//spyglass//dtd html 2.0 extended//",
271 "-//sq//dtd html 2.0 hotmetal + extensions//",
272 "-//sun microsystems corp.//dtd hotjava html//",
273 "-//sun microsystems corp.//dtd hotjava strict html//",
274 "-//w3c//dtd html 3 1995-03-24//",
275 "-//w3c//dtd html 3.2 draft//",
276 "-//w3c//dtd html 3.2 final//",
277 "-//w3c//dtd html 3.2//",
278 "-//w3c//dtd html 3.2s draft//",
279 "-//w3c//dtd html 4.0 frameset//",
280 "-//w3c//dtd html 4.0 transitional//",
281 "-//w3c//dtd html experimental 19960712//",
282 "-//w3c//dtd html experimental 970421//",
283 "-//w3c//dtd w3 html//",
284 "-//w3o//dtd w3 html 3.0//",
285 "-//webtechs//dtd mozilla html 2.0//",
286 "-//webtechs//dtd mozilla html//",
287 );
288 $publicSetToForQuirks = array(
289 "-//w3o//dtd w3 html strict 3.0//",
290 "-/w3c/dtd html 4.0 transitional/en",
291 "html",
292 );
293 $publicStartsWithAndSystemForQuirks = array(
294 "-//w3c//dtd html 4.01 frameset//",
295 "-//w3c//dtd html 4.01 transitional//",
296 );
297 $publicStartsWithForLimitedQuirks = array(
298 "-//w3c//dtd xhtml 1.0 frameset//",
299 "-//w3c//dtd xhtml 1.0 transitional//",
300 );
301 $publicStartsWithAndSystemForLimitedQuirks = array(
302 "-//w3c//dtd html 4.01 frameset//",
303 "-//w3c//dtd html 4.01 transitional//",
304 );
305 // first, do easy checks
306 if (
307 !empty($token['force-quirks']) ||
308 strtolower($token['name']) !== 'html'
309 ) {
310 $this->quirks_mode = self::QUIRKS_MODE;
311 } else {
312 do {
313 if ($system) {
314 foreach ($publicStartsWithAndSystemForQuirks as $x) {
315 if (strncmp($public, $x, strlen($x)) === 0) {
316 $this->quirks_mode = self::QUIRKS_MODE;
317 break;
318 }
319 }
320 if (!is_null($this->quirks_mode)) break;
321 foreach ($publicStartsWithAndSystemForLimitedQuirks as $x) {
322 if (strncmp($public, $x, strlen($x)) === 0) {
323 $this->quirks_mode = self::LIMITED_QUIRKS_MODE;
324 break;
325 }
326 }
327 if (!is_null($this->quirks_mode)) break;
328 }
329 foreach ($publicSetToForQuirks as $x) {
330 if ($public === $x) {
331 $this->quirks_mode = self::QUIRKS_MODE;
332 break;
333 }
334 }
335 if (!is_null($this->quirks_mode)) break;
336 foreach ($publicStartsWithForLimitedQuirks as $x) {
337 if (strncmp($public, $x, strlen($x)) === 0) {
338 $this->quirks_mode = self::LIMITED_QUIRKS_MODE;
339 }
340 }
341 if (!is_null($this->quirks_mode)) break;
342 if ($system === "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd") {
343 $this->quirks_mode = self::QUIRKS_MODE;
344 break;
345 }
346 foreach ($publicStartsWithForQuirks as $x) {
347 if (strncmp($public, $x, strlen($x)) === 0) {
348 $this->quirks_mode = self::QUIRKS_MODE;
349 break;
350 }
351 }
352 if (is_null($this->quirks_mode)) {
353 $this->quirks_mode = self::NO_QUIRKS;
354 }
355 } while (false);
356 }
357 $this->mode = self::BEFORE_HTML;
358 } else {
359 // parse error
360 /* Switch the insertion mode to "before html", then reprocess the
361 * current token. */
362 $this->mode = self::BEFORE_HTML;
363 $this->quirks_mode = self::QUIRKS_MODE;
364 $this->emitToken($token);
365 }
366 break;
367
368 case self::BEFORE_HTML:
369
370 /* A DOCTYPE token */
371 if($token['type'] === HTML5_Tokenizer::DOCTYPE) {
372 // Parse error. Ignore the token.
373 $this->ignored = true;
374
375 /* A comment token */
376 } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
377 /* Append a Comment node to the Document object with the data
378 attribute set to the data given in the comment token. */
379 // XDOM
380 $comment = $this->dom->createComment($token['data']);
381 $this->dom->appendChild($comment);
382
383 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
384 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
385 or U+0020 SPACE */
386 } elseif($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
387 /* Ignore the token. */
388 $this->ignored = true;
389
390 /* A start tag whose tag name is "html" */
391 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] == 'html') {
392 /* Create an element for the token in the HTML namespace. Append it
393 * to the Document object. Put this element in the stack of open
394 * elements. */
395 // XDOM
396 $html = $this->insertElement($token, false);
397 $this->dom->appendChild($html);
398 $this->stack[] = $html;
399
400 $this->mode = self::BEFORE_HEAD;
401
402 } else {
403 /* Create an html element. Append it to the Document object. Put
404 * this element in the stack of open elements. */
405 // XDOM
406 $html = $this->dom->createElementNS(self::NS_HTML, 'html');
407 $this->dom->appendChild($html);
408 $this->stack[] = $html;
409
410 /* Switch the insertion mode to "before head", then reprocess the
411 * current token. */
412 $this->mode = self::BEFORE_HEAD;
413 $this->emitToken($token);
414 }
415 break;
416
417 case self::BEFORE_HEAD:
418
419 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
420 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
421 or U+0020 SPACE */
422 if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
423 /* Ignore the token. */
424 $this->ignored = true;
425
426 /* A comment token */
427 } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
428 /* Append a Comment node to the current node with the data attribute
429 set to the data given in the comment token. */
430 $this->insertComment($token['data']);
431
432 /* A DOCTYPE token */
433 } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
434 /* Parse error. Ignore the token */
435 $this->ignored = true;
436 // parse error
437
438 /* A start tag token with the tag name "html" */
439 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {
440 /* Process the token using the rules for the "in body"
441 * insertion mode. */
442 $this->processWithRulesFor($token, self::IN_BODY);
443
444 /* A start tag token with the tag name "head" */
445 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'head') {
446 /* Insert an HTML element for the token. */
447 $element = $this->insertElement($token);
448
449 /* Set the head element pointer to this new element node. */
450 $this->head_pointer = $element;
451
452 /* Change the insertion mode to "in head". */
453 $this->mode = self::IN_HEAD;
454
455 /* An end tag whose tag name is one of: "head", "body", "html", "br" */
456 } elseif(
457 $token['type'] === HTML5_Tokenizer::ENDTAG && (
458 $token['name'] === 'head' || $token['name'] === 'body' ||
459 $token['name'] === 'html' || $token['name'] === 'br'
460 )) {
461 /* Act as if a start tag token with the tag name "head" and no
462 * attributes had been seen, then reprocess the current token. */
463 $this->emitToken(array(
464 'name' => 'head',
465 'type' => HTML5_Tokenizer::STARTTAG,
466 'attr' => array()
467 ));
468 $this->emitToken($token);
469
470 /* Any other end tag */
471 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG) {
472 /* Parse error. Ignore the token. */
473 $this->ignored = true;
474
475 } else {
476 /* Act as if a start tag token with the tag name "head" and no
477 * attributes had been seen, then reprocess the current token.
478 * Note: This will result in an empty head element being
479 * generated, with the current token being reprocessed in the
480 * "after head" insertion mode. */
481 $this->emitToken(array(
482 'name' => 'head',
483 'type' => HTML5_Tokenizer::STARTTAG,
484 'attr' => array()
485 ));
486 $this->emitToken($token);
487 }
488 break;
489
490 case self::IN_HEAD:
491
492 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
493 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
494 or U+0020 SPACE. */
495 if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
496 /* Insert the character into the current node. */
497 $this->insertText($token['data']);
498
499 /* A comment token */
500 } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
501 /* Append a Comment node to the current node with the data attribute
502 set to the data given in the comment token. */
503 $this->insertComment($token['data']);
504
505 /* A DOCTYPE token */
506 } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
507 /* Parse error. Ignore the token. */
508 $this->ignored = true;
509 // parse error
510
511 /* A start tag whose tag name is "html" */
512 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
513 $token['name'] === 'html') {
514 $this->processWithRulesFor($token, self::IN_BODY);
515
516 /* A start tag whose tag name is one of: "base", "command", "link" */
517 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
518 ($token['name'] === 'base' || $token['name'] === 'command' ||
519 $token['name'] === 'link')) {
520 /* Insert an HTML element for the token. Immediately pop the
521 * current node off the stack of open elements. */
522 $this->insertElement($token);
523 array_pop($this->stack);
524
525 // YYY: Acknowledge the token's self-closing flag, if it is set.
526
527 /* A start tag whose tag name is "meta" */
528 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'meta') {
529 /* Insert an HTML element for the token. Immediately pop the
530 * current node off the stack of open elements. */
531 $this->insertElement($token);
532 array_pop($this->stack);
533
534 // XERROR: Acknowledge the token's self-closing flag, if it is set.
535
536 // XENCODING: If the element has a charset attribute, and its value is a
537 // supported encoding, and the confidence is currently tentative,
538 // then change the encoding to the encoding given by the value of
539 // the charset attribute.
540 //
541 // Otherwise, if the element has a content attribute, and applying
542 // the algorithm for extracting an encoding from a Content-Type to
543 // its value returns a supported encoding encoding, and the
544 // confidence is currently tentative, then change the encoding to
545 // the encoding encoding.
546
547 /* A start tag with the tag name "title" */
548 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'title') {
549 $this->insertRCDATAElement($token);
550
551 /* A start tag whose tag name is "noscript", if the scripting flag is enabled, or
552 * A start tag whose tag name is one of: "noframes", "style" */
553 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
554 ($token['name'] === 'noscript' || $token['name'] === 'noframes' || $token['name'] === 'style')) {
555 // XSCRIPT: Scripting flag not respected
556 $this->insertCDATAElement($token);
557
558 // XSCRIPT: Scripting flag disable not implemented
559
560 /* A start tag with the tag name "script" */
561 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'script') {
562 /* 1. Create an element for the token in the HTML namespace. */
563 $node = $this->insertElement($token, false);
564
565 /* 2. Mark the element as being "parser-inserted" */
566 // Uhhh... XSCRIPT
567
568 /* 3. If the parser was originally created for the HTML
569 * fragment parsing algorithm, then mark the script element as
570 * "already executed". (fragment case) */
571 // ditto... XSCRIPT
572
573 /* 4. Append the new element to the current node and push it onto
574 * the stack of open elements. */
575 end($this->stack)->appendChild($node);
576 $this->stack[] = $node;
577 // I guess we could squash these together
578
579 /* 6. Let the original insertion mode be the current insertion mode. */
580 $this->original_mode = $this->mode;
581 /* 7. Switch the insertion mode to "in CDATA/RCDATA" */
582 $this->mode = self::IN_CDATA_RCDATA;
583 /* 5. Switch the tokeniser's content model flag to the CDATA state. */
584 $this->content_model = HTML5_Tokenizer::CDATA;
585
586 /* An end tag with the tag name "head" */
587 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'head') {
588 /* Pop the current node (which will be the head element) off the stack of open elements. */
589 array_pop($this->stack);
590
591 /* Change the insertion mode to "after head". */
592 $this->mode = self::AFTER_HEAD;
593
594 // Slight logic inversion here to minimize duplication
595 /* A start tag with the tag name "head". */
596 /* An end tag whose tag name is not one of: "body", "html", "br" */
597 } elseif(($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'head') ||
598 ($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] !== 'html' &&
599 $token['name'] !== 'body' && $token['name'] !== 'br')) {
600 // Parse error. Ignore the token.
601 $this->ignored = true;
602
603 /* Anything else */
604 } else {
605 /* Act as if an end tag token with the tag name "head" had been
606 * seen, and reprocess the current token. */
607 $this->emitToken(array(
608 'name' => 'head',
609 'type' => HTML5_Tokenizer::ENDTAG
610 ));
611
612 /* Then, reprocess the current token. */
613 $this->emitToken($token);
614 }
615 break;
616
617 case self::IN_HEAD_NOSCRIPT:
618 if ($token['type'] === HTML5_Tokenizer::DOCTYPE) {
619 // parse error
620 } elseif ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {
621 $this->processWithRulesFor($token, self::IN_BODY);
622 } elseif ($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'noscript') {
623 /* Pop the current node (which will be a noscript element) from the
624 * stack of open elements; the new current node will be a head
625 * element. */
626 array_pop($this->stack);
627 $this->mode = self::IN_HEAD;
628 } elseif (
629 ($token['type'] === HTML5_Tokenizer::SPACECHARACTER) ||
630 ($token['type'] === HTML5_Tokenizer::COMMENT) ||
631 ($token['type'] === HTML5_Tokenizer::STARTTAG && (
632 $token['name'] === 'link' || $token['name'] === 'meta' ||
633 $token['name'] === 'noframes' || $token['name'] === 'style'))) {
634 $this->processWithRulesFor($token, self::IN_HEAD);
635 // inverted logic
636 } elseif (
637 ($token['type'] === HTML5_Tokenizer::STARTTAG && (
638 $token['name'] === 'head' || $token['name'] === 'noscript')) ||
639 ($token['type'] === HTML5_Tokenizer::ENDTAG &&
640 $token['name'] !== 'br')) {
641 // parse error
642 } else {
643 // parse error
644 $this->emitToken(array(
645 'type' => HTML5_Tokenizer::ENDTAG,
646 'name' => 'noscript',
647 ));
648 $this->emitToken($token);
649 }
650 break;
651
652 case self::AFTER_HEAD:
653 /* Handle the token as follows: */
654
655 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
656 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
657 or U+0020 SPACE */
658 if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
659 /* Append the character to the current node. */
660 $this->insertText($token['data']);
661
662 /* A comment token */
663 } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
664 /* Append a Comment node to the current node with the data attribute
665 set to the data given in the comment token. */
666 $this->insertComment($token['data']);
667
668 } elseif ($token['type'] === HTML5_Tokenizer::DOCTYPE) {
669 // parse error
670
671 } elseif ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {
672 $this->processWithRulesFor($token, self::IN_BODY);
673
674 /* A start tag token with the tag name "body" */
675 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'body') {
676 $this->insertElement($token);
677
678 /* Set the frameset-ok flag to "not ok". */
679 $this->flag_frameset_ok = false;
680
681 /* Change the insertion mode to "in body". */
682 $this->mode = self::IN_BODY;
683
684 /* A start tag token with the tag name "frameset" */
685 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'frameset') {
686 /* Insert a frameset element for the token. */
687 $this->insertElement($token);
688
689 /* Change the insertion mode to "in frameset". */
690 $this->mode = self::IN_FRAMESET;
691
692 /* A start tag token whose tag name is one of: "base", "link", "meta",
693 "script", "style", "title" */
694 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],
695 array('base', 'link', 'meta', 'noframes', 'script', 'style', 'title'))) {
696 // parse error
697 /* Push the node pointed to by the head element pointer onto the
698 * stack of open elements. */
699 $this->stack[] = $this->head_pointer;
700 $this->processWithRulesFor($token, self::IN_HEAD);
701 array_splice($this->stack, array_search($this->head_pointer, $this->stack, true), 1);
702
703 // inversion of specification
704 } elseif(
705 ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'head') ||
706 ($token['type'] === HTML5_Tokenizer::ENDTAG &&
707 $token['name'] !== 'body' && $token['name'] !== 'html' &&
708 $token['name'] !== 'br')) {
709 // parse error
710
711 /* Anything else */
712 } else {
713 $this->emitToken(array(
714 'name' => 'body',
715 'type' => HTML5_Tokenizer::STARTTAG,
716 'attr' => array()
717 ));
718 $this->flag_frameset_ok = true;
719 $this->emitToken($token);
720 }
721 break;
722
723 case self::IN_BODY:
724 /* Handle the token as follows: */
725
726 switch($token['type']) {
727 /* A character token */
728 case HTML5_Tokenizer::CHARACTER:
729 case HTML5_Tokenizer::SPACECHARACTER:
730 /* Reconstruct the active formatting elements, if any. */
731 $this->reconstructActiveFormattingElements();
732
733 /* Append the token's character to the current node. */
734 $this->insertText($token['data']);
735
736 /* If the token is not one of U+0009 CHARACTER TABULATION,
737 * U+000A LINE FEED (LF), U+000C FORM FEED (FF), or U+0020
738 * SPACE, then set the frameset-ok flag to "not ok". */
739 // i.e., if any of the characters is not whitespace
740 if (strlen($token['data']) !== strspn($token['data'], HTML5_Tokenizer::WHITESPACE)) {
741 $this->flag_frameset_ok = false;
742 }
743 break;
744
745 /* A comment token */
746 case HTML5_Tokenizer::COMMENT:
747 /* Append a Comment node to the current node with the data
748 attribute set to the data given in the comment token. */
749 $this->insertComment($token['data']);
750 break;
751
752 case HTML5_Tokenizer::DOCTYPE:
753 // parse error
754 break;
755
756 case HTML5_Tokenizer::EOF:
757 // parse error
758 break;
759
760 case HTML5_Tokenizer::STARTTAG:
761 switch($token['name']) {
762 case 'html':
763 // parse error
764 /* For each attribute on the token, check to see if the
765 * attribute is already present on the top element of the
766 * stack of open elements. If it is not, add the attribute
767 * and its corresponding value to that element. */
768 foreach($token['attr'] as $attr) {
769 if(!$this->stack[0]->hasAttribute($attr['name'])) {
770 $this->stack[0]->setAttribute($attr['name'], $attr['value']);
771 }
772 }
773 break;
774
775 case 'base': case 'command': case 'link': case 'meta': case 'noframes':
776 case 'script': case 'style': case 'title':
777 /* Process the token as if the insertion mode had been "in
778 head". */
779 $this->processWithRulesFor($token, self::IN_HEAD);
780 break;
781
782 /* A start tag token with the tag name "body" */
783 case 'body':
784 /* Parse error. If the second element on the stack of open
785 elements is not a body element, or, if the stack of open
786 elements has only one node on it, then ignore the token.
787 (fragment case) */
788 if(count($this->stack) === 1 || $this->stack[1]->tagName !== 'body') {
789 $this->ignored = true;
790 // Ignore
791
792 /* Otherwise, for each attribute on the token, check to see
793 if the attribute is already present on the body element (the
794 second element) on the stack of open elements. If it is not,
795 add the attribute and its corresponding value to that
796 element. */
797 } else {
798 foreach($token['attr'] as $attr) {
799 if(!$this->stack[1]->hasAttribute($attr['name'])) {
800 $this->stack[1]->setAttribute($attr['name'], $attr['value']);
801 }
802 }
803 }
804 break;
805
806 case 'frameset':
807 // parse error
808 /* If the second element on the stack of open elements is
809 * not a body element, or, if the stack of open elements
810 * has only one node on it, then ignore the token.
811 * (fragment case) */
812 if(count($this->stack) === 1 || $this->stack[1]->tagName !== 'body') {
813 $this->ignored = true;
814 // Ignore
815 } elseif (!$this->flag_frameset_ok) {
816 $this->ignored = true;
817 // Ignore
818 } else {
819 /* 1. Remove the second element on the stack of open
820 * elements from its parent node, if it has one. */
821 if($this->stack[1]->parentNode) {
822 $this->stack[1]->parentNode->removeChild($this->stack[1]);
823 }
824
825 /* 2. Pop all the nodes from the bottom of the stack of
826 * open elements, from the current node up to the root
827 * html element. */
828 array_splice($this->stack, 1);
829
830 $this->insertElement($token);
831 $this->mode = self::IN_FRAMESET;
832 }
833 break;
834
835 // in spec, there is a diversion here
836
837 case 'address': case 'article': case 'aside': case 'blockquote':
838 case 'center': case 'datagrid': case 'details': case 'dir':
839 case 'div': case 'dl': case 'fieldset': case 'figure': case 'footer':
840 case 'header': case 'hgroup': case 'menu': case 'nav':
841 case 'ol': case 'p': case 'section': case 'ul':
842 /* If the stack of open elements has a p element in scope,
843 then act as if an end tag with the tag name p had been
844 seen. */
845 if($this->elementInScope('p')) {
846 $this->emitToken(array(
847 'name' => 'p',
848 'type' => HTML5_Tokenizer::ENDTAG
849 ));
850 }
851
852 /* Insert an HTML element for the token. */
853 $this->insertElement($token);
854 break;
855
856 /* A start tag whose tag name is one of: "h1", "h2", "h3", "h4",
857 "h5", "h6" */
858 case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6':
859 /* If the stack of open elements has a p element in scope,
860 then act as if an end tag with the tag name p had been seen. */
861 if($this->elementInScope('p')) {
862 $this->emitToken(array(
863 'name' => 'p',
864 'type' => HTML5_Tokenizer::ENDTAG
865 ));
866 }
867
868 /* If the current node is an element whose tag name is one
869 * of "h1", "h2", "h3", "h4", "h5", or "h6", then this is a
870 * parse error; pop the current node off the stack of open
871 * elements. */
872 $peek = array_pop($this->stack);
873 if (in_array($peek->tagName, array("h1", "h2", "h3", "h4", "h5", "h6"))) {
874 // parse error
875 } else {
876 $this->stack[] = $peek;
877 }
878
879 /* Insert an HTML element for the token. */
880 $this->insertElement($token);
881 break;
882
883 case 'pre': case 'listing':
884 /* If the stack of open elements has a p element in scope,
885 then act as if an end tag with the tag name p had been seen. */
886 if($this->elementInScope('p')) {
887 $this->emitToken(array(
888 'name' => 'p',
889 'type' => HTML5_Tokenizer::ENDTAG
890 ));
891 }
892 $this->insertElement($token);
893 /* If the next token is a U+000A LINE FEED (LF) character
894 * token, then ignore that token and move on to the next
895 * one. (Newlines at the start of pre blocks are ignored as
896 * an authoring convenience.) */
897 $this->ignore_lf_token = 2;
898 $this->flag_frameset_ok = false;
899 break;
900
901 /* A start tag whose tag name is "form" */
902 case 'form':
903 /* If the form element pointer is not null, ignore the
904 token with a parse error. */
905 if($this->form_pointer !== null) {
906 $this->ignored = true;
907 // Ignore.
908
909 /* Otherwise: */
910 } else {
911 /* If the stack of open elements has a p element in
912 scope, then act as if an end tag with the tag name p
913 had been seen. */
914 if($this->elementInScope('p')) {
915 $this->emitToken(array(
916 'name' => 'p',
917 'type' => HTML5_Tokenizer::ENDTAG
918 ));
919 }
920
921 /* Insert an HTML element for the token, and set the
922 form element pointer to point to the element created. */
923 $element = $this->insertElement($token);
924 $this->form_pointer = $element;
925 }
926 break;
927
928 // condensed specification
929 case 'li': case 'dc': case 'dd': case 'ds': case 'dt':
930 /* 1. Set the frameset-ok flag to "not ok". */
931 $this->flag_frameset_ok = false;
932
933 $stack_length = count($this->stack) - 1;
934 for($n = $stack_length; 0 <= $n; $n--) {
935 /* 2. Initialise node to be the current node (the
936 bottommost node of the stack). */
937 $stop = false;
938 $node = $this->stack[$n];
939 $cat = $this->getElementCategory($node);
940
941 // for case 'li':
942 /* 3. If node is an li element, then act as if an end
943 * tag with the tag name "li" had been seen, then jump
944 * to the last step. */
945 // for case 'dc': case 'dd': case 'ds': case 'dt':
946 /* If node is a dc, dd, ds or dt element, then act as if an end
947 * tag with the same tag name as node had been seen, then
948 * jump to the last step. */
949 if(($token['name'] === 'li' && $node->tagName === 'li') ||
950 ($token['name'] !== 'li' && ($node->tagName == 'dc' || $node->tagName === 'dd' || $node->tagName == 'ds' || $node->tagName === 'dt'))) { // limited conditional
951 $this->emitToken(array(
952 'type' => HTML5_Tokenizer::ENDTAG,
953 'name' => $node->tagName,
954 ));
955 break;
956 }
957
958 /* 4. If node is not in the formatting category, and is
959 not in the phrasing category, and is not an address,
960 div or p element, then stop this algorithm. */
961 if($cat !== self::FORMATTING && $cat !== self::PHRASING &&
962 $node->tagName !== 'address' && $node->tagName !== 'div' &&
963 $node->tagName !== 'p') {
964 break;
965 }
966
967 /* 5. Otherwise, set node to the previous entry in the
968 * stack of open elements and return to step 2. */
969 }
970
971 /* 6. This is the last step. */
972
973 /* If the stack of open elements has a p element in scope,
974 then act as if an end tag with the tag name p had been
975 seen. */
976 if($this->elementInScope('p')) {
977 $this->emitToken(array(
978 'name' => 'p',
979 'type' => HTML5_Tokenizer::ENDTAG
980 ));
981 }
982
983 /* Finally, insert an HTML element with the same tag
984 name as the token's. */
985 $this->insertElement($token);
986 break;
987
988 /* A start tag token whose tag name is "plaintext" */
989 case 'plaintext':
990 /* If the stack of open elements has a p element in scope,
991 then act as if an end tag with the tag name p had been
992 seen. */
993 if($this->elementInScope('p')) {
994 $this->emitToken(array(
995 'name' => 'p',
996 'type' => HTML5_Tokenizer::ENDTAG
997 ));
998 }
999
1000 /* Insert an HTML element for the token. */
1001 $this->insertElement($token);
1002
1003 $this->content_model = HTML5_Tokenizer::PLAINTEXT;
1004 break;
1005
1006 // more diversions
1007
1008 /* A start tag whose tag name is "a" */
1009 case 'a':
1010 /* If the list of active formatting elements contains
1011 an element whose tag name is "a" between the end of the
1012 list and the last marker on the list (or the start of
1013 the list if there is no marker on the list), then this
1014 is a parse error; act as if an end tag with the tag name
1015 "a" had been seen, then remove that element from the list
1016 of active formatting elements and the stack of open
1017 elements if the end tag didn't already remove it (it
1018 might not have if the element is not in table scope). */
1019 $leng = count($this->a_formatting);
1020
1021 for($n = $leng - 1; $n >= 0; $n--) {
1022 if($this->a_formatting[$n] === self::MARKER) {
1023 break;
1024
1025 } elseif($this->a_formatting[$n]->tagName === 'a') {
1026 $a = $this->a_formatting[$n];
1027 $this->emitToken(array(
1028 'name' => 'a',
1029 'type' => HTML5_Tokenizer::ENDTAG
1030 ));
1031 if (in_array($a, $this->a_formatting)) {
1032 $a_i = array_search($a, $this->a_formatting, true);
1033 if($a_i !== false) array_splice($this->a_formatting, $a_i, 1);
1034 }
1035 if (in_array($a, $this->stack)) {
1036 $a_i = array_search($a, $this->stack, true);
1037 if ($a_i !== false) array_splice($this->stack, $a_i, 1);
1038 }
1039 break;
1040 }
1041 }
1042
1043 /* Reconstruct the active formatting elements, if any. */
1044 $this->reconstructActiveFormattingElements();
1045
1046 /* Insert an HTML element for the token. */
1047 $el = $this->insertElement($token);
1048
1049 /* Add that element to the list of active formatting
1050 elements. */
1051 $this->a_formatting[] = $el;
1052 break;
1053
1054 case 'b': case 'big': case 'code': case 'em': case 'font': case 'i':
1055 case 's': case 'small': case 'strike':
1056 case 'strong': case 'tt': case 'u':
1057 /* Reconstruct the active formatting elements, if any. */
1058 $this->reconstructActiveFormattingElements();
1059
1060 /* Insert an HTML element for the token. */
1061 $el = $this->insertElement($token);
1062
1063 /* Add that element to the list of active formatting
1064 elements. */
1065 $this->a_formatting[] = $el;
1066 break;
1067
1068 case 'nobr':
1069 /* Reconstruct the active formatting elements, if any. */
1070 $this->reconstructActiveFormattingElements();
1071
1072 /* If the stack of open elements has a nobr element in
1073 * scope, then this is a parse error; act as if an end tag
1074 * with the tag name "nobr" had been seen, then once again
1075 * reconstruct the active formatting elements, if any. */
1076 if ($this->elementInScope('nobr')) {
1077 $this->emitToken(array(
1078 'name' => 'nobr',
1079 'type' => HTML5_Tokenizer::ENDTAG,
1080 ));
1081 $this->reconstructActiveFormattingElements();
1082 }
1083
1084 /* Insert an HTML element for the token. */
1085 $el = $this->insertElement($token);
1086
1087 /* Add that element to the list of active formatting
1088 elements. */
1089 $this->a_formatting[] = $el;
1090 break;
1091
1092 // another diversion
1093
1094 /* A start tag token whose tag name is "button" */
1095 case 'button':
1096 /* If the stack of open elements has a button element in scope,
1097 then this is a parse error; act as if an end tag with the tag
1098 name "button" had been seen, then reprocess the token. (We don't
1099 do that. Unnecessary.) (I hope you're right! -- ezyang) */
1100 if($this->elementInScope('button')) {
1101 $this->emitToken(array(
1102 'name' => 'button',
1103 'type' => HTML5_Tokenizer::ENDTAG
1104 ));
1105 }
1106
1107 /* Reconstruct the active formatting elements, if any. */
1108 $this->reconstructActiveFormattingElements();
1109
1110 /* Insert an HTML element for the token. */
1111 $this->insertElement($token);
1112
1113 /* Insert a marker at the end of the list of active
1114 formatting elements. */
1115 $this->a_formatting[] = self::MARKER;
1116
1117 $this->flag_frameset_ok = false;
1118 break;
1119
1120 case 'applet': case 'marquee': case 'object':
1121 /* Reconstruct the active formatting elements, if any. */
1122 $this->reconstructActiveFormattingElements();
1123
1124 /* Insert an HTML element for the token. */
1125 $this->insertElement($token);
1126
1127 /* Insert a marker at the end of the list of active
1128 formatting elements. */
1129 $this->a_formatting[] = self::MARKER;
1130
1131 $this->flag_frameset_ok = false;
1132 break;
1133
1134 // spec diversion
1135
1136 /* A start tag whose tag name is "table" */
1137 case 'table':
1138 /* If the Document is not set to quirks mode, and the
1139 * stack of open elements has a p element in scope, then
1140 * act as if an end tag with the tag name "p" had been
1141 * seen. */
1142 if($this->quirks_mode !== self::QUIRKS_MODE &&
1143 $this->elementInScope('p')) {
1144 $this->emitToken(array(
1145 'name' => 'p',
1146 'type' => HTML5_Tokenizer::ENDTAG
1147 ));
1148 }
1149
1150 /* Insert an HTML element for the token. */
1151 $this->insertElement($token);
1152
1153 $this->flag_frameset_ok = false;
1154
1155 /* Change the insertion mode to "in table". */
1156 $this->mode = self::IN_TABLE;
1157 break;
1158
1159 /* A start tag whose tag name is one of: "area", "basefont",
1160 "bgsound", "br", "embed", "img", "param", "spacer", "wbr" */
1161 case 'area': case 'basefont': case 'bgsound': case 'br':
1162 case 'embed': case 'img': case 'input': case 'keygen': case 'spacer':
1163 case 'wbr':
1164 /* Reconstruct the active formatting elements, if any. */
1165 $this->reconstructActiveFormattingElements();
1166
1167 /* Insert an HTML element for the token. */
1168 $this->insertElement($token);
1169
1170 /* Immediately pop the current node off the stack of open elements. */
1171 array_pop($this->stack);
1172
1173 // YYY: Acknowledge the token's self-closing flag, if it is set.
1174
1175 $this->flag_frameset_ok = false;
1176 break;
1177
1178 case 'param': case 'source':
1179 /* Insert an HTML element for the token. */
1180 $this->insertElement($token);
1181
1182 /* Immediately pop the current node off the stack of open elements. */
1183 array_pop($this->stack);
1184
1185 // YYY: Acknowledge the token's self-closing flag, if it is set.
1186 break;
1187
1188 /* A start tag whose tag name is "hr" */
1189 case 'hr':
1190 /* If the stack of open elements has a p element in scope,
1191 then act as if an end tag with the tag name p had been seen. */
1192 if($this->elementInScope('p')) {
1193 $this->emitToken(array(
1194 'name' => 'p',
1195 'type' => HTML5_Tokenizer::ENDTAG
1196 ));
1197 }
1198
1199 /* Insert an HTML element for the token. */
1200 $this->insertElement($token);
1201
1202 /* Immediately pop the current node off the stack of open elements. */
1203 array_pop($this->stack);
1204
1205 // YYY: Acknowledge the token's self-closing flag, if it is set.
1206
1207 $this->flag_frameset_ok = false;
1208 break;
1209
1210 /* A start tag whose tag name is "image" */
1211 case 'image':
1212 /* Parse error. Change the token's tag name to "img" and
1213 reprocess it. (Don't ask.) */
1214 $token['name'] = 'img';
1215 $this->emitToken($token);
1216 break;
1217
1218 /* A start tag whose tag name is "isindex" */
1219 case 'isindex':
1220 /* Parse error. */
1221
1222 /* If the form element pointer is not null,
1223 then ignore the token. */
1224 if($this->form_pointer === null) {
1225 /* Act as if a start tag token with the tag name "form" had
1226 been seen. */
1227 /* If the token has an attribute called "action", set
1228 * the action attribute on the resulting form
1229 * element to the value of the "action" attribute of
1230 * the token. */
1231 $attr = array();
1232 $action = $this->getAttr($token, 'action');
1233 if ($action !== false) {
1234 $attr[] = array('name' => 'action', 'value' => $action);
1235 }
1236 $this->emitToken(array(
1237 'name' => 'form',
1238 'type' => HTML5_Tokenizer::STARTTAG,
1239 'attr' => $attr
1240 ));
1241
1242 /* Act as if a start tag token with the tag name "hr" had
1243 been seen. */
1244 $this->emitToken(array(
1245 'name' => 'hr',
1246 'type' => HTML5_Tokenizer::STARTTAG,
1247 'attr' => array()
1248 ));
1249
1250 /* Act as if a start tag token with the tag name "label"
1251 had been seen. */
1252 $this->emitToken(array(
1253 'name' => 'label',
1254 'type' => HTML5_Tokenizer::STARTTAG,
1255 'attr' => array()
1256 ));
1257
1258 /* Act as if a stream of character tokens had been seen. */
1259 $prompt = $this->getAttr($token, 'prompt');
1260 if ($prompt === false) {
1261 $prompt = 'This is a searchable index. '.
1262 'Insert your search keywords here: ';
1263 }
1264 $this->emitToken(array(
1265 'data' => $prompt,
1266 'type' => HTML5_Tokenizer::CHARACTER,
1267 ));
1268
1269 /* Act as if a start tag token with the tag name "input"
1270 had been seen, with all the attributes from the "isindex"
1271 token, except with the "name" attribute set to the value
1272 "isindex" (ignoring any explicit "name" attribute). */
1273 $attr = array();
1274 foreach ($token['attr'] as $keypair) {
1275 if ($keypair['name'] === 'name' || $keypair['name'] === 'action' ||
1276 $keypair['name'] === 'prompt') continue;
1277 $attr[] = $keypair;
1278 }
1279 $attr[] = array('name' => 'name', 'value' => 'isindex');
1280
1281 $this->emitToken(array(
1282 'name' => 'input',
1283 'type' => HTML5_Tokenizer::STARTTAG,
1284 'attr' => $attr
1285 ));
1286
1287 /* Act as if an end tag token with the tag name "label"
1288 had been seen. */
1289 $this->emitToken(array(
1290 'name' => 'label',
1291 'type' => HTML5_Tokenizer::ENDTAG
1292 ));
1293
1294 /* Act as if a start tag token with the tag name "hr" had
1295 been seen. */
1296 $this->emitToken(array(
1297 'name' => 'hr',
1298 'type' => HTML5_Tokenizer::STARTTAG
1299 ));
1300
1301 /* Act as if an end tag token with the tag name "form" had
1302 been seen. */
1303 $this->emitToken(array(
1304 'name' => 'form',
1305 'type' => HTML5_Tokenizer::ENDTAG
1306 ));
1307 } else {
1308 $this->ignored = true;
1309 }
1310 break;
1311
1312 /* A start tag whose tag name is "textarea" */
1313 case 'textarea':
1314 $this->insertElement($token);
1315
1316 /* If the next token is a U+000A LINE FEED (LF)
1317 * character token, then ignore that token and move on to
1318 * the next one. (Newlines at the start of textarea
1319 * elements are ignored as an authoring convenience.)
1320 * need flag, see also <pre> */
1321 $this->ignore_lf_token = 2;
1322
1323 $this->original_mode = $this->mode;
1324 $this->flag_frameset_ok = false;
1325 $this->mode = self::IN_CDATA_RCDATA;
1326
1327 /* Switch the tokeniser's content model flag to the
1328 RCDATA state. */
1329 $this->content_model = HTML5_Tokenizer::RCDATA;
1330 break;
1331
1332 /* A start tag token whose tag name is "xmp" */
1333 case 'xmp':
1334 /* If the stack of open elements has a p element in
1335 scope, then act as if an end tag with the tag name
1336 "p" has been seen. */
1337 if ($this->elementInScope('p')) {
1338 $this->emitToken(array(
1339 'name' => 'p',
1340 'type' => HTML5_Tokenizer::ENDTAG
1341 ));
1342 }
1343
1344 /* Reconstruct the active formatting elements, if any. */
1345 $this->reconstructActiveFormattingElements();
1346
1347 $this->flag_frameset_ok = false;
1348
1349 $this->insertCDATAElement($token);
1350 break;
1351
1352 case 'iframe':
1353 $this->flag_frameset_ok = false;
1354 $this->insertCDATAElement($token);
1355 break;
1356
1357 case 'noembed': case 'noscript':
1358 // XSCRIPT: should check scripting flag
1359 $this->insertCDATAElement($token);
1360 break;
1361
1362 /* A start tag whose tag name is "select" */
1363 case 'select':
1364 /* Reconstruct the active formatting elements, if any. */
1365 $this->reconstructActiveFormattingElements();
1366
1367 /* Insert an HTML element for the token. */
1368 $this->insertElement($token);
1369
1370 $this->flag_frameset_ok = false;
1371
1372 /* If the insertion mode is one of in table", "in caption",
1373 * "in column group", "in table body", "in row", or "in
1374 * cell", then switch the insertion mode to "in select in
1375 * table". Otherwise, switch the insertion mode to "in
1376 * select". */
1377 if (
1378 $this->mode === self::IN_TABLE || $this->mode === self::IN_CAPTION ||
1379 $this->mode === self::IN_COLUMN_GROUP || $this->mode ==+self::IN_TABLE_BODY ||
1380 $this->mode === self::IN_ROW || $this->mode === self::IN_CELL
1381 ) {
1382 $this->mode = self::IN_SELECT_IN_TABLE;
1383 } else {
1384 $this->mode = self::IN_SELECT;
1385 }
1386 break;
1387
1388 case 'option': case 'optgroup':
1389 if ($this->elementInScope('option')) {
1390 $this->emitToken(array(
1391 'name' => 'option',
1392 'type' => HTML5_Tokenizer::ENDTAG,
1393 ));
1394 }
1395 $this->reconstructActiveFormattingElements();
1396 $this->insertElement($token);
1397 break;
1398
1399 case 'rp': case 'rt':
1400 /* If the stack of open elements has a ruby element in scope, then generate
1401 * implied end tags. If the current node is not then a ruby element, this is
1402 * a parse error; pop all the nodes from the current node up to the node
1403 * immediately before the bottommost ruby element on the stack of open elements.
1404 */
1405 if ($this->elementInScope('ruby')) {
1406 $this->generateImpliedEndTags();
1407 }
1408 $peek = false;
1409 do {
1410 if ($peek) {
1411 // parse error
1412 }
1413 $peek = array_pop($this->stack);
1414 } while ($peek->tagName !== 'ruby');
1415 $this->stack[] = $peek; // we popped one too many
1416 $this->insertElement($token);
1417 break;
1418
1419 // spec diversion
1420
1421 case 'math':
1422 $this->reconstructActiveFormattingElements();
1423 $token = $this->adjustMathMLAttributes($token);
1424 $token = $this->adjustForeignAttributes($token);
1425 $this->insertForeignElement($token, self::NS_MATHML);
1426 if (isset($token['self-closing'])) {
1427 // XERROR: acknowledge the token's self-closing flag
1428 array_pop($this->stack);
1429 }
1430 if ($this->mode !== self::IN_FOREIGN_CONTENT) {
1431 $this->secondary_mode = $this->mode;
1432 $this->mode = self::IN_FOREIGN_CONTENT;
1433 }
1434 break;
1435
1436 case 'svg':
1437 $this->reconstructActiveFormattingElements();
1438 $token = $this->adjustSVGAttributes($token);
1439 $token = $this->adjustForeignAttributes($token);
1440 $this->insertForeignElement($token, self::NS_SVG);
1441 if (isset($token['self-closing'])) {
1442 // XERROR: acknowledge the token's self-closing flag
1443 array_pop($this->stack);
1444 }
1445 if ($this->mode !== self::IN_FOREIGN_CONTENT) {
1446 $this->secondary_mode = $this->mode;
1447 $this->mode = self::IN_FOREIGN_CONTENT;
1448 }
1449 break;
1450
1451 case 'caption': case 'col': case 'colgroup': case 'frame': case 'head':
1452 case 'tbody': case 'td': case 'tfoot': case 'th': case 'thead': case 'tr':
1453 // parse error
1454 break;
1455
1456 /* A start tag token not covered by the previous entries */
1457 default:
1458 /* Reconstruct the active formatting elements, if any. */
1459 $this->reconstructActiveFormattingElements();
1460
1461 $this->insertElement($token);
1462 /* This element will be a phrasing element. */
1463 break;
1464 }
1465 break;
1466
1467 case HTML5_Tokenizer::ENDTAG:
1468 switch($token['name']) {
1469 /* An end tag with the tag name "body" */
1470 case 'body':
1471 /* If the stack of open elements does not have a body
1472 * element in scope, this is a parse error; ignore the
1473 * token. */
1474 if(!$this->elementInScope('body')) {
1475 $this->ignored = true;
1476
1477 /* Otherwise, if there is a node in the stack of open
1478 * elements that is not either a dc element, a dd element,
1479 * a ds element, a dt element, an li element, an optgroup
1480 * element, an option element, a p element, an rp element,
1481 * an rt element, a tbody element, a td element, a tfoot
1482 * element, a th element, a thead element, a tr element,
1483 * the body element, or the html element, then this is a
1484 * parse error.
1485 */
1486 } else {
1487 // XERROR: implement this check for parse error
1488 }
1489
1490 /* Change the insertion mode to "after body". */
1491 $this->mode = self::AFTER_BODY;
1492 break;
1493
1494 /* An end tag with the tag name "html" */
1495 case 'html':
1496 /* Act as if an end tag with tag name "body" had been seen,
1497 then, if that token wasn't ignored, reprocess the current
1498 token. */
1499 $this->emitToken(array(
1500 'name' => 'body',
1501 'type' => HTML5_Tokenizer::ENDTAG
1502 ));
1503
1504 if (!$this->ignored) $this->emitToken($token);
1505 break;
1506
1507 case 'address': case 'article': case 'aside': case 'blockquote':
1508 case 'center': case 'datagrid': case 'details': case 'dir':
1509 case 'div': case 'dl': case 'fieldset': case 'footer':
1510 case 'header': case 'hgroup': case 'listing': case 'menu':
1511 case 'nav': case 'ol': case 'pre': case 'section': case 'ul':
1512 /* If the stack of open elements has an element in scope
1513 with the same tag name as that of the token, then generate
1514 implied end tags. */
1515 if($this->elementInScope($token['name'])) {
1516 $this->generateImpliedEndTags();
1517
1518 /* Now, if the current node is not an element with
1519 the same tag name as that of the token, then this
1520 is a parse error. */
1521 // XERROR: implement parse error logic
1522
1523 /* If the stack of open elements has an element in
1524 scope with the same tag name as that of the token,
1525 then pop elements from this stack until an element
1526 with that tag name has been popped from the stack. */
1527 do {
1528 $node = array_pop($this->stack);
1529 } while ($node->tagName !== $token['name']);
1530 } else {
1531 // parse error
1532 }
1533 break;
1534
1535 /* An end tag whose tag name is "form" */
1536 case 'form':
1537 /* Let node be the element that the form element pointer is set to. */
1538 $node = $this->form_pointer;
1539 /* Set the form element pointer to null. */
1540 $this->form_pointer = null;
1541 /* If node is null or the stack of open elements does not
1542 * have node in scope, then this is a parse error; ignore the token. */
1543 if ($node === null || !in_array($node, $this->stack)) {
1544 // parse error
1545 $this->ignored = true;
1546 } else {
1547 /* 1. Generate implied end tags. */
1548 $this->generateImpliedEndTags();
1549 /* 2. If the current node is not node, then this is a parse error. */
1550 if (end($this->stack) !== $node) {
1551 // parse error
1552 }
1553 /* 3. Remove node from the stack of open elements. */
1554 array_splice($this->stack, array_search($node, $this->stack, true), 1);
1555 }
1556
1557 break;
1558
1559 /* An end tag whose tag name is "p" */
1560 case 'p':
1561 /* If the stack of open elements has a p element in scope,
1562 then generate implied end tags, except for p elements. */
1563 if($this->elementInScope('p')) {
1564 /* Generate implied end tags, except for elements with
1565 * the same tag name as the token. */
1566 $this->generateImpliedEndTags(array('p'));
1567
1568 /* If the current node is not a p element, then this is
1569 a parse error. */
1570 // XERROR: implement
1571
1572 /* Pop elements from the stack of open elements until
1573 * an element with the same tag name as the token has
1574 * been popped from the stack. */
1575 do {
1576 $node = array_pop($this->stack);
1577 } while ($node->tagName !== 'p');
1578
1579 } else {
1580 // parse error
1581 $this->emitToken(array(
1582 'name' => 'p',
1583 'type' => HTML5_Tokenizer::STARTTAG,
1584 ));
1585 $this->emitToken($token);
1586 }
1587 break;
1588
1589 /* An end tag whose tag name is "li" */
1590 case 'li':
1591 /* If the stack of open elements does not have an element
1592 * in list item scope with the same tag name as that of the
1593 * token, then this is a parse error; ignore the token. */
1594 if ($this->elementInScope($token['name'], self::SCOPE_LISTITEM)) {
1595 /* Generate implied end tags, except for elements with the
1596 * same tag name as the token. */
1597 $this->generateImpliedEndTags(array($token['name']));
1598 /* If the current node is not an element with the same tag
1599 * name as that of the token, then this is a parse error. */
1600 // XERROR: parse error
1601 /* Pop elements from the stack of open elements until an
1602 * element with the same tag name as the token has been
1603 * popped from the stack. */
1604 do {
1605 $node = array_pop($this->stack);
1606 } while ($node->tagName !== $token['name']);
1607 } else {
1608 // XERROR: parse error
1609 }
1610 break;
1611
1612 /* An end tag whose tag name is "dc", "dd", "ds", "dt" */
1613 case 'dc': case 'dd': case 'ds': case 'dt':
1614 if($this->elementInScope($token['name'])) {
1615 $this->generateImpliedEndTags(array($token['name']));
1616
1617 /* If the current node is not an element with the same
1618 tag name as the token, then this is a parse error. */
1619 // XERROR: implement parse error
1620
1621 /* Pop elements from the stack of open elements until
1622 * an element with the same tag name as the token has
1623 * been popped from the stack. */
1624 do {
1625 $node = array_pop($this->stack);
1626 } while ($node->tagName !== $token['name']);
1627
1628 } else {
1629 // XERROR: parse error
1630 }
1631 break;
1632
1633 /* An end tag whose tag name is one of: "h1", "h2", "h3", "h4",
1634 "h5", "h6" */
1635 case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6':
1636 $elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6');
1637
1638 /* If the stack of open elements has in scope an element whose
1639 tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then
1640 generate implied end tags. */
1641 if($this->elementInScope($elements)) {
1642 $this->generateImpliedEndTags();
1643
1644 /* Now, if the current node is not an element with the same
1645 tag name as that of the token, then this is a parse error. */
1646 // XERROR: implement parse error
1647
1648 /* If the stack of open elements has in scope an element
1649 whose tag name is one of "h1", "h2", "h3", "h4", "h5", or
1650 "h6", then pop elements from the stack until an element
1651 with one of those tag names has been popped from the stack. */
1652 do {
1653 $node = array_pop($this->stack);
1654 } while (!in_array($node->tagName, $elements));
1655 } else {
1656 // parse error
1657 }
1658 break;
1659
1660 /* An end tag whose tag name is one of: "a", "b", "big", "em",
1661 "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u" */
1662 case 'a': case 'b': case 'big': case 'code': case 'em': case 'font':
1663 case 'i': case 'nobr': case 's': case 'small': case 'strike':
1664 case 'strong': case 'tt': case 'u':
1665 // XERROR: generally speaking this needs parse error logic
1666 /* 1. Let the formatting element be the last element in
1667 the list of active formatting elements that:
1668 * is between the end of the list and the last scope
1669 marker in the list, if any, or the start of the list
1670 otherwise, and
1671 * has the same tag name as the token.
1672 */
1673 while(true) {
1674 for($a = count($this->a_formatting) - 1; $a >= 0; $a--) {
1675 if($this->a_formatting[$a] === self::MARKER) {
1676 break;
1677
1678 } elseif($this->a_formatting[$a]->tagName === $token['name']) {
1679 $formatting_element = $this->a_formatting[$a];
1680 $in_stack = in_array($formatting_element, $this->stack, true);
1681 $fe_af_pos = $a;
1682 break;
1683 }
1684 }
1685
1686 /* If there is no such node, or, if that node is
1687 also in the stack of open elements but the element
1688 is not in scope, then this is a parse error. Abort
1689 these steps. The token is ignored. */
1690 if(!isset($formatting_element) || ($in_stack &&
1691 !$this->elementInScope($token['name']))) {
1692 $this->ignored = true;
1693 break;
1694
1695 /* Otherwise, if there is such a node, but that node
1696 is not in the stack of open elements, then this is a
1697 parse error; remove the element from the list, and
1698 abort these steps. */
1699 } elseif(isset($formatting_element) && !$in_stack) {
1700 unset($this->a_formatting[$fe_af_pos]);
1701 $this->a_formatting = array_merge($this->a_formatting);
1702 break;
1703 }
1704
1705 /* Otherwise, there is a formatting element and that
1706 * element is in the stack and is in scope. If the
1707 * element is not the current node, this is a parse
1708 * error. In any case, proceed with the algorithm as
1709 * written in the following steps. */
1710 // XERROR: implement me
1711
1712 /* 2. Let the furthest block be the topmost node in the
1713 stack of open elements that is lower in the stack
1714 than the formatting element, and is not an element in
1715 the phrasing or formatting categories. There might
1716 not be one. */
1717 $fe_s_pos = array_search($formatting_element, $this->stack, true);
1718 $length = count($this->stack);
1719
1720 for($s = $fe_s_pos + 1; $s < $length; $s++) {
1721 $category = $this->getElementCategory($this->stack[$s]);
1722
1723 if($category !== self::PHRASING && $category !== self::FORMATTING) {
1724 $furthest_block = $this->stack[$s];
1725 break;
1726 }
1727 }
1728
1729 /* 3. If there is no furthest block, then the UA must
1730 skip the subsequent steps and instead just pop all
1731 the nodes from the bottom of the stack of open
1732 elements, from the current node up to the formatting
1733 element, and remove the formatting element from the
1734 list of active formatting elements. */
1735 if(!isset($furthest_block)) {
1736 for($n = $length - 1; $n >= $fe_s_pos; $n--) {
1737 array_pop($this->stack);
1738 }
1739
1740 unset($this->a_formatting[$fe_af_pos]);
1741 $this->a_formatting = array_merge($this->a_formatting);
1742 break;
1743 }
1744
1745 /* 4. Let the common ancestor be the element
1746 immediately above the formatting element in the stack
1747 of open elements. */
1748 $common_ancestor = $this->stack[$fe_s_pos - 1];
1749
1750 /* 5. Let a bookmark note the position of the
1751 formatting element in the list of active formatting
1752 elements relative to the elements on either side
1753 of it in the list. */
1754 $bookmark = $fe_af_pos;
1755
1756 /* 6. Let node and last node be the furthest block.
1757 Follow these steps: */
1758 $node = $furthest_block;
1759 $last_node = $furthest_block;
1760
1761 while(true) {
1762 for($n = array_search($node, $this->stack, true) - 1; $n >= 0; $n--) {
1763 /* 6.1 Let node be the element immediately
1764 prior to node in the stack of open elements. */
1765 $node = $this->stack[$n];
1766
1767 /* 6.2 If node is not in the list of active
1768 formatting elements, then remove node from
1769 the stack of open elements and then go back
1770 to step 1. */
1771 if(!in_array($node, $this->a_formatting, true)) {
1772 array_splice($this->stack, $n, 1);
1773
1774 } else {
1775 break;
1776 }
1777 }
1778
1779 /* 6.3 Otherwise, if node is the formatting
1780 element, then go to the next step in the overall
1781 algorithm. */
1782 if($node === $formatting_element) {
1783 break;
1784
1785 /* 6.4 Otherwise, if last node is the furthest
1786 block, then move the aforementioned bookmark to
1787 be immediately after the node in the list of
1788 active formatting elements. */
1789 } elseif($last_node === $furthest_block) {
1790 $bookmark = array_search($node, $this->a_formatting, true) + 1;
1791 }
1792
1793 /* 6.5 Create an element for the token for which
1794 * the element node was created, replace the entry
1795 * for node in the list of active formatting
1796 * elements with an entry for the new element,
1797 * replace the entry for node in the stack of open
1798 * elements with an entry for the new element, and
1799 * let node be the new element. */
1800 // we don't know what the token is anymore
1801 // XDOM
1802 $clone = $node->cloneNode();
1803 $a_pos = array_search($node, $this->a_formatting, true);
1804 $s_pos = array_search($node, $this->stack, true);
1805 $this->a_formatting[$a_pos] = $clone;
1806 $this->stack[$s_pos] = $clone;
1807 $node = $clone;
1808
1809 /* 6.6 Insert last node into node, first removing
1810 it from its previous parent node if any. */
1811 // XDOM
1812 if($last_node->parentNode !== null) {
1813 $last_node->parentNode->removeChild($last_node);
1814 }
1815
1816 // XDOM
1817 $node->appendChild($last_node);
1818
1819 /* 6.7 Let last node be node. */
1820 $last_node = $node;
1821
1822 /* 6.8 Return to step 1 of this inner set of steps. */
1823 }
1824
1825 /* 7. If the common ancestor node is a table, tbody,
1826 * tfoot, thead, or tr element, then, foster parent
1827 * whatever last node ended up being in the previous
1828 * step, first removing it from its previous parent
1829 * node if any. */
1830 // XDOM
1831 if ($last_node->parentNode) { // common step
1832 $last_node->parentNode->removeChild($last_node);
1833 }
1834 if (in_array($common_ancestor->tagName, array('table', 'tbody', 'tfoot', 'thead', 'tr'))) {
1835 $this->fosterParent($last_node);
1836 /* Otherwise, append whatever last node ended up being
1837 * in the previous step to the common ancestor node,
1838 * first removing it from its previous parent node if
1839 * any. */
1840 } else {
1841 // XDOM
1842 $common_ancestor->appendChild($last_node);
1843 }
1844
1845 /* 8. Create an element for the token for which the
1846 * formatting element was created. */
1847 // XDOM
1848 $clone = $formatting_element->cloneNode();
1849
1850 /* 9. Take all of the child nodes of the furthest
1851 block and append them to the element created in the
1852 last step. */
1853 // XDOM
1854 while($furthest_block->hasChildNodes()) {
1855 $child = $furthest_block->firstChild;
1856 $furthest_block->removeChild($child);
1857 $clone->appendChild($child);
1858 }
1859
1860 /* 10. Append that clone to the furthest block. */
1861 // XDOM
1862 $furthest_block->appendChild($clone);
1863
1864 /* 11. Remove the formatting element from the list
1865 of active formatting elements, and insert the new element
1866 into the list of active formatting elements at the
1867 position of the aforementioned bookmark. */
1868 $fe_af_pos = array_search($formatting_element, $this->a_formatting, true);
1869 array_splice($this->a_formatting, $fe_af_pos, 1);
1870
1871 $af_part1 = array_slice($this->a_formatting, 0, $bookmark - 1);
1872 $af_part2 = array_slice($this->a_formatting, $bookmark);
1873 $this->a_formatting = array_merge($af_part1, array($clone), $af_part2);
1874
1875 /* 12. Remove the formatting element from the stack
1876 of open elements, and insert the new element into the stack
1877 of open elements immediately below the position of the
1878 furthest block in that stack. */
1879 $fe_s_pos = array_search($formatting_element, $this->stack, true);
1880 array_splice($this->stack, $fe_s_pos, 1);
1881
1882 $fb_s_pos = array_search($furthest_block, $this->stack, true);
1883 $s_part1 = array_slice($this->stack, 0, $fb_s_pos + 1);
1884 $s_part2 = array_slice($this->stack, $fb_s_pos + 1);
1885 $this->stack = array_merge($s_part1, array($clone), $s_part2);
1886
1887 /* 13. Jump back to step 1 in this series of steps. */
1888 unset($formatting_element, $fe_af_pos, $fe_s_pos, $furthest_block);
1889 }
1890 break;
1891
1892 case 'applet': case 'button': case 'marquee': case 'object':
1893 /* If the stack of open elements has an element in scope whose
1894 tag name matches the tag name of the token, then generate implied
1895 tags. */
1896 if($this->elementInScope($token['name'])) {
1897 $this->generateImpliedEndTags();
1898
1899 /* Now, if the current node is not an element with the same
1900 tag name as the token, then this is a parse error. */
1901 // XERROR: implement logic
1902
1903 /* Pop elements from the stack of open elements until
1904 * an element with the same tag name as the token has
1905 * been popped from the stack. */
1906 do {
1907 $node = array_pop($this->stack);
1908 } while ($node->tagName !== $token['name']);
1909
1910 /* Clear the list of active formatting elements up to the
1911 * last marker. */
1912 $keys = array_keys($this->a_formatting, self::MARKER, true);
1913 $marker = end($keys);
1914
1915 for($n = count($this->a_formatting) - 1; $n > $marker; $n--) {
1916 array_pop($this->a_formatting);
1917 }
1918 } else {
1919 // parse error
1920 }
1921 break;
1922
1923 case 'br':
1924 // Parse error
1925 $this->emitToken(array(
1926 'name' => 'br',
1927 'type' => HTML5_Tokenizer::STARTTAG,
1928 ));
1929 break;
1930
1931 /* An end tag token not covered by the previous entries */
1932 default:
1933 for($n = count($this->stack) - 1; $n >= 0; $n--) {
1934 /* Initialise node to be the current node (the bottommost
1935 node of the stack). */
1936 $node = $this->stack[$n];
1937
1938 /* If node has the same tag name as the end tag token,
1939 then: */
1940 if($token['name'] === $node->tagName) {
1941 /* Generate implied end tags. */
1942 $this->generateImpliedEndTags();
1943
1944 /* If the tag name of the end tag token does not
1945 match the tag name of the current node, this is a
1946 parse error. */
1947 // XERROR: implement this
1948
1949 /* Pop all the nodes from the current node up to
1950 node, including node, then stop these steps. */
1951 // XSKETCHY
1952 do {
1953 $pop = array_pop($this->stack);
1954 } while ($pop !== $node);
1955 break;
1956
1957 } else {
1958 $category = $this->getElementCategory($node);
1959
1960 if($category !== self::FORMATTING && $category !== self::PHRASING) {
1961 /* Otherwise, if node is in neither the formatting
1962 category nor the phrasing category, then this is a
1963 parse error. Stop this algorithm. The end tag token
1964 is ignored. */
1965 $this->ignored = true;
1966 break;
1967 // parse error
1968 }
1969 }
1970 /* Set node to the previous entry in the stack of open elements. Loop. */
1971 }
1972 break;
1973 }
1974 break;
1975 }
1976 break;
1977
1978 case self::IN_CDATA_RCDATA:
1979 if (
1980 $token['type'] === HTML5_Tokenizer::CHARACTER ||
1981 $token['type'] === HTML5_Tokenizer::SPACECHARACTER
1982 ) {
1983 $this->insertText($token['data']);
1984 } elseif ($token['type'] === HTML5_Tokenizer::EOF) {
1985 // parse error
1986 /* If the current node is a script element, mark the script
1987 * element as "already executed". */
1988 // probably not necessary
1989 array_pop($this->stack);
1990 $this->mode = $this->original_mode;
1991 $this->emitToken($token);
1992 } elseif ($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'script') {
1993 array_pop($this->stack);
1994 $this->mode = $this->original_mode;
1995 // we're ignoring all of the execution stuff
1996 } elseif ($token['type'] === HTML5_Tokenizer::ENDTAG) {
1997 array_pop($this->stack);
1998 $this->mode = $this->original_mode;
1999 }
2000 break;
2001
2002 case self::IN_TABLE:
2003 $clear = array('html', 'table');
2004
2005 /* A character token */
2006 if ($token['type'] === HTML5_Tokenizer::CHARACTER ||
2007 $token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
2008 /* Let the pending table character tokens
2009 * be an empty list of tokens. */
2010 $this->pendingTableCharacters = "";
2011 $this->pendingTableCharactersDirty = false;
2012 /* Let the original insertion mode be the current
2013 * insertion mode. */
2014 $this->original_mode = $this->mode;
2015 /* Switch the insertion mode to
2016 * "in table text" and
2017 * reprocess the token. */
2018 $this->mode = self::IN_TABLE_TEXT;
2019 $this->emitToken($token);
2020
2021 /* A comment token */
2022 } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
2023 /* Append a Comment node to the current node with the data
2024 attribute set to the data given in the comment token. */
2025 $this->insertComment($token['data']);
2026
2027 } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
2028 // parse error
2029
2030 /* A start tag whose tag name is "caption" */
2031 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
2032 $token['name'] === 'caption') {
2033 /* Clear the stack back to a table context. */
2034 $this->clearStackToTableContext($clear);
2035
2036 /* Insert a marker at the end of the list of active
2037 formatting elements. */
2038 $this->a_formatting[] = self::MARKER;
2039
2040 /* Insert an HTML element for the token, then switch the
2041 insertion mode to "in caption". */
2042 $this->insertElement($token);
2043 $this->mode = self::IN_CAPTION;
2044
2045 /* A start tag whose tag name is "colgroup" */
2046 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
2047 $token['name'] === 'colgroup') {
2048 /* Clear the stack back to a table context. */
2049 $this->clearStackToTableContext($clear);
2050
2051 /* Insert an HTML element for the token, then switch the
2052 insertion mode to "in column group". */
2053 $this->insertElement($token);
2054 $this->mode = self::IN_COLUMN_GROUP;
2055
2056 /* A start tag whose tag name is "col" */
2057 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
2058 $token['name'] === 'col') {
2059 $this->emitToken(array(
2060 'name' => 'colgroup',
2061 'type' => HTML5_Tokenizer::STARTTAG,
2062 'attr' => array()
2063 ));
2064
2065 $this->emitToken($token);
2066
2067 /* A start tag whose tag name is one of: "tbody", "tfoot", "thead" */
2068 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],
2069 array('tbody', 'tfoot', 'thead'))) {
2070 /* Clear the stack back to a table context. */
2071 $this->clearStackToTableContext($clear);
2072
2073 /* Insert an HTML element for the token, then switch the insertion
2074 mode to "in table body". */
2075 $this->insertElement($token);
2076 $this->mode = self::IN_TABLE_BODY;
2077
2078 /* A start tag whose tag name is one of: "td", "th", "tr" */
2079 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
2080 in_array($token['name'], array('td', 'th', 'tr'))) {
2081 /* Act as if a start tag token with the tag name "tbody" had been
2082 seen, then reprocess the current token. */
2083 $this->emitToken(array(
2084 'name' => 'tbody',
2085 'type' => HTML5_Tokenizer::STARTTAG,
2086 'attr' => array()
2087 ));
2088
2089 $this->emitToken($token);
2090
2091 /* A start tag whose tag name is "table" */
2092 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
2093 $token['name'] === 'table') {
2094 /* Parse error. Act as if an end tag token with the tag name "table"
2095 had been seen, then, if that token wasn't ignored, reprocess the
2096 current token. */
2097 $this->emitToken(array(
2098 'name' => 'table',
2099 'type' => HTML5_Tokenizer::ENDTAG
2100 ));
2101
2102 if (!$this->ignored) $this->emitToken($token);
2103
2104 /* An end tag whose tag name is "table" */
2105 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
2106 $token['name'] === 'table') {
2107 /* If the stack of open elements does not have an element in table
2108 scope with the same tag name as the token, this is a parse error.
2109 Ignore the token. (fragment case) */
2110 if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
2111 $this->ignored = true;
2112
2113 /* Otherwise: */
2114 } else {
2115 do {
2116 $node = array_pop($this->stack);
2117 } while ($node->tagName !== 'table');
2118
2119 /* Reset the insertion mode appropriately. */
2120 $this->resetInsertionMode();
2121 }
2122
2123 /* An end tag whose tag name is one of: "body", "caption", "col",
2124 "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr" */
2125 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],
2126 array('body', 'caption', 'col', 'colgroup', 'html', 'tbody', 'td',
2127 'tfoot', 'th', 'thead', 'tr'))) {
2128 // Parse error. Ignore the token.
2129
2130 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
2131 ($token['name'] === 'style' || $token['name'] === 'script')) {
2132 $this->processWithRulesFor($token, self::IN_HEAD);
2133
2134 } elseif ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'input' &&
2135 // assignment is intentional
2136 /* If the token does not have an attribute with the name "type", or
2137 * if it does, but that attribute's value is not an ASCII
2138 * case-insensitive match for the string "hidden", then: act as
2139 * described in the "anything else" entry below. */
2140 ($type = $this->getAttr($token, 'type')) && strtolower($type) === 'hidden') {
2141 // I.e., if its an input with the type attribute == 'hidden'
2142 /* Otherwise */
2143 // parse error
2144 $this->insertElement($token);
2145 array_pop($this->stack);
2146 } elseif ($token['type'] === HTML5_Tokenizer::EOF) {
2147 /* If the current node is not the root html element, then this is a parse error. */
2148 if (end($this->stack)->tagName !== 'html') {
2149 // Note: It can only be the current node in the fragment case.
2150 // parse error
2151 }
2152 /* Stop parsing. */
2153 /* Anything else */
2154 } else {
2155 /* Parse error. Process the token as if the insertion mode was "in
2156 body", with the following exception: */
2157
2158 $old = $this->foster_parent;
2159 $this->foster_parent = true;
2160 $this->processWithRulesFor($token, self::IN_BODY);
2161 $this->foster_parent = $old;
2162 }
2163 break;
2164
2165 case self::IN_TABLE_TEXT:
2166 /* A character token */
2167 if($token['type'] === HTML5_Tokenizer::CHARACTER) {
2168 /* Append the character token to the pending table
2169 * character tokens list. */
2170 $this->pendingTableCharacters .= $token['data'];
2171 $this->pendingTableCharactersDirty = true;
2172 } elseif ($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
2173 $this->pendingTableCharacters .= $token['data'];
2174 /* Anything else */
2175 } else {
2176 if ($this->pendingTableCharacters !== '' && is_string($this->pendingTableCharacters)) {
2177 /* If any of the tokens in the pending table character tokens list
2178 * are character tokens that are not one of U+0009 CHARACTER
2179 * TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or
2180 * U+0020 SPACE, then reprocess those character tokens using the
2181 * rules given in the "anything else" entry in the in table"
2182 * insertion mode.*/
2183 if ($this->pendingTableCharactersDirty) {
2184 /* Parse error. Process the token using the rules for the
2185 * "in body" insertion mode, except that if the current
2186 * node is a table, tbody, tfoot, thead, or tr element,
2187 * then, whenever a node would be inserted into the current
2188 * node, it must instead be foster parented. */
2189 // XERROR
2190 $old = $this->foster_parent;
2191 $this->foster_parent = true;
2192 $text_token = array(
2193 'type' => HTML5_Tokenizer::CHARACTER,
2194 'data' => $this->pendingTableCharacters,
2195 );
2196 $this->processWithRulesFor($text_token, self::IN_BODY);
2197 $this->foster_parent = $old;
2198
2199 /* Otherwise, insert the characters given by the pending table
2200 * character tokens list into the current node. */
2201 } else {
2202 $this->insertText($this->pendingTableCharacters);
2203 }
2204 $this->pendingTableCharacters = null;
2205 $this->pendingTableCharactersNull = null;
2206 }
2207
2208 /* Switch the insertion mode to the original insertion mode and
2209 * reprocess the token.
2210 */
2211 $this->mode = $this->original_mode;
2212 $this->emitToken($token);
2213 }
2214 break;
2215
2216 case self::IN_CAPTION:
2217 /* An end tag whose tag name is "caption" */
2218 if($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'caption') {
2219 /* If the stack of open elements does not have an element in table
2220 scope with the same tag name as the token, this is a parse error.
2221 Ignore the token. (fragment case) */
2222 if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
2223 $this->ignored = true;
2224 // Ignore
2225
2226 /* Otherwise: */
2227 } else {
2228 /* Generate implied end tags. */
2229 $this->generateImpliedEndTags();
2230
2231 /* Now, if the current node is not a caption element, then this
2232 is a parse error. */
2233 // XERROR: implement
2234
2235 /* Pop elements from this stack until a caption element has
2236 been popped from the stack. */
2237 do {
2238 $node = array_pop($this->stack);
2239 } while ($node->tagName !== 'caption');
2240
2241 /* Clear the list of active formatting elements up to the last
2242 marker. */
2243 $this->clearTheActiveFormattingElementsUpToTheLastMarker();
2244
2245 /* Switch the insertion mode to "in table". */
2246 $this->mode = self::IN_TABLE;
2247 }
2248
2249 /* A start tag whose tag name is one of: "caption", "col", "colgroup",
2250 "tbody", "td", "tfoot", "th", "thead", "tr", or an end tag whose tag
2251 name is "table" */
2252 } elseif(($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],
2253 array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th',
2254 'thead', 'tr'))) || ($token['type'] === HTML5_Tokenizer::ENDTAG &&
2255 $token['name'] === 'table')) {
2256 /* Parse error. Act as if an end tag with the tag name "caption"
2257 had been seen, then, if that token wasn't ignored, reprocess the
2258 current token. */
2259 $this->emitToken(array(
2260 'name' => 'caption',
2261 'type' => HTML5_Tokenizer::ENDTAG
2262 ));
2263
2264 if (!$this->ignored) $this->emitToken($token);
2265
2266 /* An end tag whose tag name is one of: "body", "col", "colgroup",
2267 "html", "tbody", "td", "tfoot", "th", "thead", "tr" */
2268 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],
2269 array('body', 'col', 'colgroup', 'html', 'tbody', 'tfoot', 'th',
2270 'thead', 'tr'))) {
2271 // Parse error. Ignore the token.
2272 $this->ignored = true;
2273
2274 /* Anything else */
2275 } else {
2276 /* Process the token as if the insertion mode was "in body". */
2277 $this->processWithRulesFor($token, self::IN_BODY);
2278 }
2279 break;
2280
2281 case self::IN_COLUMN_GROUP:
2282 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
2283 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
2284 or U+0020 SPACE */
2285 if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
2286 /* Append the character to the current node. */
2287 $this->insertText($token['data']);
2288
2289 /* A comment token */
2290 } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
2291 /* Append a Comment node to the current node with the data
2292 attribute set to the data given in the comment token. */
2293 $this->insertToken($token['data']);
2294
2295 } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
2296 // parse error
2297
2298 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {
2299 $this->processWithRulesFor($token, self::IN_BODY);
2300
2301 /* A start tag whose tag name is "col" */
2302 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'col') {
2303 /* Insert a col element for the token. Immediately pop the current
2304 node off the stack of open elements. */
2305 $this->insertElement($token);
2306 array_pop($this->stack);
2307 // XERROR: Acknowledge the token's self-closing flag, if it is set.
2308
2309 /* An end tag whose tag name is "colgroup" */
2310 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
2311 $token['name'] === 'colgroup') {
2312 /* If the current node is the root html element, then this is a
2313 parse error, ignore the token. (fragment case) */
2314 if(end($this->stack)->tagName === 'html') {
2315 $this->ignored = true;
2316
2317 /* Otherwise, pop the current node (which will be a colgroup
2318 element) from the stack of open elements. Switch the insertion
2319 mode to "in table". */
2320 } else {
2321 array_pop($this->stack);
2322 $this->mode = self::IN_TABLE;
2323 }
2324
2325 /* An end tag whose tag name is "col" */
2326 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'col') {
2327 /* Parse error. Ignore the token. */
2328 $this->ignored = true;
2329
2330 /* An end-of-file token */
2331 /* If the current node is the root html element */
2332 } elseif($token['type'] === HTML5_Tokenizer::EOF && end($this->stack)->tagName === 'html') {
2333 /* Stop parsing */
2334
2335 /* Anything else */
2336 } else {
2337 /* Act as if an end tag with the tag name "colgroup" had been seen,
2338 and then, if that token wasn't ignored, reprocess the current token. */
2339 $this->emitToken(array(
2340 'name' => 'colgroup',
2341 'type' => HTML5_Tokenizer::ENDTAG
2342 ));
2343
2344 if (!$this->ignored) $this->emitToken($token);
2345 }
2346 break;
2347
2348 case self::IN_TABLE_BODY:
2349 $clear = array('tbody', 'tfoot', 'thead', 'html');
2350
2351 /* A start tag whose tag name is "tr" */
2352 if($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'tr') {
2353 /* Clear the stack back to a table body context. */
2354 $this->clearStackToTableContext($clear);
2355
2356 /* Insert a tr element for the token, then switch the insertion
2357 mode to "in row". */
2358 $this->insertElement($token);
2359 $this->mode = self::IN_ROW;
2360
2361 /* A start tag whose tag name is one of: "th", "td" */
2362 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
2363 ($token['name'] === 'th' || $token['name'] === 'td')) {
2364 /* Parse error. Act as if a start tag with the tag name "tr" had
2365 been seen, then reprocess the current token. */
2366 $this->emitToken(array(
2367 'name' => 'tr',
2368 'type' => HTML5_Tokenizer::STARTTAG,
2369 'attr' => array()
2370 ));
2371
2372 $this->emitToken($token);
2373
2374 /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */
2375 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
2376 in_array($token['name'], array('tbody', 'tfoot', 'thead'))) {
2377 /* If the stack of open elements does not have an element in table
2378 scope with the same tag name as the token, this is a parse error.
2379 Ignore the token. */
2380 if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
2381 // Parse error
2382 $this->ignored = true;
2383
2384 /* Otherwise: */
2385 } else {
2386 /* Clear the stack back to a table body context. */
2387 $this->clearStackToTableContext($clear);
2388
2389 /* Pop the current node from the stack of open elements. Switch
2390 the insertion mode to "in table". */
2391 array_pop($this->stack);
2392 $this->mode = self::IN_TABLE;
2393 }
2394
2395 /* A start tag whose tag name is one of: "caption", "col", "colgroup",
2396 "tbody", "tfoot", "thead", or an end tag whose tag name is "table" */
2397 } elseif(($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],
2398 array('caption', 'col', 'colgroup', 'tbody', 'tfoot', 'thead'))) ||
2399 ($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'table')) {
2400 /* If the stack of open elements does not have a tbody, thead, or
2401 tfoot element in table scope, this is a parse error. Ignore the
2402 token. (fragment case) */
2403 if(!$this->elementInScope(array('tbody', 'thead', 'tfoot'), self::SCOPE_TABLE)) {
2404 // parse error
2405 $this->ignored = true;
2406
2407 /* Otherwise: */
2408 } else {
2409 /* Clear the stack back to a table body context. */
2410 $this->clearStackToTableContext($clear);
2411
2412 /* Act as if an end tag with the same tag name as the current
2413 node ("tbody", "tfoot", or "thead") had been seen, then
2414 reprocess the current token. */
2415 $this->emitToken(array(
2416 'name' => end($this->stack)->tagName,
2417 'type' => HTML5_Tokenizer::ENDTAG
2418 ));
2419
2420 $this->emitToken($token);
2421 }
2422
2423 /* An end tag whose tag name is one of: "body", "caption", "col",
2424 "colgroup", "html", "td", "th", "tr" */
2425 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],
2426 array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th', 'tr'))) {
2427 /* Parse error. Ignore the token. */
2428 $this->ignored = true;
2429
2430 /* Anything else */
2431 } else {
2432 /* Process the token as if the insertion mode was "in table". */
2433 $this->processWithRulesFor($token, self::IN_TABLE);
2434 }
2435 break;
2436
2437 case self::IN_ROW:
2438 $clear = array('tr', 'html');
2439
2440 /* A start tag whose tag name is one of: "th", "td" */
2441 if($token['type'] === HTML5_Tokenizer::STARTTAG &&
2442 ($token['name'] === 'th' || $token['name'] === 'td')) {
2443 /* Clear the stack back to a table row context. */
2444 $this->clearStackToTableContext($clear);
2445
2446 /* Insert an HTML element for the token, then switch the insertion
2447 mode to "in cell". */
2448 $this->insertElement($token);
2449 $this->mode = self::IN_CELL;
2450
2451 /* Insert a marker at the end of the list of active formatting
2452 elements. */
2453 $this->a_formatting[] = self::MARKER;
2454
2455 /* An end tag whose tag name is "tr" */
2456 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'tr') {
2457 /* If the stack of open elements does not have an element in table
2458 scope with the same tag name as the token, this is a parse error.
2459 Ignore the token. (fragment case) */
2460 if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
2461 // Ignore.
2462 $this->ignored = true;
2463
2464 /* Otherwise: */
2465 } else {
2466 /* Clear the stack back to a table row context. */
2467 $this->clearStackToTableContext($clear);
2468
2469 /* Pop the current node (which will be a tr element) from the
2470 stack of open elements. Switch the insertion mode to "in table
2471 body". */
2472 array_pop($this->stack);
2473 $this->mode = self::IN_TABLE_BODY;
2474 }
2475
2476 /* A start tag whose tag name is one of: "caption", "col", "colgroup",
2477 "tbody", "tfoot", "thead", "tr" or an end tag whose tag name is "table" */
2478 } elseif(($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],
2479 array('caption', 'col', 'colgroup', 'tbody', 'tfoot', 'thead', 'tr'))) ||
2480 ($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'table')) {
2481 /* Act as if an end tag with the tag name "tr" had been seen, then,
2482 if that token wasn't ignored, reprocess the current token. */
2483 $this->emitToken(array(
2484 'name' => 'tr',
2485 'type' => HTML5_Tokenizer::ENDTAG
2486 ));
2487 if (!$this->ignored) $this->emitToken($token);
2488
2489 /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */
2490 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
2491 in_array($token['name'], array('tbody', 'tfoot', 'thead'))) {
2492 /* If the stack of open elements does not have an element in table
2493 scope with the same tag name as the token, this is a parse error.
2494 Ignore the token. */
2495 if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
2496 $this->ignored = true;
2497
2498 /* Otherwise: */
2499 } else {
2500 /* Otherwise, act as if an end tag with the tag name "tr" had
2501 been seen, then reprocess the current token. */
2502 $this->emitToken(array(
2503 'name' => 'tr',
2504 'type' => HTML5_Tokenizer::ENDTAG
2505 ));
2506
2507 $this->emitToken($token);
2508 }
2509
2510 /* An end tag whose tag name is one of: "body", "caption", "col",
2511 "colgroup", "html", "td", "th" */
2512 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],
2513 array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th'))) {
2514 /* Parse error. Ignore the token. */
2515 $this->ignored = true;
2516
2517 /* Anything else */
2518 } else {
2519 /* Process the token as if the insertion mode was "in table". */
2520 $this->processWithRulesFor($token, self::IN_TABLE);
2521 }
2522 break;
2523
2524 case self::IN_CELL:
2525 /* An end tag whose tag name is one of: "td", "th" */
2526 if($token['type'] === HTML5_Tokenizer::ENDTAG &&
2527 ($token['name'] === 'td' || $token['name'] === 'th')) {
2528 /* If the stack of open elements does not have an element in table
2529 scope with the same tag name as that of the token, then this is a
2530 parse error and the token must be ignored. */
2531 if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
2532 $this->ignored = true;
2533
2534 /* Otherwise: */
2535 } else {
2536 /* Generate implied end tags, except for elements with the same
2537 tag name as the token. */
2538 $this->generateImpliedEndTags(array($token['name']));
2539
2540 /* Now, if the current node is not an element with the same tag
2541 name as the token, then this is a parse error. */
2542 // XERROR: Implement parse error code
2543
2544 /* Pop elements from this stack until an element with the same
2545 tag name as the token has been popped from the stack. */
2546 do {
2547 $node = array_pop($this->stack);
2548 } while ($node->tagName !== $token['name']);
2549
2550 /* Clear the list of active formatting elements up to the last
2551 marker. */
2552 $this->clearTheActiveFormattingElementsUpToTheLastMarker();
2553
2554 /* Switch the insertion mode to "in row". (The current node
2555 will be a tr element at this point.) */
2556 $this->mode = self::IN_ROW;
2557 }
2558
2559 /* A start tag whose tag name is one of: "caption", "col", "colgroup",
2560 "tbody", "td", "tfoot", "th", "thead", "tr" */
2561 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],
2562 array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th',
2563 'thead', 'tr'))) {
2564 /* If the stack of open elements does not have a td or th element
2565 in table scope, then this is a parse error; ignore the token.
2566 (fragment case) */
2567 if(!$this->elementInScope(array('td', 'th'), self::SCOPE_TABLE)) {
2568 // parse error
2569 $this->ignored = true;
2570
2571 /* Otherwise, close the cell (see below) and reprocess the current
2572 token. */
2573 } else {
2574 $this->closeCell();
2575 $this->emitToken($token);
2576 }
2577
2578 /* An end tag whose tag name is one of: "body", "caption", "col",
2579 "colgroup", "html" */
2580 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],
2581 array('body', 'caption', 'col', 'colgroup', 'html'))) {
2582 /* Parse error. Ignore the token. */
2583 $this->ignored = true;
2584
2585 /* An end tag whose tag name is one of: "table", "tbody", "tfoot",
2586 "thead", "tr" */
2587 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],
2588 array('table', 'tbody', 'tfoot', 'thead', 'tr'))) {
2589 /* If the stack of open elements does not have a td or th element
2590 in table scope, then this is a parse error; ignore the token.
2591 (innerHTML case) */
2592 if(!$this->elementInScope(array('td', 'th'), self::SCOPE_TABLE)) {
2593 // Parse error
2594 $this->ignored = true;
2595
2596 /* Otherwise, close the cell (see below) and reprocess the current
2597 token. */
2598 } else {
2599 $this->closeCell();
2600 $this->emitToken($token);
2601 }
2602
2603 /* Anything else */
2604 } else {
2605 /* Process the token as if the insertion mode was "in body". */
2606 $this->processWithRulesFor($token, self::IN_BODY);
2607 }
2608 break;
2609
2610 case self::IN_SELECT:
2611 /* Handle the token as follows: */
2612
2613 /* A character token */
2614 if(
2615 $token['type'] === HTML5_Tokenizer::CHARACTER ||
2616 $token['type'] === HTML5_Tokenizer::SPACECHARACTER
2617 ) {
2618 /* Append the token's character to the current node. */
2619 $this->insertText($token['data']);
2620
2621 /* A comment token */
2622 } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
2623 /* Append a Comment node to the current node with the data
2624 attribute set to the data given in the comment token. */
2625 $this->insertComment($token['data']);
2626
2627 } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
2628 // parse error
2629
2630 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {
2631 $this->processWithRulesFor($token, self::INBODY);
2632
2633 /* A start tag token whose tag name is "option" */
2634 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
2635 $token['name'] === 'option') {
2636 /* If the current node is an option element, act as if an end tag
2637 with the tag name "option" had been seen. */
2638 if(end($this->stack)->tagName === 'option') {
2639 $this->emitToken(array(
2640 'name' => 'option',
2641 'type' => HTML5_Tokenizer::ENDTAG
2642 ));
2643 }
2644
2645 /* Insert an HTML element for the token. */
2646 $this->insertElement($token);
2647
2648 /* A start tag token whose tag name is "optgroup" */
2649 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
2650 $token['name'] === 'optgroup') {
2651 /* If the current node is an option element, act as if an end tag
2652 with the tag name "option" had been seen. */
2653 if(end($this->stack)->tagName === 'option') {
2654 $this->emitToken(array(
2655 'name' => 'option',
2656 'type' => HTML5_Tokenizer::ENDTAG
2657 ));
2658 }
2659
2660 /* If the current node is an optgroup element, act as if an end tag
2661 with the tag name "optgroup" had been seen. */
2662 if(end($this->stack)->tagName === 'optgroup') {
2663 $this->emitToken(array(
2664 'name' => 'optgroup',
2665 'type' => HTML5_Tokenizer::ENDTAG
2666 ));
2667 }
2668
2669 /* Insert an HTML element for the token. */
2670 $this->insertElement($token);
2671
2672 /* An end tag token whose tag name is "optgroup" */
2673 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
2674 $token['name'] === 'optgroup') {
2675 /* First, if the current node is an option element, and the node
2676 immediately before it in the stack of open elements is an optgroup
2677 element, then act as if an end tag with the tag name "option" had
2678 been seen. */
2679 $elements_in_stack = count($this->stack);
2680
2681 if($this->stack[$elements_in_stack - 1]->tagName === 'option' &&
2682 $this->stack[$elements_in_stack - 2]->tagName === 'optgroup') {
2683 $this->emitToken(array(
2684 'name' => 'option',
2685 'type' => HTML5_Tokenizer::ENDTAG
2686 ));
2687 }
2688
2689 /* If the current node is an optgroup element, then pop that node
2690 from the stack of open elements. Otherwise, this is a parse error,
2691 ignore the token. */
2692 if(end($this->stack)->tagName === 'optgroup') {
2693 array_pop($this->stack);
2694 } else {
2695 // parse error
2696 $this->ignored = true;
2697 }
2698
2699 /* An end tag token whose tag name is "option" */
2700 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
2701 $token['name'] === 'option') {
2702 /* If the current node is an option element, then pop that node
2703 from the stack of open elements. Otherwise, this is a parse error,
2704 ignore the token. */
2705 if(end($this->stack)->tagName === 'option') {
2706 array_pop($this->stack);
2707 } else {
2708 // parse error
2709 $this->ignored = true;
2710 }
2711
2712 /* An end tag whose tag name is "select" */
2713 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
2714 $token['name'] === 'select') {
2715 /* If the stack of open elements does not have an element in table
2716 scope with the same tag name as the token, this is a parse error.
2717 Ignore the token. (fragment case) */
2718 if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
2719 $this->ignored = true;
2720 // parse error
2721
2722 /* Otherwise: */
2723 } else {
2724 /* Pop elements from the stack of open elements until a select
2725 element has been popped from the stack. */
2726 do {
2727 $node = array_pop($this->stack);
2728 } while ($node->tagName !== 'select');
2729
2730 /* Reset the insertion mode appropriately. */
2731 $this->resetInsertionMode();
2732 }
2733
2734 /* A start tag whose tag name is "select" */
2735 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'select') {
2736 /* Parse error. Act as if the token had been an end tag with the
2737 tag name "select" instead. */
2738 $this->emitToken(array(
2739 'name' => 'select',
2740 'type' => HTML5_Tokenizer::ENDTAG
2741 ));
2742
2743 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
2744 ($token['name'] === 'input' || $token['name'] === 'keygen' || $token['name'] === 'textarea')) {
2745 // parse error
2746 $this->emitToken(array(
2747 'name' => 'select',
2748 'type' => HTML5_Tokenizer::ENDTAG
2749 ));
2750 $this->emitToken($token);
2751
2752 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'script') {
2753 $this->processWithRulesFor($token, self::IN_HEAD);
2754
2755 } elseif($token['type'] === HTML5_Tokenizer::EOF) {
2756 // XERROR: If the current node is not the root html element, then this is a parse error.
2757 /* Stop parsing */
2758
2759 /* Anything else */
2760 } else {
2761 /* Parse error. Ignore the token. */
2762 $this->ignored = true;
2763 }
2764 break;
2765
2766 case self::IN_SELECT_IN_TABLE:
2767
2768 if($token['type'] === HTML5_Tokenizer::STARTTAG &&
2769 in_array($token['name'], array('caption', 'table', 'tbody',
2770 'tfoot', 'thead', 'tr', 'td', 'th'))) {
2771 // parse error
2772 $this->emitToken(array(
2773 'name' => 'select',
2774 'type' => HTML5_Tokenizer::ENDTAG,
2775 ));
2776 $this->emitToken($token);
2777
2778 /* An end tag whose tag name is one of: "caption", "table", "tbody",
2779 "tfoot", "thead", "tr", "td", "th" */
2780 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
2781 in_array($token['name'], array('caption', 'table', 'tbody', 'tfoot', 'thead', 'tr', 'td', 'th'))) {
2782 /* Parse error. */
2783 // parse error
2784
2785 /* If the stack of open elements has an element in table scope with
2786 the same tag name as that of the token, then act as if an end tag
2787 with the tag name "select" had been seen, and reprocess the token.
2788 Otherwise, ignore the token. */
2789 if($this->elementInScope($token['name'], self::SCOPE_TABLE)) {
2790 $this->emitToken(array(
2791 'name' => 'select',
2792 'type' => HTML5_Tokenizer::ENDTAG
2793 ));
2794
2795 $this->emitToken($token);
2796 } else {
2797 $this->ignored = true;
2798 }
2799 } else {
2800 $this->processWithRulesFor($token, self::IN_SELECT);
2801 }
2802 break;
2803
2804 case self::IN_FOREIGN_CONTENT:
2805 if ($token['type'] === HTML5_Tokenizer::CHARACTER ||
2806 $token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
2807 $this->insertText($token['data']);
2808 } elseif ($token['type'] === HTML5_Tokenizer::COMMENT) {
2809 $this->insertComment($token['data']);
2810 } elseif ($token['type'] === HTML5_Tokenizer::DOCTYPE) {
2811 // XERROR: parse error
2812 } elseif ($token['type'] === HTML5_Tokenizer::ENDTAG &&
2813 $token['name'] === 'script' && end($this->stack)->tagName === 'script' &&
2814 // XDOM
2815 end($this->stack)->namespaceURI === self::NS_SVG) {
2816 array_pop($this->stack);
2817 // a bunch of script running mumbo jumbo
2818 } elseif (
2819 ($token['type'] === HTML5_Tokenizer::STARTTAG &&
2820 ((
2821 $token['name'] !== 'mglyph' &&
2822 $token['name'] !== 'malignmark' &&
2823 // XDOM
2824 end($this->stack)->namespaceURI === self::NS_MATHML &&
2825 in_array(end($this->stack)->tagName, array('mi', 'mo', 'mn', 'ms', 'mtext'))
2826 ) ||
2827 (
2828 $token['name'] === 'svg' &&
2829 // XDOM
2830 end($this->stack)->namespaceURI === self::NS_MATHML &&
2831 end($this->stack)->tagName === 'annotation-xml'
2832 ) ||
2833 (
2834 // XDOM
2835 end($this->stack)->namespaceURI === self::NS_SVG &&
2836 in_array(end($this->stack)->tagName, array('foreignObject', 'desc', 'title'))
2837 ) ||
2838 (
2839 // XSKETCHY && XDOM
2840 end($this->stack)->namespaceURI === self::NS_HTML
2841 ))
2842 ) || $token['type'] === HTML5_Tokenizer::ENDTAG
2843 ) {
2844 $this->processWithRulesFor($token, $this->secondary_mode);
2845 /* If, after doing so, the insertion mode is still "in foreign
2846 * content", but there is no element in scope that has a namespace
2847 * other than the HTML namespace, switch the insertion mode to the
2848 * secondary insertion mode. */
2849 if ($this->mode === self::IN_FOREIGN_CONTENT) {
2850 $found = false;
2851 // this basically duplicates elementInScope()
2852 for ($i = count($this->stack) - 1; $i >= 0; $i--) {
2853 // XDOM
2854 $node = $this->stack[$i];
2855 if ($node->namespaceURI !== self::NS_HTML) {
2856 $found = true;
2857 break;
2858 } elseif (in_array($node->tagName, array('table', 'html',
2859 'applet', 'caption', 'td', 'th', 'button', 'marquee',
2860 'object')) || ($node->tagName === 'foreignObject' &&
2861 $node->namespaceURI === self::NS_SVG)) {
2862 break;
2863 }
2864 }
2865 if (!$found) {
2866 $this->mode = $this->secondary_mode;
2867 }
2868 }
2869 } elseif ($token['type'] === HTML5_Tokenizer::EOF || (
2870 $token['type'] === HTML5_Tokenizer::STARTTAG &&
2871 (in_array($token['name'], array('b', "big", "blockquote", "body", "br",
2872 "center", "code", "dc", "dd", "div", "dl", "ds", "dt", "em", "embed", "h1", "h2",
2873 "h3", "h4", "h5", "h6", "head", "hr", "i", "img", "li", "listing",
2874 "menu", "meta", "nobr", "ol", "p", "pre", "ruby", "s", "small",
2875 "span", "strong", "strike", "sub", "sup", "table", "tt", "u", "ul",
2876 "var")) || ($token['name'] === 'font' && ($this->getAttr($token, 'color') ||
2877 $this->getAttr($token, 'face') || $this->getAttr($token, 'size')))))) {
2878 // XERROR: parse error
2879 do {
2880 $node = array_pop($this->stack);
2881 // XDOM
2882 } while ($node->namespaceURI !== self::NS_HTML);
2883 $this->stack[] = $node;
2884 $this->mode = $this->secondary_mode;
2885 $this->emitToken($token);
2886 } elseif ($token['type'] === HTML5_Tokenizer::STARTTAG) {
2887 static $svg_lookup = array(
2888 'altglyph' => 'altGlyph',
2889 'altglyphdef' => 'altGlyphDef',
2890 'altglyphitem' => 'altGlyphItem',
2891 'animatecolor' => 'animateColor',
2892 'animatemotion' => 'animateMotion',
2893 'animatetransform' => 'animateTransform',
2894 'clippath' => 'clipPath',
2895 'feblend' => 'feBlend',
2896 'fecolormatrix' => 'feColorMatrix',
2897 'fecomponenttransfer' => 'feComponentTransfer',
2898 'fecomposite' => 'feComposite',
2899 'feconvolvematrix' => 'feConvolveMatrix',
2900 'fediffuselighting' => 'feDiffuseLighting',
2901 'fedisplacementmap' => 'feDisplacementMap',
2902 'fedistantlight' => 'feDistantLight',
2903 'feflood' => 'feFlood',
2904 'fefunca' => 'feFuncA',
2905 'fefuncb' => 'feFuncB',
2906 'fefuncg' => 'feFuncG',
2907 'fefuncr' => 'feFuncR',
2908 'fegaussianblur' => 'feGaussianBlur',
2909 'feimage' => 'feImage',
2910 'femerge' => 'feMerge',
2911 'femergenode' => 'feMergeNode',
2912 'femorphology' => 'feMorphology',
2913 'feoffset' => 'feOffset',
2914 'fepointlight' => 'fePointLight',
2915 'fespecularlighting' => 'feSpecularLighting',
2916 'fespotlight' => 'feSpotLight',
2917 'fetile' => 'feTile',
2918 'feturbulence' => 'feTurbulence',
2919 'foreignobject' => 'foreignObject',
2920 'glyphref' => 'glyphRef',
2921 'lineargradient' => 'linearGradient',
2922 'radialgradient' => 'radialGradient',
2923 'textpath' => 'textPath',
2924 );
2925 // XDOM
2926 $current = end($this->stack);
2927 if ($current->namespaceURI === self::NS_MATHML) {
2928 $token = $this->adjustMathMLAttributes($token);
2929 }
2930 if ($current->namespaceURI === self::NS_SVG &&
2931 isset($svg_lookup[$token['name']])) {
2932 $token['name'] = $svg_lookup[$token['name']];
2933 }
2934 if ($current->namespaceURI === self::NS_SVG) {
2935 $token = $this->adjustSVGAttributes($token);
2936 }
2937 $token = $this->adjustForeignAttributes($token);
2938 $this->insertForeignElement($token, $current->namespaceURI);
2939 if (isset($token['self-closing'])) {
2940 array_pop($this->stack);
2941 // XERROR: acknowledge self-closing flag
2942 }
2943 }
2944 break;
2945
2946 case self::AFTER_BODY:
2947 /* Handle the token as follows: */
2948
2949 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
2950 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
2951 or U+0020 SPACE */
2952 if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
2953 /* Process the token as it would be processed if the insertion mode
2954 was "in body". */
2955 $this->processWithRulesFor($token, self::IN_BODY);
2956
2957 /* A comment token */
2958 } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
2959 /* Append a Comment node to the first element in the stack of open
2960 elements (the html element), with the data attribute set to the
2961 data given in the comment token. */
2962 // XDOM
2963 $comment = $this->dom->createComment($token['data']);
2964 $this->stack[0]->appendChild($comment);
2965
2966 } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
2967 // parse error
2968
2969 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {
2970 $this->processWithRulesFor($token, self::IN_BODY);
2971
2972 /* An end tag with the tag name "html" */
2973 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'html') {
2974 /* If the parser was originally created as part of the HTML
2975 * fragment parsing algorithm, this is a parse error; ignore
2976 * the token. (fragment case) */
2977 $this->ignored = true;
2978 // XERROR: implement this
2979
2980 $this->mode = self::AFTER_AFTER_BODY;
2981
2982 } elseif($token['type'] === HTML5_Tokenizer::EOF) {
2983 /* Stop parsing */
2984
2985 /* Anything else */
2986 } else {
2987 /* Parse error. Set the insertion mode to "in body" and reprocess
2988 the token. */
2989 $this->mode = self::IN_BODY;
2990 $this->emitToken($token);
2991 }
2992 break;
2993
2994 case self::IN_FRAMESET:
2995 /* Handle the token as follows: */
2996
2997 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
2998 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
2999 U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */
3000 if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
3001 /* Append the character to the current node. */
3002 $this->insertText($token['data']);
3003
3004 /* A comment token */
3005 } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
3006 /* Append a Comment node to the current node with the data
3007 attribute set to the data given in the comment token. */
3008 $this->insertComment($token['data']);
3009
3010 } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
3011 // parse error
3012
3013 /* A start tag with the tag name "frameset" */
3014 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
3015 $token['name'] === 'frameset') {
3016 $this->insertElement($token);
3017
3018 /* An end tag with the tag name "frameset" */
3019 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
3020 $token['name'] === 'frameset') {
3021 /* If the current node is the root html element, then this is a
3022 parse error; ignore the token. (fragment case) */
3023 if(end($this->stack)->tagName === 'html') {
3024 $this->ignored = true;
3025 // Parse error
3026
3027 } else {
3028 /* Otherwise, pop the current node from the stack of open
3029 elements. */
3030 array_pop($this->stack);
3031
3032 /* If the parser was not originally created as part of the HTML
3033 * fragment parsing algorithm (fragment case), and the current
3034 * node is no longer a frameset element, then switch the
3035 * insertion mode to "after frameset". */
3036 $this->mode = self::AFTER_FRAMESET;
3037 }
3038
3039 /* A start tag with the tag name "frame" */
3040 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
3041 $token['name'] === 'frame') {
3042 /* Insert an HTML element for the token. */
3043 $this->insertElement($token);
3044
3045 /* Immediately pop the current node off the stack of open elements. */
3046 array_pop($this->stack);
3047
3048 // XERROR: Acknowledge the token's self-closing flag, if it is set.
3049
3050 /* A start tag with the tag name "noframes" */
3051 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
3052 $token['name'] === 'noframes') {
3053 /* Process the token using the rules for the "in head" insertion mode. */
3054 $this->processwithRulesFor($token, self::IN_HEAD);
3055
3056 } elseif($token['type'] === HTML5_Tokenizer::EOF) {
3057 // XERROR: If the current node is not the root html element, then this is a parse error.
3058 /* Stop parsing */
3059 /* Anything else */
3060 } else {
3061 /* Parse error. Ignore the token. */
3062 $this->ignored = true;
3063 }
3064 break;
3065
3066 case self::AFTER_FRAMESET:
3067 /* Handle the token as follows: */
3068
3069 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
3070 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
3071 U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */
3072 if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {
3073 /* Append the character to the current node. */
3074 $this->insertText($token['data']);
3075
3076 /* A comment token */
3077 } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {
3078 /* Append a Comment node to the current node with the data
3079 attribute set to the data given in the comment token. */
3080 $this->insertComment($token['data']);
3081
3082 } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {
3083 // parse error
3084
3085 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {
3086 $this->processWithRulesFor($token, self::IN_BODY);
3087
3088 /* An end tag with the tag name "html" */
3089 } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&
3090 $token['name'] === 'html') {
3091 $this->mode = self::AFTER_AFTER_FRAMESET;
3092
3093 /* A start tag with the tag name "noframes" */
3094 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&
3095 $token['name'] === 'noframes') {
3096 $this->processWithRulesFor($token, self::IN_HEAD);
3097
3098 } elseif($token['type'] === HTML5_Tokenizer::EOF) {
3099 /* Stop parsing */
3100
3101 /* Anything else */
3102 } else {
3103 /* Parse error. Ignore the token. */
3104 $this->ignored = true;
3105 }
3106 break;
3107
3108 case self::AFTER_AFTER_BODY:
3109 /* A comment token */
3110 if($token['type'] === HTML5_Tokenizer::COMMENT) {
3111 /* Append a Comment node to the Document object with the data
3112 attribute set to the data given in the comment token. */
3113 // XDOM
3114 $comment = $this->dom->createComment($token['data']);
3115 $this->dom->appendChild($comment);
3116
3117 } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE ||
3118 $token['type'] === HTML5_Tokenizer::SPACECHARACTER ||
3119 ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html')) {
3120 $this->processWithRulesFor($token, self::IN_BODY);
3121
3122 /* An end-of-file token */
3123 } elseif($token['type'] === HTML5_Tokenizer::EOF) {
3124 /* OMG DONE!! */
3125 } else {
3126 // parse error
3127 $this->mode = self::IN_BODY;
3128 $this->emitToken($token);
3129 }
3130 break;
3131
3132 case self::AFTER_AFTER_FRAMESET:
3133 /* A comment token */
3134 if($token['type'] === HTML5_Tokenizer::COMMENT) {
3135 /* Append a Comment node to the Document object with the data
3136 attribute set to the data given in the comment token. */
3137 // XDOM
3138 $comment = $this->dom->createComment($token['data']);
3139 $this->dom->appendChild($comment);
3140
3141 } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE ||
3142 $token['type'] === HTML5_Tokenizer::SPACECHARACTER ||
3143 ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html')) {
3144 $this->processWithRulesFor($token, self::IN_BODY);
3145
3146 /* An end-of-file token */
3147 } elseif($token['type'] === HTML5_Tokenizer::EOF) {
3148 /* OMG DONE!! */
3149 } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'nofrmaes') {
3150 $this->processWithRulesFor($token, self::IN_HEAD);
3151 } else {
3152 // parse error
3153 }
3154 break;
3155 }
3156 // end funky indenting
3157 }
3158
3159 private function insertElement($token, $append = true) {
3160 $el = $this->dom->createElementNS(self::NS_HTML, $token['name']);
3161
3162 if (!empty($token['attr'])) {
3163 foreach($token['attr'] as $attr) {
3164 if(!$el->hasAttribute($attr['name'])) {
3165 $el->setAttribute($attr['name'], $attr['value']);
3166 }
3167 }
3168 }
3169 if ($append) {
3170 $this->appendToRealParent($el);
3171 $this->stack[] = $el;
3172 }
3173
3174 return $el;
3175 }
3176
3177 private function insertText($data) {
3178 if ($data === '') return;
3179 if ($this->ignore_lf_token) {
3180 if ($data[0] === "\n") {
3181 $data = substr($data, 1);
3182 if ($data === false) return;
3183 }
3184 }
3185 $text = $this->dom->createTextNode($data);
3186 $this->appendToRealParent($text);
3187 }
3188
3189 private function insertComment($data) {
3190 $comment = $this->dom->createComment($data);
3191 $this->appendToRealParent($comment);
3192 }
3193
3194 private function appendToRealParent($node) {
3195 // this is only for the foster_parent case
3196 /* If the current node is a table, tbody, tfoot, thead, or tr
3197 element, then, whenever a node would be inserted into the current
3198 node, it must instead be inserted into the foster parent element. */
3199 if(!$this->foster_parent || !in_array(end($this->stack)->tagName,
3200 array('table', 'tbody', 'tfoot', 'thead', 'tr'))) {
3201 end($this->stack)->appendChild($node);
3202 } else {
3203 $this->fosterParent($node);
3204 }
3205 }
3206
3207 private function elementInScope($el, $scope = self::SCOPE) {
3208 if(is_array($el)) {
3209 foreach($el as $element) {
3210 if($this->elementInScope($element, $scope)) {
3211 return true;
3212 }
3213 }
3214
3215 return false;
3216 }
3217
3218 $leng = count($this->stack);
3219
3220 for($n = 0; $n < $leng; $n++) {
3221 /* 1. Initialise node to be the current node (the bottommost node of
3222 the stack). */
3223 $node = $this->stack[$leng - 1 - $n];
3224
3225 if($node->tagName === $el) {
3226 /* 2. If node is the target node, terminate in a match state. */
3227 return true;
3228
3229 // We've expanded the logic for these states a little differently;
3230 // Hixie's refactoring into "specific scope" is more general, but
3231 // this "gets the job done"
3232
3233 // these are the common states for all scopes
3234 } elseif($node->tagName === 'table' || $node->tagName === 'html') {
3235 return false;
3236
3237 // these are valid for "in scope" and "in list item scope"
3238 } elseif($scope !== self::SCOPE_TABLE &&
3239 (in_array($node->tagName, array('applet', 'caption', 'td',
3240 'th', 'button', 'marquee', 'object')) ||
3241 $node->tagName === 'foreignObject' && $node->namespaceURI === self::NS_SVG)) {
3242 return false;
3243
3244
3245 // these are valid for "in list item scope"
3246 } elseif($scope === self::SCOPE_LISTITEM && in_array($node->tagName, array('ol', 'ul'))) {
3247 return false;
3248 }
3249
3250 /* Otherwise, set node to the previous entry in the stack of open
3251 elements and return to step 2. (This will never fail, since the loop
3252 will always terminate in the previous step if the top of the stack
3253 is reached.) */
3254 }
3255 }
3256
3257 private function reconstructActiveFormattingElements() {
3258 /* 1. If there are no entries in the list of active formatting elements,
3259 then there is nothing to reconstruct; stop this algorithm. */
3260 $formatting_elements = count($this->a_formatting);
3261
3262 if($formatting_elements === 0) {
3263 return false;
3264 }
3265
3266 /* 3. Let entry be the last (most recently added) element in the list
3267 of active formatting elements. */
3268 $entry = end($this->a_formatting);
3269
3270 /* 2. If the last (most recently added) entry in the list of active
3271 formatting elements is a marker, or if it is an element that is in the
3272 stack of open elements, then there is nothing to reconstruct; stop this
3273 algorithm. */
3274 if($entry === self::MARKER || in_array($entry, $this->stack, true)) {
3275 return false;
3276 }
3277
3278 for($a = $formatting_elements - 1; $a >= 0; true) {
3279 /* 4. If there are no entries before entry in the list of active
3280 formatting elements, then jump to step 8. */
3281 if($a === 0) {
3282 $step_seven = false;
3283 break;
3284 }
3285
3286 /* 5. Let entry be the entry one earlier than entry in the list of
3287 active formatting elements. */
3288 $a--;
3289 $entry = $this->a_formatting[$a];
3290
3291 /* 6. If entry is neither a marker nor an element that is also in
3292 thetack of open elements, go to step 4. */
3293 if($entry === self::MARKER || in_array($entry, $this->stack, true)) {
3294 break;
3295 }
3296 }
3297
3298 while(true) {
3299 /* 7. Let entry be the element one later than entry in the list of
3300 active formatting elements. */
3301 if(isset($step_seven) && $step_seven === true) {
3302 $a++;
3303 $entry = $this->a_formatting[$a];
3304 }
3305
3306 /* 8. Perform a shallow clone of the element entry to obtain clone. */
3307 $clone = $entry->cloneNode();
3308
3309 /* 9. Append clone to the current node and push it onto the stack
3310 of open elements so that it is the new current node. */
3311 $this->appendToRealParent($clone);
3312 $this->stack[] = $clone;
3313
3314 /* 10. Replace the entry for entry in the list with an entry for
3315 clone. */
3316 $this->a_formatting[$a] = $clone;
3317
3318 /* 11. If the entry for clone in the list of active formatting
3319 elements is not the last entry in the list, return to step 7. */
3320 if(end($this->a_formatting) !== $clone) {
3321 $step_seven = true;
3322 } else {
3323 break;
3324 }
3325 }
3326 }
3327
3328 private function clearTheActiveFormattingElementsUpToTheLastMarker() {
3329 /* When the steps below require the UA to clear the list of active
3330 formatting elements up to the last marker, the UA must perform the
3331 following steps: */
3332
3333 while(true) {
3334 /* 1. Let entry be the last (most recently added) entry in the list
3335 of active formatting elements. */
3336 $entry = end($this->a_formatting);
3337
3338 /* 2. Remove entry from the list of active formatting elements. */
3339 array_pop($this->a_formatting);
3340
3341 /* 3. If entry was a marker, then stop the algorithm at this point.
3342 The list has been cleared up to the last marker. */
3343 if($entry === self::MARKER) {
3344 break;
3345 }
3346 }
3347 }
3348
3349 private function generateImpliedEndTags($exclude = array()) {
3350 /* When the steps below require the UA to generate implied end tags,
3351 * then, while the current node is a dc element, a dd element, a ds
3352 * element, a dt element, an li element, an option element, an optgroup
3353 * element, a p element, an rp element, or an rt element, the UA must
3354 * pop the current node off the stack of open elements. */
3355 $node = end($this->stack);
3356 $elements = array_diff(array('dc', 'dd', 'ds', 'dt', 'li', 'p', 'td', 'th', 'tr'), $exclude);
3357
3358 while(in_array(end($this->stack)->tagName, $elements)) {
3359 array_pop($this->stack);
3360 }
3361 }
3362
3363 private function getElementCategory($node) {
3364 if (!is_object($node)) debug_print_backtrace();
3365 $name = $node->tagName;
3366 if(in_array($name, $this->special))
3367 return self::SPECIAL;
3368
3369 elseif(in_array($name, $this->scoping))
3370 return self::SCOPING;
3371
3372 elseif(in_array($name, $this->formatting))
3373 return self::FORMATTING;
3374
3375 else
3376 return self::PHRASING;
3377 }
3378
3379 private function clearStackToTableContext($elements) {
3380 /* When the steps above require the UA to clear the stack back to a
3381 table context, it means that the UA must, while the current node is not
3382 a table element or an html element, pop elements from the stack of open
3383 elements. */
3384 while(true) {
3385 $name = end($this->stack)->tagName;
3386
3387 if(in_array($name, $elements)) {
3388 break;
3389 } else {
3390 array_pop($this->stack);
3391 }
3392 }
3393 }
3394
3395 private function resetInsertionMode($context = null) {
3396 /* 1. Let last be false. */
3397 $last = false;
3398 $leng = count($this->stack);
3399
3400 for($n = $leng - 1; $n >= 0; $n--) {
3401 /* 2. Let node be the last node in the stack of open elements. */
3402 $node = $this->stack[$n];
3403
3404 /* 3. If node is the first node in the stack of open elements, then
3405 * set last to true and set node to the context element. (fragment
3406 * case) */
3407 if($this->stack[0]->isSameNode($node)) {
3408 $last = true;
3409 $node = $context;
3410 }
3411
3412 /* 4. If node is a select element, then switch the insertion mode to
3413 "in select" and abort these steps. (fragment case) */
3414 if($node->tagName === 'select') {
3415 $this->mode = self::IN_SELECT;
3416 break;
3417
3418 /* 5. If node is a td or th element, then switch the insertion mode
3419 to "in cell" and abort these steps. */
3420 } elseif($node->tagName === 'td' || $node->nodeName === 'th') {
3421 $this->mode = self::IN_CELL;
3422 break;
3423
3424 /* 6. If node is a tr element, then switch the insertion mode to
3425 "in row" and abort these steps. */
3426 } elseif($node->tagName === 'tr') {
3427 $this->mode = self::IN_ROW;
3428 break;
3429
3430 /* 7. If node is a tbody, thead, or tfoot element, then switch the
3431 insertion mode to "in table body" and abort these steps. */
3432 } elseif(in_array($node->tagName, array('tbody', 'thead', 'tfoot'))) {
3433 $this->mode = self::IN_TABLE_BODY;
3434 break;
3435
3436 /* 8. If node is a caption element, then switch the insertion mode
3437 to "in caption" and abort these steps. */
3438 } elseif($node->tagName === 'caption') {
3439 $this->mode = self::IN_CAPTION;
3440 break;
3441
3442 /* 9. If node is a colgroup element, then switch the insertion mode
3443 to "in column group" and abort these steps. (innerHTML case) */
3444 } elseif($node->tagName === 'colgroup') {
3445 $this->mode = self::IN_COLUMN_GROUP;
3446 break;
3447
3448 /* 10. If node is a table element, then switch the insertion mode
3449 to "in table" and abort these steps. */
3450 } elseif($node->tagName === 'table') {
3451 $this->mode = self::IN_TABLE;
3452 break;
3453
3454 /* 11. If node is an element from the MathML namespace or the SVG
3455 * namespace, then switch the insertion mode to "in foreign
3456 * content", let the secondary insertion mode be "in body", and
3457 * abort these steps. */
3458 } elseif($node->namespaceURI === self::NS_SVG ||
3459 $node->namespaceURI === self::NS_MATHML) {
3460 $this->mode = self::IN_FOREIGN_CONTENT;
3461 $this->secondary_mode = self::IN_BODY;
3462 break;
3463
3464 /* 12. If node is a head element, then switch the insertion mode
3465 to "in body" ("in body"! not "in head"!) and abort these steps.
3466 (fragment case) */
3467 } elseif($node->tagName === 'head') {
3468 $this->mode = self::IN_BODY;
3469 break;
3470
3471 /* 13. If node is a body element, then switch the insertion mode to
3472 "in body" and abort these steps. */
3473 } elseif($node->tagName === 'body') {
3474 $this->mode = self::IN_BODY;
3475 break;
3476
3477 /* 14. If node is a frameset element, then switch the insertion
3478 mode to "in frameset" and abort these steps. (fragment case) */
3479 } elseif($node->tagName === 'frameset') {
3480 $this->mode = self::IN_FRAMESET;
3481 break;
3482
3483 /* 15. If node is an html element, then: if the head element
3484 pointer is null, switch the insertion mode to "before head",
3485 otherwise, switch the insertion mode to "after head". In either
3486 case, abort these steps. (fragment case) */
3487 } elseif($node->tagName === 'html') {
3488 $this->mode = ($this->head_pointer === null)
3489 ? self::BEFORE_HEAD
3490 : self::AFTER_HEAD;
3491
3492 break;
3493
3494 /* 16. If last is true, then set the insertion mode to "in body"
3495 and abort these steps. (fragment case) */
3496 } elseif($last) {
3497 $this->mode = self::IN_BODY;
3498 break;
3499 }
3500 }
3501 }
3502
3503 private function closeCell() {
3504 /* If the stack of open elements has a td or th element in table scope,
3505 then act as if an end tag token with that tag name had been seen. */
3506 foreach(array('td', 'th') as $cell) {
3507 if($this->elementInScope($cell, self::SCOPE_TABLE)) {
3508 $this->emitToken(array(
3509 'name' => $cell,
3510 'type' => HTML5_Tokenizer::ENDTAG
3511 ));
3512
3513 break;
3514 }
3515 }
3516 }
3517
3518 private function processWithRulesFor($token, $mode) {
3519 /* "using the rules for the m insertion mode", where m is one of these
3520 * modes, the user agent must use the rules described under the m
3521 * insertion mode's section, but must leave the insertion mode
3522 * unchanged unless the rules in m themselves switch the insertion mode
3523 * to a new value. */
3524 return $this->emitToken($token, $mode);
3525 }
3526
3527 private function insertCDATAElement($token) {
3528 $this->insertElement($token);
3529 $this->original_mode = $this->mode;
3530 $this->mode = self::IN_CDATA_RCDATA;
3531 $this->content_model = HTML5_Tokenizer::CDATA;
3532 }
3533
3534 private function insertRCDATAElement($token) {
3535 $this->insertElement($token);
3536 $this->original_mode = $this->mode;
3537 $this->mode = self::IN_CDATA_RCDATA;
3538 $this->content_model = HTML5_Tokenizer::RCDATA;
3539 }
3540
3541 private function getAttr($token, $key) {
3542 if (!isset($token['attr'])) return false;
3543 $ret = false;
3544 foreach ($token['attr'] as $keypair) {
3545 if ($keypair['name'] === $key) $ret = $keypair['value'];
3546 }
3547 return $ret;
3548 }
3549
3550 private function getCurrentTable() {
3551 /* The current table is the last table element in the stack of open
3552 * elements, if there is one. If there is no table element in the stack
3553 * of open elements (fragment case), then the current table is the
3554 * first element in the stack of open elements (the html element). */
3555 for ($i = count($this->stack) - 1; $i >= 0; $i--) {
3556 if ($this->stack[$i]->tagName === 'table') {
3557 return $this->stack[$i];
3558 }
3559 }
3560 return $this->stack[0];
3561 }
3562
3563 private function getFosterParent() {
3564 /* The foster parent element is the parent element of the last
3565 table element in the stack of open elements, if there is a
3566 table element and it has such a parent element. If there is no
3567 table element in the stack of open elements (innerHTML case),
3568 then the foster parent element is the first element in the
3569 stack of open elements (the html element). Otherwise, if there
3570 is a table element in the stack of open elements, but the last
3571 table element in the stack of open elements has no parent, or
3572 its parent node is not an element, then the foster parent
3573 element is the element before the last table element in the
3574 stack of open elements. */
3575 for($n = count($this->stack) - 1; $n >= 0; $n--) {
3576 if($this->stack[$n]->tagName === 'table') {
3577 $table = $this->stack[$n];
3578 break;
3579 }
3580 }
3581
3582 if(isset($table) && $table->parentNode !== null) {
3583 return $table->parentNode;
3584
3585 } elseif(!isset($table)) {
3586 return $this->stack[0];
3587
3588 } elseif(isset($table) && ($table->parentNode === null ||
3589 $table->parentNode->nodeType !== XML_ELEMENT_NODE)) {
3590 return $this->stack[$n - 1];
3591 }
3592 }
3593
3594 public function fosterParent($node) {
3595 $foster_parent = $this->getFosterParent();
3596 $table = $this->getCurrentTable(); // almost equivalent to last table element, except it can be html
3597 /* When a node node is to be foster parented, the node node must be
3598 * be inserted into the foster parent element. */
3599 /* If the foster parent element is the parent element of the last table
3600 * element in the stack of open elements, then node must be inserted
3601 * immediately before the last table element in the stack of open
3602 * elements in the foster parent element; otherwise, node must be
3603 * appended to the foster parent element. */
3604 if ($table->tagName === 'table' && $table->parentNode->isSameNode($foster_parent)) {
3605 $foster_parent->insertBefore($node, $table);
3606 } else {
3607 $foster_parent->appendChild($node);
3608 }
3609 }
3610
3611 /**
3612 * For debugging, prints the stack
3613 */
3614 private function printStack() {
3615 $names = array();
3616 foreach ($this->stack as $i => $element) {
3617 $names[] = $element->tagName;
3618 }
3619 echo " -> stack [" . implode(', ', $names) . "]\n";
3620 }
3621
3622 /**
3623 * For debugging, prints active formatting elements
3624 */
3625 private function printActiveFormattingElements() {
3626 if (!$this->a_formatting) return;
3627 $names = array();
3628 foreach ($this->a_formatting as $node) {
3629 if ($node === self::MARKER) $names[] = 'MARKER';
3630 else $names[] = $node->tagName;
3631 }
3632 echo " -> active formatting [" . implode(', ', $names) . "]\n";
3633 }
3634
3635 public function currentTableIsTainted() {
3636 return !empty($this->getCurrentTable()->tainted);
3637 }
3638
3639 /**
3640 * Sets up the tree constructor for building a fragment.
3641 */
3642 public function setupContext($context = null) {
3643 $this->fragment = true;
3644 if ($context) {
3645 $context = $this->dom->createElementNS(self::NS_HTML, $context);
3646 /* 4.1. Set the HTML parser's tokenization stage's content model
3647 * flag according to the context element, as follows: */
3648 switch ($context->tagName) {
3649 case 'title': case 'textarea':
3650 $this->content_model = HTML5_Tokenizer::RCDATA;
3651 break;
3652 case 'style': case 'script': case 'xmp': case 'iframe':
3653 case 'noembed': case 'noframes':
3654 $this->content_model = HTML5_Tokenizer::CDATA;
3655 break;
3656 case 'noscript':
3657 // XSCRIPT: assuming scripting is enabled
3658 $this->content_model = HTML5_Tokenizer::CDATA;
3659 break;
3660 case 'plaintext':
3661 $this->content_model = HTML5_Tokenizer::PLAINTEXT;
3662 break;
3663 }
3664 /* 4.2. Let root be a new html element with no attributes. */
3665 $root = $this->dom->createElementNS(self::NS_HTML, 'html');
3666 $this->root = $root;
3667 /* 4.3 Append the element root to the Document node created above. */
3668 $this->dom->appendChild($root);
3669 /* 4.4 Set up the parser's stack of open elements so that it
3670 * contains just the single element root. */
3671 $this->stack = array($root);
3672 /* 4.5 Reset the parser's insertion mode appropriately. */
3673 $this->resetInsertionMode($context);
3674 /* 4.6 Set the parser's form element pointer to the nearest node
3675 * to the context element that is a form element (going straight up
3676 * the ancestor chain, and including the element itself, if it is a
3677 * form element), or, if there is no such form element, to null. */
3678 $node = $context;
3679 do {
3680 if ($node->tagName === 'form') {
3681 $this->form_pointer = $node;
3682 break;
3683 }
3684 } while ($node = $node->parentNode);
3685 }
3686 }
3687
3688 public function adjustMathMLAttributes($token) {
3689 foreach ($token['attr'] as &$kp) {
3690 if ($kp['name'] === 'definitionurl') {
3691 $kp['name'] = 'definitionURL';
3692 }
3693 }
3694 return $token;
3695 }
3696
3697 public function adjustSVGAttributes($token) {
3698 static $lookup = array(
3699 'attributename' => 'attributeName',
3700 'attributetype' => 'attributeType',
3701 'basefrequency' => 'baseFrequency',
3702 'baseprofile' => 'baseProfile',
3703 'calcmode' => 'calcMode',
3704 'clippathunits' => 'clipPathUnits',
3705 'contentscripttype' => 'contentScriptType',
3706 'contentstyletype' => 'contentStyleType',
3707 'diffuseconstant' => 'diffuseConstant',
3708 'edgemode' => 'edgeMode',
3709 'externalresourcesrequired' => 'externalResourcesRequired',
3710 'filterres' => 'filterRes',
3711 'filterunits' => 'filterUnits',
3712 'glyphref' => 'glyphRef',
3713 'gradienttransform' => 'gradientTransform',
3714 'gradientunits' => 'gradientUnits',
3715 'kernelmatrix' => 'kernelMatrix',
3716 'kernelunitlength' => 'kernelUnitLength',
3717 'keypoints' => 'keyPoints',
3718 'keysplines' => 'keySplines',
3719 'keytimes' => 'keyTimes',
3720 'lengthadjust' => 'lengthAdjust',
3721 'limitingconeangle' => 'limitingConeAngle',
3722 'markerheight' => 'markerHeight',
3723 'markerunits' => 'markerUnits',
3724 'markerwidth' => 'markerWidth',
3725 'maskcontentunits' => 'maskContentUnits',
3726 'maskunits' => 'maskUnits',
3727 'numoctaves' => 'numOctaves',
3728 'pathlength' => 'pathLength',
3729 'patterncontentunits' => 'patternContentUnits',
3730 'patterntransform' => 'patternTransform',
3731 'patternunits' => 'patternUnits',
3732 'pointsatx' => 'pointsAtX',
3733 'pointsaty' => 'pointsAtY',
3734 'pointsatz' => 'pointsAtZ',
3735 'preservealpha' => 'preserveAlpha',
3736 'preserveaspectratio' => 'preserveAspectRatio',
3737 'primitiveunits' => 'primitiveUnits',
3738 'refx' => 'refX',
3739 'refy' => 'refY',
3740 'repeatcount' => 'repeatCount',
3741 'repeatdur' => 'repeatDur',
3742 'requiredextensions' => 'requiredExtensions',
3743 'requiredfeatures' => 'requiredFeatures',
3744 'specularconstant' => 'specularConstant',
3745 'specularexponent' => 'specularExponent',
3746 'spreadmethod' => 'spreadMethod',
3747 'startoffset' => 'startOffset',
3748 'stddeviation' => 'stdDeviation',
3749 'stitchtiles' => 'stitchTiles',
3750 'surfacescale' => 'surfaceScale',
3751 'systemlanguage' => 'systemLanguage',
3752 'tablevalues' => 'tableValues',
3753 'targetx' => 'targetX',
3754 'targety' => 'targetY',
3755 'textlength' => 'textLength',
3756 'viewbox' => 'viewBox',
3757 'viewtarget' => 'viewTarget',
3758 'xchannelselector' => 'xChannelSelector',
3759 'ychannelselector' => 'yChannelSelector',
3760 'zoomandpan' => 'zoomAndPan',
3761 );
3762 foreach ($token['attr'] as &$kp) {
3763 if (isset($lookup[$kp['name']])) {
3764 $kp['name'] = $lookup[$kp['name']];
3765 }
3766 }
3767 return $token;
3768 }
3769
3770 public function adjustForeignAttributes($token) {
3771 static $lookup = array(
3772 'xlink:actuate' => array('xlink', 'actuate', self::NS_XLINK),
3773 'xlink:arcrole' => array('xlink', 'arcrole', self::NS_XLINK),
3774 'xlink:href' => array('xlink', 'href', self::NS_XLINK),
3775 'xlink:role' => array('xlink', 'role', self::NS_XLINK),
3776 'xlink:show' => array('xlink', 'show', self::NS_XLINK),
3777 'xlink:title' => array('xlink', 'title', self::NS_XLINK),
3778 'xlink:type' => array('xlink', 'type', self::NS_XLINK),
3779 'xml:base' => array('xml', 'base', self::NS_XML),
3780 'xml:lang' => array('xml', 'lang', self::NS_XML),
3781 'xml:space' => array('xml', 'space', self::NS_XML),
3782 'xmlns' => array(null, 'xmlns', self::NS_XMLNS),
3783 'xmlns:xlink' => array('xmlns', 'xlink', self::NS_XMLNS),
3784 );
3785 foreach ($token['attr'] as &$kp) {
3786 if (isset($lookup[$kp['name']])) {
3787 $kp['name'] = $lookup[$kp['name']];
3788 }
3789 }
3790 return $token;
3791 }
3792
3793 public function insertForeignElement($token, $namespaceURI) {
3794 $el = $this->dom->createElementNS($namespaceURI, $token['name']);
3795 if (!empty($token['attr'])) {
3796 foreach ($token['attr'] as $kp) {
3797 $attr = $kp['name'];
3798 if (is_array($attr)) {
3799 $ns = $attr[2];
3800 $attr = $attr[1];
3801 } else {
3802 $ns = self::NS_HTML;
3803 }
3804 if (!$el->hasAttributeNS($ns, $attr)) {
3805 // XSKETCHY: work around godawful libxml bug
3806 if ($ns === self::NS_XLINK) {
3807 $el->setAttribute('xlink:'.$attr, $kp['value']);
3808 } elseif ($ns === self::NS_HTML) {
3809 // Another godawful libxml bug
3810 $el->setAttribute($attr, $kp['value']);
3811 } else {
3812 $el->setAttributeNS($ns, $attr, $kp['value']);
3813 }
3814 }
3815 }
3816 }
3817 $this->appendToRealParent($el);
3818 $this->stack[] = $el;
3819 // XERROR: see below
3820 /* If the newly created element has an xmlns attribute in the XMLNS
3821 * namespace whose value is not exactly the same as the element's
3822 * namespace, that is a parse error. Similarly, if the newly created
3823 * element has an xmlns:xlink attribute in the XMLNS namespace whose
3824 * value is not the XLink Namespace, that is a parse error. */
3825 }
3826
3827 public function save() {
3828 $this->dom->normalize();
3829 if (!$this->fragment) {
3830 return $this->dom;
3831 } else {
3832 if ($this->root) {
3833 return $this->root->childNodes;
3834 } else {
3835 return $this->dom->childNodes;
3836 }
3837 }
3838 }
3839}
3840
diff --git a/inc/3rdparty/libraries/html5/named-character-references.ser b/inc/3rdparty/libraries/html5/named-character-references.ser
new file mode 100644
index 00000000..e3ae0502
--- /dev/null
+++ b/inc/3rdparty/libraries/html5/named-character-references.ser
@@ -0,0 +1 @@
a:52:{s:1:"A";a:16:{s:1:"E";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:198;}s:9:"codepoint";i:198;}}}}s:1:"M";a:1:{s:1:"P";a:2:{s:1:";";a:1:{s:9:"codepoint";i:38;}s:9:"codepoint";i:38;}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:193;}s:9:"codepoint";i:193;}}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:258;}}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:194;}s:9:"codepoint";i:194;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1040;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120068;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:192;}s:9:"codepoint";i:192;}}}}}s:1:"l";a:1:{s:1:"p";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:913;}}}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:256;}}}}}s:1:"n";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10835;}}}s:1:"o";a:2:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:260;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120120;}}}}s:1:"p";a:1:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"y";a:1:{s:1:"F";a:1:{s:1:"u";a:1:{s:1:"n";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8289;}}}}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:197;}s:9:"codepoint";i:197;}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119964;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8788;}}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:195;}s:9:"codepoint";i:195;}}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:196;}s:9:"codepoint";i:196;}}}}s:1:"B";a:8:{s:1:"a";a:2:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"s";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8726;}}}}}}}}s:1:"r";a:2:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10983;}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8966;}}}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1041;}}}s:1:"e";a:3:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8757;}}}}}}s:1:"r";a:1:{s:1:"n";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8492;}}}}}}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:914;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120069;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120121;}}}}s:1:"r";a:1:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:728;}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8492;}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"p";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8782;}}}}}}}s:1:"C";a:14:{s:1:"H";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1063;}}}}s:1:"O";a:1:{s:1:"P";a:1:{s:1:"Y";a:2:{s:1:";";a:1:{s:9:"codepoint";i:169;}s:9:"codepoint";i:169;}}}s:1:"a";a:3:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:262;}}}}}s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8914;}s:1:"i";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"D";a:1:{s:1:"i";a:1:{s:1:"f";a:1:{s:1:"f";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"D";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8517;}}}}}}}}}}}}}}}}}}}s:1:"y";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"y";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8493;}}}}}}}s:1:"c";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:268;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:199;}s:9:"codepoint";i:199;}}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:264;}}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8752;}}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:266;}}}}s:1:"e";a:2:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:184;}}}}}}s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:183;}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8493;}}}s:1:"h";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:935;}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:"l";a:1:{s:1:"e";a:4:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8857;}}}}s:1:"M";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8854;}}}}}}s:1:"P";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8853;}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8855;}}}}}}}}}}}s:1:"l";a:1:{s:1:"o";a:2:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"w";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"C";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"I";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8754;}}}}}}}}}}}}}}}}}}}}}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"C";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"l";a:1:{s:1:"y";a:2:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"Q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8221;}}}}}}}}}}}}s:1:"Q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8217;}}}}}}}}}}}}}}}s:1:"o";a:4:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8759;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10868;}}}}}s:1:"n";a:3:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8801;}}}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8751;}}}}s:1:"t";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"I";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8750;}}}}}}}}}}}}}}s:1:"p";a:2:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8450;}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"d";a:1:{s:1:"u";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8720;}}}}}}}}s:1:"u";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"C";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"w";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"C";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"I";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8755;}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10799;}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119966;}}}}s:1:"u";a:1:{s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8915;}s:1:"C";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8781;}}}}}}}s:1:"D";a:11:{s:1:"D";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8517;}s:1:"o";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"h";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10513;}}}}}}}}s:1:"J";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1026;}}}}s:1:"S";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1029;}}}}s:1:"Z";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1039;}}}}s:1:"a";a:3:{s:1:"g";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8225;}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8609;}}}s:1:"s";a:1:{s:1:"h";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10980;}}}}}s:1:"c";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:270;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1044;}}}s:1:"e";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8711;}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:916;}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120071;}}}s:1:"i";a:2:{s:1:"a";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:4:{s:1:"A";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:180;}}}}}}s:1:"D";a:1:{s:1:"o";a:2:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:729;}}s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"A";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:733;}}}}}}}}}}}}s:1:"G";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:96;}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:732;}}}}}}}}}}}}}}s:1:"m";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8900;}}}}}}s:1:"f";a:1:{s:1:"f";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"D";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8518;}}}}}}}}}}}}}s:1:"o";a:4:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120123;}}}s:1:"t";a:3:{s:1:";";a:1:{s:9:"codepoint";i:168;}s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8412;}}}}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8784;}}}}}}}s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:6:{s:1:"C";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"I";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8751;}}}}}}}}}}}}}}}}s:1:"D";a:1:{s:1:"o";a:2:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:168;}}s:1:"w";a:1:{s:1:"n";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8659;}}}}}}}}}}s:1:"L";a:2:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:3:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8656;}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8660;}}}}}}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10980;}}}}}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"g";a:2:{s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10232;}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10234;}}}}}}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10233;}}}}}}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8658;}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8872;}}}}}}}}}s:1:"U";a:1:{s:1:"p";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8657;}}}}}}s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8661;}}}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8741;}}}}}}}}}}}}}}}}s:1:"w";a:1:{s:1:"n";a:6:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8595;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10515;}}}}s:1:"U";a:1:{s:1:"p";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8693;}}}}}}}}}}}}}s:1:"B";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:785;}}}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:3:{s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10576;}}}}}}}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10590;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8637;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10582;}}}}}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:2:{s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10591;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8641;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10583;}}}}}}}}}}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8868;}s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8615;}}}}}}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8659;}}}}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119967;}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:272;}}}}}}}s:1:"E";a:16:{s:1:"N";a:1:{s:1:"G";a:1:{s:1:";";a:1:{s:9:"codepoint";i:330;}}}s:1:"T";a:1:{s:1:"H";a:2:{s:1:";";a:1:{s:9:"codepoint";i:208;}s:9:"codepoint";i:208;}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:201;}s:9:"codepoint";i:201;}}}}}s:1:"c";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:282;}}}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:202;}s:9:"codepoint";i:202;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1069;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:278;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120072;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:200;}s:9:"codepoint";i:200;}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8712;}}}}}}}s:1:"m";a:2:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:274;}}}}s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:2:{s:1:"S";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"S";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9723;}}}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"y";a:1:{s:1:"S";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"S";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9643;}}}}}}}}}}}}}}}}}}}}s:1:"o";a:2:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:280;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120124;}}}}s:1:"p";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:917;}}}}}}}s:1:"q";a:1:{s:1:"u";a:2:{s:1:"a";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10869;}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8770;}}}}}}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"b";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8652;}}}}}}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8496;}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10867;}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:919;}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:203;}s:9:"codepoint";i:203;}}}s:1:"x";a:2:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8707;}}}}}s:1:"p";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8519;}}}}}}}}}}}}}s:1:"F";a:5:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1060;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120073;}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"d";a:2:{s:1:"S";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"S";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9724;}}}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"y";a:1:{s:1:"S";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"S";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9642;}}}}}}}}}}}}}}}}}}}}}s:1:"o";a:3:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120125;}}}s:1:"r";a:1:{s:1:"A";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8704;}}}}}s:1:"u";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8497;}}}}}}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8497;}}}}}s:1:"G";a:12:{s:1:"J";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1027;}}}}s:1:"T";a:2:{s:1:";";a:1:{s:9:"codepoint";i:62;}s:9:"codepoint";i:62;}s:1:"a";a:1:{s:1:"m";a:1:{s:1:"m";a:1:{s:1:"a";a:2:{s:1:";";a:1:{s:9:"codepoint";i:915;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:988;}}}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:286;}}}}}}s:1:"c";a:3:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:290;}}}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:284;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1043;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:288;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120074;}}}s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8921;}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120126;}}}}s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:6:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8805;}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8923;}}}}}}}}}}s:1:"F";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8807;}}}}}}}}}}s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10914;}}}}}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8823;}}}}}s:1:"S";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10878;}}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8819;}}}}}}}}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119970;}}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8811;}}}s:1:"H";a:8:{s:1:"A";a:1:{s:1:"R";a:1:{s:1:"D";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1066;}}}}}}s:1:"a";a:2:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:711;}}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:94;}}}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:292;}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8460;}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"b";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8459;}}}}}}}}}}}}s:1:"o";a:2:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8461;}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"z";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"L";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9472;}}}}}}}}}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8459;}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:294;}}}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"p";a:2:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"H";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8782;}}}}}}}}}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8783;}}}}}}}}}}s:1:"I";a:14:{s:1:"E";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1045;}}}}s:1:"J";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:306;}}}}}s:1:"O";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1025;}}}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:205;}s:9:"codepoint";i:205;}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:206;}s:9:"codepoint";i:206;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1048;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:304;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8465;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:204;}s:9:"codepoint";i:204;}}}}}s:1:"m";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8465;}s:1:"a";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:298;}}}s:1:"g";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"y";a:1:{s:1:"I";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8520;}}}}}}}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8658;}}}}}}}s:1:"n";a:2:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8748;}s:1:"e";a:2:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8747;}}}}}s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8898;}}}}}}}}}}}s:1:"v";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:2:{s:1:"C";a:1:{s:1:"o";a:1:{s:1:"m";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8291;}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8290;}}}}}}}}}}}}}}s:1:"o";a:3:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:302;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120128;}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:921;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8464;}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:296;}}}}}}s:1:"u";a:2:{s:1:"k";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1030;}}}}s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:207;}s:9:"codepoint";i:207;}}}}s:1:"J";a:5:{s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:308;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1049;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120077;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120129;}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119973;}}}s:1:"e";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1032;}}}}}}s:1:"u";a:1:{s:1:"k";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1028;}}}}}}s:1:"K";a:7:{s:1:"H";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1061;}}}}s:1:"J";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1036;}}}}s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:922;}}}}}s:1:"c";a:2:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:310;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1050;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120078;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120130;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119974;}}}}}s:1:"L";a:11:{s:1:"J";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1033;}}}}s:1:"T";a:2:{s:1:";";a:1:{s:9:"codepoint";i:60;}s:9:"codepoint";i:60;}s:1:"a";a:5:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:313;}}}}}s:1:"m";a:1:{s:1:"b";a:1:{s:1:"d";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:923;}}}}}s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10218;}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8466;}}}}}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8606;}}}}s:1:"c";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:317;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:315;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1051;}}}s:1:"e";a:2:{s:1:"f";a:1:{s:1:"t";a:10:{s:1:"A";a:2:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"B";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10216;}}}}}}}}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8592;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8676;}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8646;}}}}}}}}}}}}}}}}s:1:"C";a:1:{s:1:"e";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8968;}}}}}}}}s:1:"D";a:1:{s:1:"o";a:2:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"B";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10214;}}}}}}}}}}}}s:1:"w";a:1:{s:1:"n";a:2:{s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10593;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8643;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10585;}}}}}}}}}}}}}}s:1:"F";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8970;}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8596;}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10574;}}}}}}}}}}}}s:1:"T";a:2:{s:1:"e";a:1:{s:1:"e";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8867;}s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8612;}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10586;}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8882;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10703;}}}}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8884;}}}}}}}}}}}}}}s:1:"U";a:1:{s:1:"p";a:3:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10577;}}}}}}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10592;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8639;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10584;}}}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8636;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10578;}}}}}}}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8656;}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8660;}}}}}}}}}}}}}s:1:"s";a:1:{s:1:"s";a:6:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8922;}}}}}}}}}}}}}s:1:"F";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8806;}}}}}}}}}}s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8822;}}}}}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10913;}}}}}s:1:"S";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10877;}}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8818;}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120079;}}}s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8920;}s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8666;}}}}}}}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:319;}}}}}}s:1:"o";a:3:{s:1:"n";a:1:{s:1:"g";a:4:{s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10229;}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10231;}}}}}}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10230;}}}}}}}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10232;}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10234;}}}}}}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10233;}}}}}}}}}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120131;}}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"r";a:2:{s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8601;}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8600;}}}}}}}}}}}}}}}s:1:"s";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8466;}}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8624;}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:321;}}}}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8810;}}}s:1:"M";a:8:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10501;}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1052;}}}s:1:"e";a:2:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8287;}}}}}}}}}}s:1:"l";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8499;}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120080;}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:"P";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8723;}}}}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120132;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8499;}}}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:924;}}}s:1:"N";a:9:{s:1:"J";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1034;}}}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:323;}}}}}}s:1:"c";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:327;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:325;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1053;}}}s:1:"e";a:3:{s:1:"g";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"v";a:1:{s:1:"e";a:3:{s:1:"M";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8203;}}}}}}}}}}}}s:1:"T";a:1:{s:1:"h";a:1:{s:1:"i";a:2:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8203;}}}}}}}}s:1:"n";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8203;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"y";a:1:{s:1:"T";a:1:{s:1:"h";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8203;}}}}}}}}}}}}}}}}}}}}s:1:"s";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"d";a:2:{s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8811;}}}}}}}}}}}}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:"L";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8810;}}}}}}}}}}}}}s:1:"w";a:1:{s:1:"L";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10;}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120081;}}}s:1:"o";a:4:{s:1:"B";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8288;}}}}}}s:1:"n";a:1:{s:1:"B";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"k";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:160;}}}}}}}}}}}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8469;}}}s:1:"t";a:11:{s:1:";";a:1:{s:9:"codepoint";i:10988;}s:1:"C";a:2:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8802;}}}}}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:"C";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8813;}}}}}}}s:1:"D";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8742;}}}}}}}}}}}}}}}}}}s:1:"E";a:3:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8713;}}}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8800;}}}}}s:1:"x";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8708;}}}}}}}s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8815;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8817;}}}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8825;}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8821;}}}}}}}}}}}}}s:1:"L";a:1:{s:1:"e";a:2:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"T";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8938;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8940;}}}}}}}}}}}}}}}}s:1:"s";a:1:{s:1:"s";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8814;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8816;}}}}}}s:1:"G";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8824;}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8820;}}}}}}}}}}s:1:"P";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8832;}s:1:"S";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8928;}}}}}}}}}}}}}}}}}}}s:1:"R";a:2:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"E";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8716;}}}}}}}}}}}}}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"T";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8939;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8941;}}}}}}}}}}}}}}}}}}}s:1:"S";a:2:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"S";a:1:{s:1:"u";a:2:{s:1:"b";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8930;}}}}}}}}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8931;}}}}}}}}}}}}}}}}}}}s:1:"u";a:3:{s:1:"b";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8840;}}}}}}}}}}s:1:"c";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8833;}s:1:"S";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8929;}}}}}}}}}}}}}}}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8841;}}}}}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8769;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8772;}}}}}}s:1:"F";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8775;}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8777;}}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8740;}}}}}}}}}}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119977;}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:209;}s:9:"codepoint";i:209;}}}}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:925;}}}s:1:"O";a:14:{s:1:"E";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:338;}}}}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:211;}s:9:"codepoint";i:211;}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:212;}s:9:"codepoint";i:212;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1054;}}}s:1:"d";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:336;}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120082;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:210;}s:9:"codepoint";i:210;}}}}}s:1:"m";a:3:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:332;}}}}s:1:"e";a:1:{s:1:"g";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:937;}}}}s:1:"i";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:927;}}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120134;}}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"C";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"l";a:1:{s:1:"y";a:2:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"Q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8220;}}}}}}}}}}}}s:1:"Q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8216;}}}}}}}}}}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10836;}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119978;}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:2:{s:1:";";a:1:{s:9:"codepoint";i:216;}s:9:"codepoint";i:216;}}}}}s:1:"t";a:1:{s:1:"i";a:2:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:213;}s:9:"codepoint";i:213;}}}s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10807;}}}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:214;}s:9:"codepoint";i:214;}}}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"r";a:2:{s:1:"B";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:175;}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"c";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9182;}}s:1:"k";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9140;}}}}}}}}s:1:"P";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9180;}}}}}}}}}}}}}}}}s:1:"P";a:9:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"D";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8706;}}}}}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1055;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120083;}}}s:1:"h";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:934;}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:928;}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:"M";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:177;}}}}}}}}}s:1:"o";a:2:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8460;}}}}}}}}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8473;}}}}s:1:"r";a:4:{s:1:";";a:1:{s:9:"codepoint";i:10939;}s:1:"e";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:"s";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8826;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10927;}}}}}}s:1:"S";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8828;}}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8830;}}}}}}}}}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8243;}}}}s:1:"o";a:2:{s:1:"d";a:1:{s:1:"u";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8719;}}}}}s:1:"p";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8759;}s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8733;}}}}}}}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119979;}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:936;}}}}s:1:"Q";a:4:{s:1:"U";a:1:{s:1:"O";a:1:{s:1:"T";a:2:{s:1:";";a:1:{s:9:"codepoint";i:34;}s:9:"codepoint";i:34;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120084;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8474;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119980;}}}}}s:1:"R";a:12:{s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10512;}}}}}s:1:"E";a:1:{s:1:"G";a:2:{s:1:";";a:1:{s:9:"codepoint";i:174;}s:9:"codepoint";i:174;}}s:1:"a";a:3:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:340;}}}}}s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10219;}}}s:1:"r";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8608;}s:1:"t";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10518;}}}}}}s:1:"c";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:344;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:342;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1056;}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8476;}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:2:{s:1:"E";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8715;}}}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"b";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8651;}}}}}}}}}}}}s:1:"U";a:1:{s:1:"p";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"b";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10607;}}}}}}}}}}}}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8476;}}}s:1:"h";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:929;}}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:8:{s:1:"A";a:2:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"B";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10217;}}}}}}}}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8594;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8677;}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8644;}}}}}}}}}}}}}}}s:1:"C";a:1:{s:1:"e";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8969;}}}}}}}}s:1:"D";a:1:{s:1:"o";a:2:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"B";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10215;}}}}}}}}}}}}s:1:"w";a:1:{s:1:"n";a:2:{s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10589;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8642;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10581;}}}}}}}}}}}}}}s:1:"F";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8971;}}}}}}s:1:"T";a:2:{s:1:"e";a:1:{s:1:"e";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8866;}s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8614;}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10587;}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8883;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10704;}}}}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8885;}}}}}}}}}}}}}}s:1:"U";a:1:{s:1:"p";a:3:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10575;}}}}}}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10588;}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8638;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10580;}}}}}}}}}}}}s:1:"V";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8640;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10579;}}}}}}}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8658;}}}}}}}}}}s:1:"o";a:2:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8477;}}}s:1:"u";a:1:{s:1:"n";a:1:{s:1:"d";a:1:{s:1:"I";a:1:{s:1:"m";a:1:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10608;}}}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8667;}}}}}}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8475;}}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8625;}}}s:1:"u";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"D";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"y";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10740;}}}}}}}}}}}}s:1:"S";a:13:{s:1:"H";a:2:{s:1:"C";a:1:{s:1:"H";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1065;}}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1064;}}}}s:1:"O";a:1:{s:1:"F";a:1:{s:1:"T";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1068;}}}}}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:346;}}}}}}s:1:"c";a:5:{s:1:";";a:1:{s:9:"codepoint";i:10940;}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:352;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:350;}}}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:348;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1057;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120086;}}}s:1:"h";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"t";a:4:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8595;}}}}}}}}}}s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8592;}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8594;}}}}}}}}}}}s:1:"U";a:1:{s:1:"p";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8593;}}}}}}}}}}}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:931;}}}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"C";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8728;}}}}}}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120138;}}}}s:1:"q";a:2:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8730;}}}s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:4:{s:1:";";a:1:{s:9:"codepoint";i:9633;}s:1:"I";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8851;}}}}}}}}}}}}}s:1:"S";a:1:{s:1:"u";a:2:{s:1:"b";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8847;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8849;}}}}}}}}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8848;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8850;}}}}}}}}}}}}}}s:1:"U";a:1:{s:1:"n";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8852;}}}}}}}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119982;}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8902;}}}}s:1:"u";a:4:{s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8912;}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8912;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8838;}}}}}}}}}}s:1:"c";a:2:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"s";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8827;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10928;}}}}}}s:1:"S";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8829;}}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8831;}}}}}}}}}}}s:1:"h";a:1:{s:1:"T";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8715;}}}}}}}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8721;}}s:1:"p";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8913;}s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8835;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8839;}}}}}}}}}}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8913;}}}}}}}s:1:"T";a:11:{s:1:"H";a:1:{s:1:"O";a:1:{s:1:"R";a:1:{s:1:"N";a:2:{s:1:";";a:1:{s:9:"codepoint";i:222;}s:9:"codepoint";i:222;}}}}s:1:"R";a:1:{s:1:"A";a:1:{s:1:"D";a:1:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8482;}}}}}s:1:"S";a:2:{s:1:"H";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1035;}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1062;}}}}s:1:"a";a:2:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9;}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:932;}}}s:1:"c";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:356;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:354;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1058;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120087;}}}s:1:"h";a:2:{s:1:"e";a:2:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8756;}}}}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:920;}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8201;}}}}}}}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8764;}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8771;}}}}}}s:1:"F";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8773;}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8776;}}}}}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120139;}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8411;}}}}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119983;}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:358;}}}}}}}s:1:"U";a:14:{s:1:"a";a:2:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:218;}s:9:"codepoint";i:218;}}}}s:1:"r";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8607;}s:1:"o";a:1:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10569;}}}}}}}}s:1:"b";a:1:{s:1:"r";a:2:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1038;}}}s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:364;}}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:219;}s:9:"codepoint";i:219;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1059;}}}s:1:"d";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:368;}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120088;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:217;}s:9:"codepoint";i:217;}}}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:362;}}}}}s:1:"n";a:2:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:"r";a:2:{s:1:"B";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:818;}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"c";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9183;}}s:1:"k";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9141;}}}}}}}}s:1:"P";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9181;}}}}}}}}}}}}}}}s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8899;}s:1:"P";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8846;}}}}}}}}}s:1:"o";a:2:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:370;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120140;}}}}s:1:"p";a:8:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8593;}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10514;}}}}s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8645;}}}}}}}}}}}}}}}s:1:"D";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8597;}}}}}}}}}}s:1:"E";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"b";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10606;}}}}}}}}}}}}s:1:"T";a:1:{s:1:"e";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8869;}s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8613;}}}}}}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8657;}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8661;}}}}}}}}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"r";a:2:{s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8598;}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8599;}}}}}}}}}}}}}}s:1:"s";a:1:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:978;}s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:933;}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:366;}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119984;}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:360;}}}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:220;}s:9:"codepoint";i:220;}}}}s:1:"V";a:9:{s:1:"D";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8875;}}}}}s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10987;}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1042;}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8873;}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10982;}}}}}}s:1:"e";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8897;}}s:1:"r";a:3:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8214;}}}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8214;}s:1:"i";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:4:{s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8739;}}}}s:1:"L";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:124;}}}}}s:1:"S";a:1:{s:1:"e";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10072;}}}}}}}}}}s:1:"T";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8768;}}}}}}}}}}}s:1:"y";a:1:{s:1:"T";a:1:{s:1:"h";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8202;}}}}}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120089;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120141;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119985;}}}}s:1:"v";a:1:{s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8874;}}}}}}}s:1:"W";a:5:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:372;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8896;}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120090;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120142;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119986;}}}}}s:1:"X";a:4:{s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120091;}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:926;}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120143;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119987;}}}}}s:1:"Y";a:9:{s:1:"A";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1071;}}}}s:1:"I";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1031;}}}}s:1:"U";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1070;}}}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:221;}s:9:"codepoint";i:221;}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:374;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1067;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120092;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120144;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119988;}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:376;}}}}}s:1:"Z";a:8:{s:1:"H";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1046;}}}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:377;}}}}}}s:1:"c";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:381;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1047;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:379;}}}}s:1:"e";a:2:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"W";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:"S";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8203;}}}}}}}}}}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:918;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8488;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8484;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119989;}}}}}s:1:"a";a:16:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:225;}s:9:"codepoint";i:225;}}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:259;}}}}}}s:1:"c";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8766;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8767;}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:226;}s:9:"codepoint";i:226;}}}s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:180;}s:9:"codepoint";i:180;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1072;}}}s:1:"e";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:230;}s:9:"codepoint";i:230;}}}}s:1:"f";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8289;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120094;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:224;}s:9:"codepoint";i:224;}}}}}s:1:"l";a:2:{s:1:"e";a:2:{s:1:"f";a:1:{s:1:"s";a:1:{s:1:"y";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8501;}}}}}s:1:"p";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8501;}}}}s:1:"p";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:945;}}}}}s:1:"m";a:2:{s:1:"a";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:257;}}}s:1:"l";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10815;}}}}s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:38;}s:9:"codepoint";i:38;}}s:1:"n";a:2:{s:1:"d";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8743;}s:1:"a";a:1:{s:1:"n";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10837;}}}}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10844;}}s:1:"s";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10840;}}}}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10842;}}}s:1:"g";a:7:{s:1:";";a:1:{s:9:"codepoint";i:8736;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10660;}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8736;}}}s:1:"m";a:1:{s:1:"s";a:1:{s:1:"d";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8737;}s:1:"a";a:8:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10664;}}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10665;}}s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10666;}}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10667;}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10668;}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10669;}}s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10670;}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10671;}}}}}}s:1:"r";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8735;}s:1:"v";a:1:{s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8894;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10653;}}}}}}s:1:"s";a:2:{s:1:"p";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8738;}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8491;}}}s:1:"z";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9084;}}}}}}}s:1:"o";a:2:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:261;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120146;}}}}s:1:"p";a:7:{s:1:";";a:1:{s:9:"codepoint";i:8776;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10864;}}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10863;}}}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8778;}}s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8779;}}}s:1:"o";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:39;}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8776;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8778;}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:229;}s:9:"codepoint";i:229;}}}}s:1:"s";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119990;}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:42;}}s:1:"y";a:1:{s:1:"m";a:1:{s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8776;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8781;}}}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:227;}s:9:"codepoint";i:227;}}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:228;}s:9:"codepoint";i:228;}}}s:1:"w";a:2:{s:1:"c";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8755;}}}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10769;}}}}}}s:1:"b";a:16:{s:1:"N";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10989;}}}}s:1:"a";a:2:{s:1:"c";a:1:{s:1:"k";a:4:{s:1:"c";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8780;}}}}}s:1:"e";a:1:{s:1:"p";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1014;}}}}}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8245;}}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8765;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8909;}}}}}}}}s:1:"r";a:2:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8893;}}}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8965;}s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8965;}}}}}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9141;}s:1:"t";a:1:{s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9142;}}}}}}}}s:1:"c";a:2:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8780;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1073;}}}s:1:"d";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8222;}}}}}s:1:"e";a:5:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"u";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8757;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8757;}}}}}}s:1:"m";a:1:{s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10672;}}}}}}s:1:"p";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1014;}}}}s:1:"r";a:1:{s:1:"n";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8492;}}}}}s:1:"t";a:3:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:946;}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8502;}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8812;}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120095;}}}s:1:"i";a:1:{s:1:"g";a:7:{s:1:"c";a:3:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8898;}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9711;}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8899;}}}}s:1:"o";a:3:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10752;}}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10753;}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10754;}}}}}}}s:1:"s";a:2:{s:1:"q";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10758;}}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9733;}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:2:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9661;}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9651;}}}}}}}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10756;}}}}}}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8897;}}}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8896;}}}}}}}}s:1:"k";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10509;}}}}}}s:1:"l";a:3:{s:1:"a";a:2:{s:1:"c";a:1:{s:1:"k";a:3:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"z";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10731;}}}}}}}}s:1:"s";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9642;}}}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:4:{s:1:";";a:1:{s:9:"codepoint";i:9652;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9662;}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9666;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9656;}}}}}}}}}}}}}}}}s:1:"n";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9251;}}}}s:1:"k";a:2:{i:1;a:2:{i:2;a:1:{s:1:";";a:1:{s:9:"codepoint";i:9618;}}i:4;a:1:{s:1:";";a:1:{s:9:"codepoint";i:9617;}}}i:3;a:1:{i:4;a:1:{s:1:";";a:1:{s:9:"codepoint";i:9619;}}}}s:1:"o";a:1:{s:1:"c";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9608;}}}}}s:1:"n";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8976;}}}}s:1:"o";a:4:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120147;}}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8869;}s:1:"t";a:1:{s:1:"o";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8869;}}}}}s:1:"w";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8904;}}}}}s:1:"x";a:12:{s:1:"D";a:4:{s:1:"L";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9559;}}s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9556;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9558;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9555;}}}s:1:"H";a:5:{s:1:";";a:1:{s:9:"codepoint";i:9552;}s:1:"D";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9574;}}s:1:"U";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9577;}}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9572;}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9575;}}}s:1:"U";a:4:{s:1:"L";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9565;}}s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9562;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9564;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9561;}}}s:1:"V";a:7:{s:1:";";a:1:{s:9:"codepoint";i:9553;}s:1:"H";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9580;}}s:1:"L";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9571;}}s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9568;}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9579;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9570;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9567;}}}s:1:"b";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10697;}}}}s:1:"d";a:4:{s:1:"L";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9557;}}s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9554;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9488;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9484;}}}s:1:"h";a:5:{s:1:";";a:1:{s:9:"codepoint";i:9472;}s:1:"D";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9573;}}s:1:"U";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9576;}}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9516;}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9524;}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8863;}}}}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8862;}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8864;}}}}}}s:1:"u";a:4:{s:1:"L";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9563;}}s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9560;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9496;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9492;}}}s:1:"v";a:7:{s:1:";";a:1:{s:9:"codepoint";i:9474;}s:1:"H";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9578;}}s:1:"L";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9569;}}s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9566;}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9532;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9508;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9500;}}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8245;}}}}}}s:1:"r";a:2:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:728;}}}}s:1:"v";a:1:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:166;}s:9:"codepoint";i:166;}}}}}s:1:"s";a:4:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119991;}}}s:1:"e";a:1:{s:1:"m";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8271;}}}}s:1:"i";a:1:{s:1:"m";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8765;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8909;}}}}s:1:"o";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:92;}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10693;}}}}}s:1:"u";a:2:{s:1:"l";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8226;}s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8226;}}}}}s:1:"m";a:1:{s:1:"p";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8782;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10926;}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8783;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8783;}}}}}}}s:1:"c";a:15:{s:1:"a";a:3:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:263;}}}}}s:1:"p";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8745;}s:1:"a";a:1:{s:1:"n";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10820;}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10825;}}}}}}s:1:"c";a:2:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10827;}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10823;}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10816;}}}}}s:1:"r";a:2:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8257;}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:711;}}}}}s:1:"c";a:4:{s:1:"a";a:2:{s:1:"p";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10829;}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:269;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:231;}s:9:"codepoint";i:231;}}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:265;}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10828;}s:1:"s";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10832;}}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:267;}}}}s:1:"e";a:3:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:184;}s:9:"codepoint";i:184;}}}s:1:"m";a:1:{s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10674;}}}}}}s:1:"n";a:1:{s:1:"t";a:3:{s:1:";";a:1:{s:9:"codepoint";i:162;}s:9:"codepoint";i:162;s:1:"e";a:1:{s:1:"r";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:183;}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120096;}}}s:1:"h";a:3:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1095;}}}s:1:"e";a:1:{s:1:"c";a:1:{s:1:"k";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10003;}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10003;}}}}}}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:967;}}}s:1:"i";a:1:{s:1:"r";a:7:{s:1:";";a:1:{s:9:"codepoint";i:9675;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10691;}}s:1:"c";a:3:{s:1:";";a:1:{s:9:"codepoint";i:710;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8791;}}}s:1:"l";a:1:{s:1:"e";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8634;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8635;}}}}}}}}}}}s:1:"d";a:5:{s:1:"R";a:1:{s:1:";";a:1:{s:9:"codepoint";i:174;}}s:1:"S";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9416;}}s:1:"a";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8859;}}}}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8858;}}}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8861;}}}}}}}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8791;}}s:1:"f";a:1:{s:1:"n";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10768;}}}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10991;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10690;}}}}}}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9827;}s:1:"u";a:1:{s:1:"i";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9827;}}}}}}}}s:1:"o";a:4:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:58;}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8788;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8788;}}}}}}s:1:"m";a:2:{s:1:"m";a:1:{s:1:"a";a:2:{s:1:";";a:1:{s:9:"codepoint";i:44;}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:64;}}}}s:1:"p";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8705;}s:1:"f";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8728;}}}s:1:"l";a:1:{s:1:"e";a:2:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8705;}}}}}s:1:"x";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8450;}}}}}}}}s:1:"n";a:2:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8773;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10861;}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8750;}}}}}s:1:"p";a:3:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120148;}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8720;}}}}s:1:"y";a:3:{s:1:";";a:1:{s:9:"codepoint";i:169;}s:9:"codepoint";i:169;s:1:"s";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8471;}}}}}}s:1:"r";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8629;}}}}s:1:"o";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10007;}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119992;}}}s:1:"u";a:2:{s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10959;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10961;}}}s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10960;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10962;}}}}}s:1:"t";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8943;}}}}}s:1:"u";a:7:{s:1:"d";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:2:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10552;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10549;}}}}}}s:1:"e";a:2:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8926;}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8927;}}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8630;}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10557;}}}}}}s:1:"p";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8746;}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10824;}}}}}}s:1:"c";a:2:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10822;}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10826;}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8845;}}}}s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10821;}}}}s:1:"r";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8631;}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10556;}}}}}s:1:"l";a:1:{s:1:"y";a:3:{s:1:"e";a:1:{s:1:"q";a:2:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8926;}}}}}s:1:"s";a:1:{s:1:"u";a:1:{s:1:"c";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8927;}}}}}}}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8910;}}}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8911;}}}}}}}}s:1:"r";a:1:{s:1:"e";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:164;}s:9:"codepoint";i:164;}}}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8630;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8631;}}}}}}}}}}}}}}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8910;}}}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8911;}}}}}s:1:"w";a:2:{s:1:"c";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8754;}}}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8753;}}}}}s:1:"y";a:1:{s:1:"l";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9005;}}}}}}}s:1:"d";a:19:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8659;}}}}s:1:"H";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10597;}}}}s:1:"a";a:4:{s:1:"g";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8224;}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8504;}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8595;}}}s:1:"s";a:1:{s:1:"h";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8208;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8867;}}}}}s:1:"b";a:2:{s:1:"k";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10511;}}}}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:733;}}}}}s:1:"c";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:271;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1076;}}}s:1:"d";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8518;}s:1:"a";a:2:{s:1:"g";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8225;}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8650;}}}}s:1:"o";a:1:{s:1:"t";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10871;}}}}}}}s:1:"e";a:3:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:176;}s:9:"codepoint";i:176;}s:1:"l";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:948;}}}}s:1:"m";a:1:{s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10673;}}}}}}}s:1:"f";a:2:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10623;}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120097;}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8643;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8642;}}}}}s:1:"i";a:5:{s:1:"a";a:1:{s:1:"m";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8900;}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"d";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8900;}s:1:"s";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9830;}}}}}}}}s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9830;}}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:168;}}s:1:"g";a:1:{s:1:"a";a:1:{s:1:"m";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:989;}}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8946;}}}}s:1:"v";a:3:{s:1:";";a:1:{s:9:"codepoint";i:247;}s:1:"i";a:1:{s:1:"d";a:1:{s:1:"e";a:3:{s:1:";";a:1:{s:9:"codepoint";i:247;}s:9:"codepoint";i:247;s:1:"o";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8903;}}}}}}}}}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8903;}}}}}}s:1:"j";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1106;}}}}s:1:"l";a:1:{s:1:"c";a:2:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8990;}}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8973;}}}}}}s:1:"o";a:5:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:36;}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120149;}}}s:1:"t";a:5:{s:1:";";a:1:{s:9:"codepoint";i:729;}s:1:"e";a:1:{s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8784;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8785;}}}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8760;}}}}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8724;}}}}}s:1:"s";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8865;}}}}}}}}s:1:"u";a:1:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8966;}}}}}}}}}}}}}s:1:"w";a:1:{s:1:"n";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8595;}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8650;}}}}}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8643;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8642;}}}}}}}}}}}}}}}}s:1:"r";a:2:{s:1:"b";a:1:{s:1:"k";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10512;}}}}}}}s:1:"c";a:2:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8991;}}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8972;}}}}}}s:1:"s";a:3:{s:1:"c";a:2:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119993;}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1109;}}}s:1:"o";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10742;}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:273;}}}}}}s:1:"t";a:2:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8945;}}}}s:1:"r";a:1:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9663;}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9662;}}}}}s:1:"u";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8693;}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10607;}}}}}s:1:"w";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10662;}}}}}}}s:1:"z";a:2:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1119;}}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10239;}}}}}}}}}s:1:"e";a:18:{s:1:"D";a:2:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10871;}}}}s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8785;}}}}s:1:"a";a:2:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:233;}s:9:"codepoint";i:233;}}}}s:1:"s";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10862;}}}}}}s:1:"c";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:283;}}}}}s:1:"i";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8790;}s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:234;}s:9:"codepoint";i:234;}}}s:1:"o";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8789;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1101;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:279;}}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8519;}}s:1:"f";a:2:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8786;}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120098;}}}s:1:"g";a:3:{s:1:";";a:1:{s:9:"codepoint";i:10906;}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:232;}s:9:"codepoint";i:232;}}}}s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10902;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10904;}}}}}}s:1:"l";a:4:{s:1:";";a:1:{s:9:"codepoint";i:10905;}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9191;}}}}}}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8467;}}s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10901;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10903;}}}}}}s:1:"m";a:3:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:275;}}}}s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8709;}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8709;}}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8709;}}}}}s:1:"s";a:1:{s:1:"p";a:2:{i:1;a:2:{i:3;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8196;}}i:4;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8197;}}}s:1:";";a:1:{s:9:"codepoint";i:8195;}}}}s:1:"n";a:2:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:331;}}s:1:"s";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8194;}}}}s:1:"o";a:2:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:281;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120150;}}}}s:1:"p";a:3:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8917;}s:1:"s";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10723;}}}}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10865;}}}}s:1:"s";a:1:{s:1:"i";a:3:{s:1:";";a:1:{s:9:"codepoint";i:1013;}s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:949;}}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:949;}}}}}s:1:"q";a:4:{s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8790;}}}}s:1:"o";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8789;}}}}}}s:1:"s";a:2:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8770;}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:2:{s:1:"g";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10902;}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10901;}}}}}}}}}}s:1:"u";a:3:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:61;}}}}s:1:"e";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8799;}}}}s:1:"i";a:1:{s:1:"v";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8801;}s:1:"D";a:1:{s:1:"D";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10872;}}}}}}s:1:"v";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10725;}}}}}}}}s:1:"r";a:2:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8787;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10609;}}}}}s:1:"s";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8495;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8784;}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8770;}}}}s:1:"t";a:2:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:951;}}s:1:"h";a:2:{s:1:";";a:1:{s:9:"codepoint";i:240;}s:9:"codepoint";i:240;}}s:1:"u";a:2:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:235;}s:9:"codepoint";i:235;}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8364;}}}}s:1:"x";a:3:{s:1:"c";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:33;}}}s:1:"i";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8707;}}}}s:1:"p";a:2:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8496;}}}}}}}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8519;}}}}}}}}}}}}}s:1:"f";a:11:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8786;}}}}}}}}}}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1092;}}}s:1:"e";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9792;}}}}}}s:1:"f";a:3:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:64259;}}}}}s:1:"l";a:2:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:64256;}}}s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:64260;}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120099;}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:64257;}}}}}s:1:"l";a:3:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9837;}}}s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:64258;}}}}s:1:"t";a:1:{s:1:"n";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9649;}}}}}s:1:"n";a:1:{s:1:"o";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:402;}}}}s:1:"o";a:2:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120151;}}}s:1:"r";a:2:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8704;}}}}s:1:"k";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8916;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10969;}}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10765;}}}}}}}}s:1:"r";a:2:{s:1:"a";a:2:{s:1:"c";a:6:{i:1;a:6:{i:2;a:2:{s:1:";";a:1:{s:9:"codepoint";i:189;}s:9:"codepoint";i:189;}i:3;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8531;}}i:4;a:2:{s:1:";";a:1:{s:9:"codepoint";i:188;}s:9:"codepoint";i:188;}i:5;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8533;}}i:6;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8537;}}i:8;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8539;}}}i:2;a:2:{i:3;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8532;}}i:5;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8534;}}}i:3;a:3:{i:4;a:2:{s:1:";";a:1:{s:9:"codepoint";i:190;}s:9:"codepoint";i:190;}i:5;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8535;}}i:8;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8540;}}}i:4;a:1:{i:5;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8536;}}}i:5;a:2:{i:6;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8538;}}i:8;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8541;}}}i:7;a:1:{i:8;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8542;}}}}s:1:"s";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8260;}}}}s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8994;}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119995;}}}}}s:1:"g";a:16:{s:1:"E";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8807;}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10892;}}}s:1:"a";a:3:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:501;}}}}}s:1:"m";a:1:{s:1:"m";a:1:{s:1:"a";a:2:{s:1:";";a:1:{s:9:"codepoint";i:947;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:989;}}}}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10886;}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:287;}}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:285;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1075;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:289;}}}}s:1:"e";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8805;}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8923;}}s:1:"q";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8805;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8807;}}s:1:"s";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10878;}}}}}}}s:1:"s";a:4:{s:1:";";a:1:{s:9:"codepoint";i:10878;}s:1:"c";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10921;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10880;}s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10882;}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10884;}}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10900;}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120100;}}}s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8811;}s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8921;}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8503;}}}}}s:1:"j";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1107;}}}}s:1:"l";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8823;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10898;}}s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10917;}}s:1:"j";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10916;}}}s:1:"n";a:4:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8809;}}s:1:"a";a:1:{s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10890;}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10890;}}}}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10888;}s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10888;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8809;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8935;}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120152;}}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:96;}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8458;}}}s:1:"i";a:1:{s:1:"m";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8819;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10894;}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10896;}}}}}s:1:"t";a:7:{s:1:";";a:1:{s:9:"codepoint";i:62;}s:9:"codepoint";i:62;s:1:"c";a:2:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10919;}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10874;}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8919;}}}}s:1:"l";a:1:{s:1:"P";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10645;}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10876;}}}}}}s:1:"r";a:5:{s:1:"a";a:2:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10886;}}}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10616;}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8919;}}}}s:1:"e";a:1:{s:1:"q";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8923;}}}}}s:1:"q";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10892;}}}}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8823;}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8819;}}}}}}}s:1:"h";a:10:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8660;}}}}s:1:"a";a:4:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8202;}}}}}s:1:"l";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:189;}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8459;}}}}}s:1:"r";a:2:{s:1:"d";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1098;}}}}s:1:"r";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8596;}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10568;}}}}s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8621;}}}}}s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8463;}}}}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:293;}}}}}s:1:"e";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9829;}s:1:"u";a:1:{s:1:"i";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9829;}}}}}}}}s:1:"l";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8230;}}}}}s:1:"r";a:1:{s:1:"c";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8889;}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120101;}}}s:1:"k";a:1:{s:1:"s";a:2:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10533;}}}}}}s:1:"w";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10534;}}}}}}}}s:1:"o";a:5:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8703;}}}}s:1:"m";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8763;}}}}}s:1:"o";a:1:{s:1:"k";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8617;}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8618;}}}}}}}}}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120153;}}}s:1:"r";a:1:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8213;}}}}}}s:1:"s";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119997;}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8463;}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:295;}}}}}}s:1:"y";a:2:{s:1:"b";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8259;}}}}}s:1:"p";a:1:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8208;}}}}}}}s:1:"i";a:15:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:237;}s:9:"codepoint";i:237;}}}}}s:1:"c";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8291;}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:238;}s:9:"codepoint";i:238;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1080;}}}s:1:"e";a:2:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1077;}}}s:1:"x";a:1:{s:1:"c";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:161;}s:9:"codepoint";i:161;}}}}s:1:"f";a:2:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8660;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120102;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:236;}s:9:"codepoint";i:236;}}}}}s:1:"i";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8520;}s:1:"i";a:2:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10764;}}}}s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8749;}}}}s:1:"n";a:1:{s:1:"f";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10716;}}}}}s:1:"o";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8489;}}}}}s:1:"j";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:307;}}}}}s:1:"m";a:3:{s:1:"a";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:299;}}}s:1:"g";a:3:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8465;}}s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8464;}}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8465;}}}}}}s:1:"t";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:305;}}}}s:1:"o";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8887;}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:437;}}}}}s:1:"n";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8712;}s:1:"c";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8453;}}}}}s:1:"f";a:1:{s:1:"i";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8734;}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10717;}}}}}}}s:1:"o";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:305;}}}}}s:1:"t";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8747;}s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8890;}}}}s:1:"e";a:2:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8484;}}}}}s:1:"r";a:1:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8890;}}}}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10775;}}}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10812;}}}}}}}s:1:"o";a:4:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1105;}}}s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:303;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120154;}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:953;}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10812;}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:191;}s:9:"codepoint";i:191;}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119998;}}}s:1:"i";a:1:{s:1:"n";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8712;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8953;}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8949;}}}}s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8948;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8947;}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8712;}}}}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8290;}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:297;}}}}}}s:1:"u";a:2:{s:1:"k";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1110;}}}}s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:239;}s:9:"codepoint";i:239;}}}}s:1:"j";a:6:{s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:309;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1081;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120103;}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:567;}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120155;}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:119999;}}}s:1:"e";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1112;}}}}}}s:1:"u";a:1:{s:1:"k";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1108;}}}}}}s:1:"k";a:8:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"a";a:2:{s:1:";";a:1:{s:9:"codepoint";i:954;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1008;}}}}}}s:1:"c";a:2:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:311;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1082;}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120104;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:312;}}}}}}s:1:"h";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1093;}}}}s:1:"j";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1116;}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120156;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120000;}}}}}s:1:"l";a:22:{s:1:"A";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8666;}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8656;}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10523;}}}}}}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10510;}}}}}s:1:"E";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8806;}s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10891;}}}s:1:"H";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10594;}}}}s:1:"a";a:9:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:314;}}}}}s:1:"e";a:1:{s:1:"m";a:1:{s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10676;}}}}}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8466;}}}}}s:1:"m";a:1:{s:1:"b";a:1:{s:1:"d";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:955;}}}}}s:1:"n";a:1:{s:1:"g";a:3:{s:1:";";a:1:{s:9:"codepoint";i:10216;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10641;}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10216;}}}}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10885;}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:171;}s:9:"codepoint";i:171;}}}s:1:"r";a:1:{s:1:"r";a:8:{s:1:";";a:1:{s:9:"codepoint";i:8592;}s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8676;}s:1:"f";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10527;}}}}s:1:"f";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10525;}}}s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8617;}}}s:1:"l";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8619;}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10553;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10611;}}}}s:1:"t";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8610;}}}}}s:1:"t";a:3:{s:1:";";a:1:{s:9:"codepoint";i:10923;}s:1:"a";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10521;}}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10925;}}}}s:1:"b";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10508;}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10098;}}}}s:1:"r";a:2:{s:1:"a";a:1:{s:1:"c";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:123;}}s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:91;}}}}s:1:"k";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10635;}}s:1:"s";a:1:{s:1:"l";a:2:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10639;}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10637;}}}}}}}s:1:"c";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:318;}}}}}s:1:"e";a:2:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:316;}}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8968;}}}}s:1:"u";a:1:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:123;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1083;}}}s:1:"d";a:4:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10550;}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8220;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8222;}}}}}s:1:"r";a:2:{s:1:"d";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10599;}}}}}s:1:"u";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10571;}}}}}}}s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8626;}}}}s:1:"e";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8804;}s:1:"f";a:1:{s:1:"t";a:5:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8592;}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8610;}}}}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8637;}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8636;}}}}}}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8647;}}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8596;}s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8646;}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8651;}}}}}}}}}s:1:"s";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8621;}}}}}}}}}}}}}}}}s:1:"t";a:1:{s:1:"h";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8907;}}}}}}}}}}}}}s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8922;}}s:1:"q";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8804;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8806;}}s:1:"s";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10877;}}}}}}}s:1:"s";a:5:{s:1:";";a:1:{s:9:"codepoint";i:10877;}s:1:"c";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10920;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10879;}s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10881;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10883;}}}}}}s:1:"g";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10899;}}}}s:1:"s";a:5:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10885;}}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8918;}}}}s:1:"e";a:1:{s:1:"q";a:2:{s:1:"g";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8922;}}}}s:1:"q";a:1:{s:1:"g";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10891;}}}}}}}s:1:"g";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8822;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8818;}}}}}}}s:1:"f";a:3:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10620;}}}}}s:1:"l";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8970;}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120105;}}}s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8822;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10897;}}}s:1:"h";a:2:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8637;}}s:1:"u";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8636;}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10602;}}}}}s:1:"b";a:1:{s:1:"l";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9604;}}}}}s:1:"j";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1113;}}}}s:1:"l";a:5:{s:1:";";a:1:{s:9:"codepoint";i:8810;}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8647;}}}}s:1:"c";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8990;}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10603;}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9722;}}}}}s:1:"m";a:2:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:320;}}}}}s:1:"o";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9136;}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9136;}}}}}}}}}}s:1:"n";a:4:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8808;}}s:1:"a";a:1:{s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10889;}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10889;}}}}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10887;}s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10887;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8808;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8934;}}}}}s:1:"o";a:8:{s:1:"a";a:2:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10220;}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8701;}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10214;}}}}s:1:"n";a:1:{s:1:"g";a:3:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10229;}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10231;}}}}}}}}}}}}}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10236;}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10230;}}}}}}}}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8619;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8620;}}}}}}}}}}}}}s:1:"p";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10629;}}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120157;}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10797;}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10804;}}}}}}s:1:"w";a:2:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8727;}}}}s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:95;}}}}}s:1:"z";a:3:{s:1:";";a:1:{s:9:"codepoint";i:9674;}s:1:"e";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9674;}}}}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10731;}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:40;}s:1:"l";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10643;}}}}}}s:1:"r";a:5:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8646;}}}}s:1:"c";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8991;}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8651;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10605;}}}}}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8206;}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8895;}}}}}s:1:"s";a:6:{s:1:"a";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8249;}}}}}s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120001;}}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8624;}}s:1:"i";a:1:{s:1:"m";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8818;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10893;}}s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10895;}}}}s:1:"q";a:2:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:91;}}s:1:"u";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8216;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8218;}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:322;}}}}}}s:1:"t";a:9:{s:1:";";a:1:{s:9:"codepoint";i:60;}s:9:"codepoint";i:60;s:1:"c";a:2:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10918;}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10873;}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8918;}}}}s:1:"h";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8907;}}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8905;}}}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10614;}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10875;}}}}}}s:1:"r";a:2:{s:1:"P";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10646;}}}}s:1:"i";a:3:{s:1:";";a:1:{s:9:"codepoint";i:9667;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8884;}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9666;}}}}}s:1:"u";a:1:{s:1:"r";a:2:{s:1:"d";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10570;}}}}}}s:1:"u";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10598;}}}}}}}}s:1:"m";a:14:{s:1:"D";a:1:{s:1:"D";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8762;}}}}}s:1:"a";a:4:{s:1:"c";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:175;}s:9:"codepoint";i:175;}}s:1:"l";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9794;}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10016;}s:1:"e";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10016;}}}}}}s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8614;}s:1:"s";a:1:{s:1:"t";a:1:{s:1:"o";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8614;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8615;}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8612;}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8613;}}}}}}}s:1:"r";a:1:{s:1:"k";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9646;}}}}}}s:1:"c";a:2:{s:1:"o";a:1:{s:1:"m";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10793;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1084;}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8212;}}}}}s:1:"e";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8737;}}}}}}}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120106;}}}s:1:"h";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8487;}}}s:1:"i";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:181;}s:9:"codepoint";i:181;}}}s:1:"d";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8739;}s:1:"a";a:1:{s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:42;}}}}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10992;}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:183;}s:9:"codepoint";i:183;}}}}s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8722;}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8863;}}s:1:"d";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8760;}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10794;}}}}}}}s:1:"l";a:2:{s:1:"c";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10971;}}}s:1:"d";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8230;}}}}s:1:"n";a:1:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8723;}}}}}}s:1:"o";a:2:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8871;}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120158;}}}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8723;}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120002;}}}s:1:"t";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8766;}}}}}}s:1:"u";a:3:{s:1:";";a:1:{s:9:"codepoint";i:956;}s:1:"l";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8888;}}}}}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8888;}}}}}}s:1:"n";a:23:{s:1:"L";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8653;}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8654;}}}}}}}}}}}}}}}s:1:"R";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8655;}}}}}}}}}}}s:1:"V";a:2:{s:1:"D";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8879;}}}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8878;}}}}}}s:1:"a";a:4:{s:1:"b";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8711;}}}}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:324;}}}}}s:1:"p";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8777;}s:1:"o";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:329;}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8777;}}}}}}s:1:"t";a:1:{s:1:"u";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9838;}s:1:"a";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9838;}s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8469;}}}}}}}}s:1:"b";a:1:{s:1:"s";a:1:{s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:160;}s:9:"codepoint";i:160;}}}s:1:"c";a:5:{s:1:"a";a:2:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10819;}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:328;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:326;}}}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8775;}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10818;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1085;}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8211;}}}}}s:1:"e";a:6:{s:1:";";a:1:{s:9:"codepoint";i:8800;}s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8663;}}}}s:1:"a";a:1:{s:1:"r";a:2:{s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10532;}}}s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8599;}s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8599;}}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8802;}}}}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10536;}}}}}s:1:"x";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8708;}s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8708;}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120107;}}}s:1:"g";a:3:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8817;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8817;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8821;}}}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8815;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8815;}}}}s:1:"h";a:3:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8654;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8622;}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10994;}}}}}s:1:"i";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8715;}s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8956;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8954;}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8715;}}}s:1:"j";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1114;}}}}s:1:"l";a:6:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8653;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8602;}}}}s:1:"d";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8229;}}}s:1:"e";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8816;}s:1:"f";a:1:{s:1:"t";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8602;}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8622;}}}}}}}}}}}}}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8816;}}s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8814;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8820;}}}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8814;}s:1:"r";a:1:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8938;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8940;}}}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8740;}}}}s:1:"o";a:2:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120159;}}}s:1:"t";a:4:{s:1:";";a:1:{s:9:"codepoint";i:172;}s:9:"codepoint";i:172;s:1:"i";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8713;}s:1:"v";a:3:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8713;}}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8951;}}s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8950;}}}}}s:1:"n";a:1:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8716;}s:1:"v";a:3:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8716;}}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8958;}}s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8957;}}}}}}}s:1:"p";a:3:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8742;}s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8742;}}}}}}}}s:1:"o";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10772;}}}}}}s:1:"r";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8832;}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8928;}}}}s:1:"e";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8832;}}}}}s:1:"r";a:4:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8655;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8603;}}}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8603;}}}}}}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8939;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8941;}}}}}}s:1:"s";a:7:{s:1:"c";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8833;}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8929;}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120003;}}}s:1:"h";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"t";a:2:{s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8740;}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8742;}}}}}}}}}}}}}s:1:"i";a:1:{s:1:"m";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8769;}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8772;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8772;}}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8740;}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8742;}}}}s:1:"q";a:1:{s:1:"s";a:1:{s:1:"u";a:2:{s:1:"b";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8930;}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8931;}}}}}}s:1:"u";a:3:{s:1:"b";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8836;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8840;}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8840;}}}}}}}s:1:"c";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8833;}}}s:1:"p";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8837;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8841;}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8841;}}}}}}}}}s:1:"t";a:4:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8825;}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:241;}s:9:"codepoint";i:241;}}}}s:1:"l";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8824;}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8938;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8940;}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8939;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8941;}}}}}}}}}}}}}}}}s:1:"u";a:2:{s:1:";";a:1:{s:9:"codepoint";i:957;}s:1:"m";a:3:{s:1:";";a:1:{s:9:"codepoint";i:35;}s:1:"e";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8470;}}}}s:1:"s";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8199;}}}}}s:1:"v";a:6:{s:1:"D";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8877;}}}}}s:1:"H";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10500;}}}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8876;}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"f";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10718;}}}}}}s:1:"l";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10498;}}}}}s:1:"r";a:1:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10499;}}}}}}s:1:"w";a:3:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8662;}}}}s:1:"a";a:1:{s:1:"r";a:2:{s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10531;}}}s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8598;}s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8598;}}}}}}s:1:"n";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10535;}}}}}}}s:1:"o";a:18:{s:1:"S";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9416;}}s:1:"a";a:2:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:243;}s:9:"codepoint";i:243;}}}}s:1:"s";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8859;}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8858;}s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:244;}s:9:"codepoint";i:244;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1086;}}}s:1:"d";a:5:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8861;}}}}s:1:"b";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:337;}}}}}s:1:"i";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10808;}}}s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8857;}}}s:1:"s";a:1:{s:1:"o";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10684;}}}}}}s:1:"e";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:339;}}}}}s:1:"f";a:2:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10687;}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120108;}}}s:1:"g";a:3:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:731;}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:242;}s:9:"codepoint";i:242;}}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10689;}}}s:1:"h";a:2:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10677;}}}}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8486;}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8750;}}}}s:1:"l";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8634;}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10686;}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"s";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10683;}}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8254;}}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10688;}}}s:1:"m";a:3:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:333;}}}}s:1:"e";a:1:{s:1:"g";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:969;}}}}s:1:"i";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:959;}}}}}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10678;}}s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8854;}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120160;}}}}s:1:"p";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10679;}}}s:1:"e";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10681;}}}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8853;}}}}}s:1:"r";a:7:{s:1:";";a:1:{s:9:"codepoint";i:8744;}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8635;}}}}s:1:"d";a:4:{s:1:";";a:1:{s:9:"codepoint";i:10845;}s:1:"e";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8500;}s:1:"o";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8500;}}}}}s:1:"f";a:2:{s:1:";";a:1:{s:9:"codepoint";i:170;}s:9:"codepoint";i:170;}s:1:"m";a:2:{s:1:";";a:1:{s:9:"codepoint";i:186;}s:9:"codepoint";i:186;}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8886;}}}}}s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10838;}}}s:1:"s";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10839;}}}}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10843;}}}s:1:"s";a:3:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8500;}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:2:{s:1:";";a:1:{s:9:"codepoint";i:248;}s:9:"codepoint";i:248;}}}}s:1:"o";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8856;}}}}s:1:"t";a:1:{s:1:"i";a:2:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:245;}s:9:"codepoint";i:245;}}}s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8855;}s:1:"a";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10806;}}}}}}}}s:1:"u";a:1:{s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:246;}s:9:"codepoint";i:246;}}}s:1:"v";a:1:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9021;}}}}}}s:1:"p";a:12:{s:1:"a";a:1:{s:1:"r";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8741;}s:1:"a";a:3:{s:1:";";a:1:{s:9:"codepoint";i:182;}s:9:"codepoint";i:182;s:1:"l";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8741;}}}}}}s:1:"s";a:2:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10995;}}}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:11005;}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8706;}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1087;}}}s:1:"e";a:1:{s:1:"r";a:5:{s:1:"c";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:37;}}}}s:1:"i";a:1:{s:1:"o";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:46;}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8240;}}}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8869;}}s:1:"t";a:1:{s:1:"e";a:1:{s:1:"n";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8241;}}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120109;}}}s:1:"h";a:3:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:966;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:966;}}}s:1:"m";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8499;}}}}}s:1:"o";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9742;}}}}}s:1:"i";a:3:{s:1:";";a:1:{s:9:"codepoint";i:960;}s:1:"t";a:1:{s:1:"c";a:1:{s:1:"h";a:1:{s:1:"f";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8916;}}}}}}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:982;}}}s:1:"l";a:2:{s:1:"a";a:1:{s:1:"n";a:2:{s:1:"c";a:1:{s:1:"k";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8463;}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8462;}}}}s:1:"k";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8463;}}}}}s:1:"u";a:1:{s:1:"s";a:9:{s:1:";";a:1:{s:9:"codepoint";i:43;}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10787;}}}}}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8862;}}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10786;}}}}s:1:"d";a:2:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8724;}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10789;}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10866;}}s:1:"m";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:177;}s:9:"codepoint";i:177;}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10790;}}}}s:1:"t";a:1:{s:1:"w";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10791;}}}}}}}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:177;}}s:1:"o";a:3:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10773;}}}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120161;}}}s:1:"u";a:1:{s:1:"n";a:1:{s:1:"d";a:2:{s:1:";";a:1:{s:9:"codepoint";i:163;}s:9:"codepoint";i:163;}}}}s:1:"r";a:10:{s:1:";";a:1:{s:9:"codepoint";i:8826;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10931;}}s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10935;}}}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8828;}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10927;}s:1:"c";a:6:{s:1:";";a:1:{s:9:"codepoint";i:8826;}s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10935;}}}}}}}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"l";a:1:{s:1:"y";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8828;}}}}}}}}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10927;}}}s:1:"n";a:3:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10937;}}}}}}}s:1:"e";a:1:{s:1:"q";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10933;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8936;}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8830;}}}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8242;}s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8473;}}}}}s:1:"n";a:3:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10933;}}s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10937;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8936;}}}}}s:1:"o";a:3:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8719;}}s:1:"f";a:3:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9006;}}}}}s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8978;}}}}}s:1:"s";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8979;}}}}}}s:1:"p";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8733;}s:1:"t";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8733;}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8830;}}}}s:1:"u";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8880;}}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120005;}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:968;}}}s:1:"u";a:1:{s:1:"n";a:1:{s:1:"c";a:1:{s:1:"s";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8200;}}}}}}}s:1:"q";a:6:{s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120110;}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10764;}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120162;}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8279;}}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120006;}}}}s:1:"u";a:3:{s:1:"a";a:1:{s:1:"t";a:2:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"n";a:1:{s:1:"i";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8461;}}}}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10774;}}}}}}s:1:"e";a:1:{s:1:"s";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:63;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8799;}}}}}}s:1:"o";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:34;}s:9:"codepoint";i:34;}}}}s:1:"r";a:21:{s:1:"A";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8667;}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8658;}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10524;}}}}}}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10511;}}}}}s:1:"H";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10596;}}}}s:1:"a";a:7:{s:1:"c";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10714;}}s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:341;}}}}}s:1:"d";a:1:{s:1:"i";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8730;}}}}s:1:"e";a:1:{s:1:"m";a:1:{s:1:"p";a:1:{s:1:"t";a:1:{s:1:"y";a:1:{s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10675;}}}}}}}s:1:"n";a:1:{s:1:"g";a:4:{s:1:";";a:1:{s:9:"codepoint";i:10217;}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10642;}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10661;}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10217;}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:187;}s:9:"codepoint";i:187;}}}s:1:"r";a:1:{s:1:"r";a:11:{s:1:";";a:1:{s:9:"codepoint";i:8594;}s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10613;}}}s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8677;}s:1:"f";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10528;}}}}s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10547;}}s:1:"f";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10526;}}}s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8618;}}}s:1:"l";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8620;}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10565;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10612;}}}}s:1:"t";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8611;}}}s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8605;}}}}s:1:"t";a:2:{s:1:"a";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10522;}}}}s:1:"i";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8758;}s:1:"n";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8474;}}}}}}}}}s:1:"b";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10509;}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10099;}}}}s:1:"r";a:2:{s:1:"a";a:1:{s:1:"c";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:125;}}s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:93;}}}}s:1:"k";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10636;}}s:1:"s";a:1:{s:1:"l";a:2:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10638;}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10640;}}}}}}}s:1:"c";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:345;}}}}}s:1:"e";a:2:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:343;}}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8969;}}}}s:1:"u";a:1:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:125;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1088;}}}s:1:"d";a:4:{s:1:"c";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10551;}}}s:1:"l";a:1:{s:1:"d";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10601;}}}}}}s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8221;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8221;}}}}}s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8627;}}}}s:1:"e";a:3:{s:1:"a";a:1:{s:1:"l";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8476;}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8475;}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8476;}}}}}s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8477;}}}}s:1:"c";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9645;}}}s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:174;}s:9:"codepoint";i:174;}}s:1:"f";a:3:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10621;}}}}}s:1:"l";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8971;}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120111;}}}s:1:"h";a:2:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8641;}}s:1:"u";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8640;}s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10604;}}}}}s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:961;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1009;}}}}s:1:"i";a:3:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:6:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8594;}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8611;}}}}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8641;}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8640;}}}}}}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8644;}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8652;}}}}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8649;}}}}}}}}}}}}s:1:"s";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8605;}}}}}}}}}}}s:1:"t";a:1:{s:1:"h";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8908;}}}}}}}}}}}}}}s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:730;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8787;}}}}}}}}}}}}s:1:"l";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8644;}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8652;}}}}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8207;}}}s:1:"m";a:1:{s:1:"o";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9137;}s:1:"a";a:1:{s:1:"c";a:1:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9137;}}}}}}}}}}s:1:"n";a:1:{s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10990;}}}}}s:1:"o";a:4:{s:1:"a";a:2:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10221;}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8702;}}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10215;}}}}s:1:"p";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10630;}}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120163;}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10798;}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10805;}}}}}}}s:1:"p";a:2:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:41;}s:1:"g";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10644;}}}}}s:1:"p";a:1:{s:1:"o";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10770;}}}}}}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8649;}}}}}s:1:"s";a:4:{s:1:"a";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8250;}}}}}s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120007;}}}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8625;}}s:1:"q";a:2:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:93;}}s:1:"u";a:1:{s:1:"o";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8217;}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8217;}}}}}}s:1:"t";a:3:{s:1:"h";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8908;}}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8906;}}}}}s:1:"r";a:1:{s:1:"i";a:4:{s:1:";";a:1:{s:9:"codepoint";i:9657;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8885;}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9656;}}s:1:"l";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10702;}}}}}}}}s:1:"u";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10600;}}}}}}}s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8478;}}}s:1:"s";a:19:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:347;}}}}}}s:1:"b";a:1:{s:1:"q";a:1:{s:1:"u";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8218;}}}}}s:1:"c";a:10:{s:1:";";a:1:{s:9:"codepoint";i:8827;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10932;}}s:1:"a";a:2:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10936;}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:353;}}}}}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8829;}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10928;}s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:351;}}}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:349;}}}}s:1:"n";a:3:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10934;}}s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10938;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8937;}}}}}s:1:"p";a:1:{s:1:"o";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10771;}}}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8831;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1089;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8901;}s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8865;}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10854;}}}}}s:1:"e";a:7:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8664;}}}}s:1:"a";a:1:{s:1:"r";a:2:{s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10533;}}}s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8600;}s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8600;}}}}}}s:1:"c";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:167;}s:9:"codepoint";i:167;}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:59;}}}s:1:"s";a:1:{s:1:"w";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10537;}}}}}s:1:"t";a:1:{s:1:"m";a:2:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8726;}}}}}s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8726;}}}}s:1:"x";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10038;}}}}s:1:"f";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:120112;}s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8994;}}}}}}s:1:"h";a:4:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9839;}}}}s:1:"c";a:2:{s:1:"h";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1097;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1096;}}}s:1:"o";a:1:{s:1:"r";a:1:{s:1:"t";a:2:{s:1:"m";a:1:{s:1:"i";a:1:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8739;}}}}s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8741;}}}}}}}}}}}}s:1:"y";a:2:{s:1:";";a:1:{s:9:"codepoint";i:173;}s:9:"codepoint";i:173;}}s:1:"i";a:2:{s:1:"g";a:1:{s:1:"m";a:1:{s:1:"a";a:3:{s:1:";";a:1:{s:9:"codepoint";i:963;}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:962;}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:962;}}}}}s:1:"m";a:8:{s:1:";";a:1:{s:9:"codepoint";i:8764;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10858;}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8771;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8771;}}}s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10910;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10912;}}}s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10909;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10911;}}}s:1:"n";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8774;}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10788;}}}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10610;}}}}}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8592;}}}}}s:1:"m";a:4:{s:1:"a";a:2:{s:1:"l";a:1:{s:1:"l";a:1:{s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"m";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8726;}}}}}}}}}}}s:1:"s";a:1:{s:1:"h";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10803;}}}}}s:1:"e";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"s";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10724;}}}}}}}s:1:"i";a:2:{s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8739;}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8995;}}}}s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10922;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10924;}}}}s:1:"o";a:3:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1100;}}}}}s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:47;}s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10692;}s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9023;}}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120164;}}}}s:1:"p";a:1:{s:1:"a";a:2:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:"s";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9824;}s:1:"u";a:1:{s:1:"i";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9824;}}}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8741;}}}}s:1:"q";a:3:{s:1:"c";a:2:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8851;}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8852;}}}}s:1:"s";a:1:{s:1:"u";a:2:{s:1:"b";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8847;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8849;}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8847;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8849;}}}}}}}s:1:"p";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8848;}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8850;}}s:1:"s";a:1:{s:1:"e";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8848;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8850;}}}}}}}}}s:1:"u";a:3:{s:1:";";a:1:{s:9:"codepoint";i:9633;}s:1:"a";a:1:{s:1:"r";a:2:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9633;}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9642;}}}}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9642;}}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8594;}}}}}s:1:"s";a:4:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120008;}}}s:1:"e";a:1:{s:1:"t";a:1:{s:1:"m";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8726;}}}}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8995;}}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8902;}}}}}}s:1:"t";a:2:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9734;}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9733;}}}}s:1:"r";a:2:{s:1:"a";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:2:{s:1:"e";a:1:{s:1:"p";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1013;}}}}}}}}s:1:"p";a:1:{s:1:"h";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:981;}}}}}}}}}s:1:"n";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:175;}}}}}s:1:"u";a:5:{s:1:"b";a:9:{s:1:";";a:1:{s:9:"codepoint";i:8834;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10949;}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10941;}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8838;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10947;}}}}}s:1:"m";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10945;}}}}}s:1:"n";a:2:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10955;}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8842;}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10943;}}}}}s:1:"r";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10617;}}}}}s:1:"s";a:3:{s:1:"e";a:1:{s:1:"t";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8834;}s:1:"e";a:1:{s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8838;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10949;}}}}s:1:"n";a:1:{s:1:"e";a:1:{s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8842;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10955;}}}}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10951;}}}s:1:"u";a:2:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10965;}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10963;}}}}}s:1:"c";a:1:{s:1:"c";a:6:{s:1:";";a:1:{s:9:"codepoint";i:8827;}s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10936;}}}}}}}s:1:"c";a:1:{s:1:"u";a:1:{s:1:"r";a:1:{s:1:"l";a:1:{s:1:"y";a:1:{s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8829;}}}}}}}}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10928;}}}s:1:"n";a:3:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10938;}}}}}}}s:1:"e";a:1:{s:1:"q";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10934;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8937;}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8831;}}}}}}s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8721;}}s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9834;}}}s:1:"p";a:13:{i:1;a:2:{s:1:";";a:1:{s:9:"codepoint";i:185;}s:9:"codepoint";i:185;}i:2;a:2:{s:1:";";a:1:{s:9:"codepoint";i:178;}s:9:"codepoint";i:178;}i:3;a:2:{s:1:";";a:1:{s:9:"codepoint";i:179;}s:9:"codepoint";i:179;}s:1:";";a:1:{s:9:"codepoint";i:8835;}s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10950;}}s:1:"d";a:2:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10942;}}}s:1:"s";a:1:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10968;}}}}}s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8839;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10948;}}}}}s:1:"h";a:1:{s:1:"s";a:1:{s:1:"u";a:1:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10967;}}}}}s:1:"l";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10619;}}}}}s:1:"m";a:1:{s:1:"u";a:1:{s:1:"l";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10946;}}}}}s:1:"n";a:2:{s:1:"E";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10956;}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8843;}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10944;}}}}}s:1:"s";a:3:{s:1:"e";a:1:{s:1:"t";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8835;}s:1:"e";a:1:{s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8839;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10950;}}}}s:1:"n";a:1:{s:1:"e";a:1:{s:1:"q";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8843;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10956;}}}}}}}s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10952;}}}s:1:"u";a:2:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10964;}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10966;}}}}}}s:1:"w";a:3:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8665;}}}}s:1:"a";a:1:{s:1:"r";a:2:{s:1:"h";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10534;}}}s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8601;}s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8601;}}}}}}s:1:"n";a:1:{s:1:"w";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10538;}}}}}}s:1:"z";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"g";a:2:{s:1:";";a:1:{s:9:"codepoint";i:223;}s:9:"codepoint";i:223;}}}}}s:1:"t";a:13:{s:1:"a";a:2:{s:1:"r";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8982;}}}}}s:1:"u";a:1:{s:1:";";a:1:{s:9:"codepoint";i:964;}}}s:1:"b";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9140;}}}}s:1:"c";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:357;}}}}}s:1:"e";a:1:{s:1:"d";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:355;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1090;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8411;}}}}s:1:"e";a:1:{s:1:"l";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8981;}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120113;}}}s:1:"h";a:4:{s:1:"e";a:2:{s:1:"r";a:1:{s:1:"e";a:2:{i:4;a:1:{s:1:";";a:1:{s:9:"codepoint";i:8756;}}s:1:"f";a:1:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8756;}}}}}}}s:1:"t";a:1:{s:1:"a";a:3:{s:1:";";a:1:{s:9:"codepoint";i:952;}s:1:"s";a:1:{s:1:"y";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:977;}}}}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:977;}}}}}s:1:"i";a:2:{s:1:"c";a:1:{s:1:"k";a:2:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"x";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8776;}}}}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8764;}}}}}}s:1:"n";a:1:{s:1:"s";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8201;}}}}}s:1:"k";a:2:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8776;}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8764;}}}}}s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:254;}s:9:"codepoint";i:254;}}}}s:1:"i";a:3:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:732;}}}}s:1:"m";a:1:{s:1:"e";a:1:{s:1:"s";a:4:{s:1:";";a:1:{s:9:"codepoint";i:215;}s:9:"codepoint";i:215;s:1:"b";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8864;}s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10801;}}}}s:1:"d";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10800;}}}}}s:1:"n";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8749;}}}}s:1:"o";a:3:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10536;}}}s:1:"p";a:4:{s:1:";";a:1:{s:9:"codepoint";i:8868;}s:1:"b";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9014;}}}}s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10993;}}}}s:1:"f";a:2:{s:1:";";a:1:{s:9:"codepoint";i:120165;}s:1:"o";a:1:{s:1:"r";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10970;}}}}}}s:1:"s";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10537;}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8244;}}}}}}s:1:"r";a:3:{s:1:"a";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8482;}}}}s:1:"i";a:7:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:5:{s:1:";";a:1:{s:9:"codepoint";i:9653;}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9663;}}}}}s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9667;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8884;}}}}}}}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8796;}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9657;}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8885;}}}}}}}}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9708;}}}}s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8796;}}s:1:"m";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10810;}}}}}}s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10809;}}}}}s:1:"s";a:1:{s:1:"b";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10701;}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10811;}}}}}}s:1:"p";a:1:{s:1:"e";a:1:{s:1:"z";a:1:{s:1:"i";a:1:{s:1:"u";a:1:{s:1:"m";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9186;}}}}}}}}s:1:"s";a:3:{s:1:"c";a:2:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120009;}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1094;}}}s:1:"h";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1115;}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:359;}}}}}}s:1:"w";a:2:{s:1:"i";a:1:{s:1:"x";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8812;}}}}s:1:"o";a:1:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:"a";a:1:{s:1:"d";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8606;}}}}}}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8608;}}}}}}}}}}}}}}}}}}s:1:"u";a:18:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8657;}}}}s:1:"H";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10595;}}}}s:1:"a";a:2:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:250;}s:9:"codepoint";i:250;}}}}s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8593;}}}}s:1:"b";a:1:{s:1:"r";a:2:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1118;}}}s:1:"e";a:1:{s:1:"v";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:365;}}}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:2:{s:1:";";a:1:{s:9:"codepoint";i:251;}s:9:"codepoint";i:251;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1091;}}}s:1:"d";a:3:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8645;}}}}s:1:"b";a:1:{s:1:"l";a:1:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:369;}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10606;}}}}}s:1:"f";a:2:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10622;}}}}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120114;}}}s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"v";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:249;}s:9:"codepoint";i:249;}}}}}s:1:"h";a:2:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:"l";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8639;}}s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8638;}}}}s:1:"b";a:1:{s:1:"l";a:1:{s:1:"k";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9600;}}}}}s:1:"l";a:2:{s:1:"c";a:2:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8988;}s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8988;}}}}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8975;}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9720;}}}}}s:1:"m";a:2:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:363;}}}}s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:168;}s:9:"codepoint";i:168;}}s:1:"o";a:2:{s:1:"g";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:371;}}}}s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120166;}}}}s:1:"p";a:6:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8593;}}}}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"n";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8597;}}}}}}}}}}s:1:"h";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:"o";a:1:{s:1:"o";a:1:{s:1:"n";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8639;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8638;}}}}}}}}}}}}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8846;}}}}s:1:"s";a:1:{s:1:"i";a:3:{s:1:";";a:1:{s:9:"codepoint";i:965;}s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:978;}}s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:965;}}}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"w";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8648;}}}}}}}}}}s:1:"r";a:3:{s:1:"c";a:2:{s:1:"o";a:1:{s:1:"r";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8989;}s:1:"e";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8989;}}}}}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8974;}}}}}s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:367;}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9721;}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120010;}}}}s:1:"t";a:3:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8944;}}}}s:1:"i";a:1:{s:1:"l";a:1:{s:1:"d";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:361;}}}}}s:1:"r";a:1:{s:1:"i";a:2:{s:1:";";a:1:{s:9:"codepoint";i:9653;}s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9652;}}}}}s:1:"u";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8648;}}}}s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:252;}s:9:"codepoint";i:252;}}}s:1:"w";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10663;}}}}}}}}s:1:"v";a:14:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8661;}}}}s:1:"B";a:1:{s:1:"a";a:1:{s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:10984;}s:1:"v";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10985;}}}}}s:1:"D";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8872;}}}}}s:1:"a";a:2:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10652;}}}}}s:1:"r";a:7:{s:1:"e";a:1:{s:1:"p";a:1:{s:1:"s";a:1:{s:1:"i";a:1:{s:1:"l";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:949;}}}}}}}}s:1:"k";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:"p";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1008;}}}}}}s:1:"n";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:"i";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8709;}}}}}}}}s:1:"p";a:3:{s:1:"h";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:966;}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:982;}}s:1:"r";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:"t";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8733;}}}}}}}s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8597;}s:1:"h";a:1:{s:1:"o";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1009;}}}}s:1:"s";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"m";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:962;}}}}}}s:1:"t";a:2:{s:1:"h";a:1:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:977;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"a";a:1:{s:1:"n";a:1:{s:1:"g";a:1:{s:1:"l";a:1:{s:1:"e";a:2:{s:1:"l";a:1:{s:1:"e";a:1:{s:1:"f";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8882;}}}}}s:1:"r";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"h";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8883;}}}}}}}}}}}}}}}}s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1074;}}}s:1:"d";a:1:{s:1:"a";a:1:{s:1:"s";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8866;}}}}}s:1:"e";a:3:{s:1:"e";a:3:{s:1:";";a:1:{s:9:"codepoint";i:8744;}s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8891;}}}}s:1:"e";a:1:{s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8794;}}}}s:1:"l";a:1:{s:1:"l";a:1:{s:1:"i";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8942;}}}}}s:1:"r";a:2:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:124;}}}}s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:124;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120115;}}}s:1:"l";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8882;}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120167;}}}}s:1:"p";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8733;}}}}}s:1:"r";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8883;}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120011;}}}}s:1:"z";a:1:{s:1:"i";a:1:{s:1:"g";a:1:{s:1:"z";a:1:{s:1:"a";a:1:{s:1:"g";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10650;}}}}}}}}s:1:"w";a:7:{s:1:"c";a:1:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:373;}}}}}s:1:"e";a:2:{s:1:"d";a:2:{s:1:"b";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10847;}}}}s:1:"g";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8743;}s:1:"q";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8793;}}}}}s:1:"i";a:1:{s:1:"e";a:1:{s:1:"r";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8472;}}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120116;}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120168;}}}}s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8472;}}s:1:"r";a:2:{s:1:";";a:1:{s:9:"codepoint";i:8768;}s:1:"e";a:1:{s:1:"a";a:1:{s:1:"t";a:1:{s:1:"h";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8768;}}}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120012;}}}}}s:1:"x";a:14:{s:1:"c";a:3:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8898;}}}s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9711;}}}}s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8899;}}}}s:1:"d";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9661;}}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120117;}}}s:1:"h";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10234;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10231;}}}}}s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:958;}}s:1:"l";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10232;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10229;}}}}}s:1:"m";a:1:{s:1:"a";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10236;}}}}s:1:"n";a:1:{s:1:"i";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8955;}}}}s:1:"o";a:3:{s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10752;}}}}s:1:"p";a:2:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120169;}}s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10753;}}}}}s:1:"t";a:1:{s:1:"i";a:1:{s:1:"m";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10754;}}}}}}s:1:"r";a:2:{s:1:"A";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10233;}}}}s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10230;}}}}}s:1:"s";a:2:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120013;}}}s:1:"q";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"p";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10758;}}}}}}s:1:"u";a:2:{s:1:"p";a:1:{s:1:"l";a:1:{s:1:"u";a:1:{s:1:"s";a:1:{s:1:";";a:1:{s:9:"codepoint";i:10756;}}}}}s:1:"t";a:1:{s:1:"r";a:1:{s:1:"i";a:1:{s:1:";";a:1:{s:9:"codepoint";i:9651;}}}}}s:1:"v";a:1:{s:1:"e";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8897;}}}}s:1:"w";a:1:{s:1:"e";a:1:{s:1:"d";a:1:{s:1:"g";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8896;}}}}}}}s:1:"y";a:8:{s:1:"a";a:1:{s:1:"c";a:2:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:2:{s:1:";";a:1:{s:9:"codepoint";i:253;}s:9:"codepoint";i:253;}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1103;}}}}s:1:"c";a:2:{s:1:"i";a:1:{s:1:"r";a:1:{s:1:"c";a:1:{s:1:";";a:1:{s:9:"codepoint";i:375;}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1099;}}}s:1:"e";a:1:{s:1:"n";a:2:{s:1:";";a:1:{s:9:"codepoint";i:165;}s:9:"codepoint";i:165;}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120118;}}}s:1:"i";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1111;}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120170;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120014;}}}}s:1:"u";a:2:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1102;}}}s:1:"m";a:1:{s:1:"l";a:2:{s:1:";";a:1:{s:9:"codepoint";i:255;}s:9:"codepoint";i:255;}}}}s:1:"z";a:10:{s:1:"a";a:1:{s:1:"c";a:1:{s:1:"u";a:1:{s:1:"t";a:1:{s:1:"e";a:1:{s:1:";";a:1:{s:9:"codepoint";i:378;}}}}}}s:1:"c";a:2:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"o";a:1:{s:1:"n";a:1:{s:1:";";a:1:{s:9:"codepoint";i:382;}}}}}s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1079;}}}s:1:"d";a:1:{s:1:"o";a:1:{s:1:"t";a:1:{s:1:";";a:1:{s:9:"codepoint";i:380;}}}}s:1:"e";a:2:{s:1:"e";a:1:{s:1:"t";a:1:{s:1:"r";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8488;}}}}}s:1:"t";a:1:{s:1:"a";a:1:{s:1:";";a:1:{s:9:"codepoint";i:950;}}}}s:1:"f";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120119;}}}s:1:"h";a:1:{s:1:"c";a:1:{s:1:"y";a:1:{s:1:";";a:1:{s:9:"codepoint";i:1078;}}}}s:1:"i";a:1:{s:1:"g";a:1:{s:1:"r";a:1:{s:1:"a";a:1:{s:1:"r";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8669;}}}}}}}s:1:"o";a:1:{s:1:"p";a:1:{s:1:"f";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120171;}}}}s:1:"s";a:1:{s:1:"c";a:1:{s:1:"r";a:1:{s:1:";";a:1:{s:9:"codepoint";i:120015;}}}}s:1:"w";a:2:{s:1:"j";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8205;}}s:1:"n";a:1:{s:1:"j";a:1:{s:1:";";a:1:{s:9:"codepoint";i:8204;}}}}}} \ No newline at end of file