/[suikacvs]/markup/html/whatpm/Whatpm/HTML/Tokenizer.pm.src
Suika

Diff of /markup/html/whatpm/Whatpm/HTML/Tokenizer.pm.src

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.17 by wakaba, Sun Oct 19 04:39:25 2008 UTC revision 1.33 by wakaba, Sat Sep 5 10:41:07 2009 UTC
# Line 105  sub COMMENT_START_STATE () { 14 } Line 105  sub COMMENT_START_STATE () { 14 }
105  sub COMMENT_START_DASH_STATE () { 15 }  sub COMMENT_START_DASH_STATE () { 15 }
106  sub COMMENT_STATE () { 16 }  sub COMMENT_STATE () { 16 }
107  sub COMMENT_END_STATE () { 17 }  sub COMMENT_END_STATE () { 17 }
108    sub COMMENT_END_BANG_STATE () { 102 }
109    sub COMMENT_END_SPACE_STATE () { 103 } ## LAST
110  sub COMMENT_END_DASH_STATE () { 18 }  sub COMMENT_END_DASH_STATE () { 18 }
111  sub BOGUS_COMMENT_STATE () { 19 }  sub BOGUS_COMMENT_STATE () { 19 }
112  sub DOCTYPE_STATE () { 20 }  sub DOCTYPE_STATE () { 20 }
# Line 177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO Line 179  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO
179  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }
180  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }
181  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }
182  sub BOGUS_MD_STATE () { 85 }  sub BEFORE_NDATA_STATE () { 85 }
183    sub NDATA_STATE () { 86 }
184    sub AFTER_NDATA_STATE () { 87 }
185    sub BEFORE_NOTATION_NAME_STATE () { 88 }
186    sub NOTATION_NAME_STATE () { 89 }
187    sub DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE () { 90 }
188    sub DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE () { 91 }
189    sub ENTITY_VALUE_ENTITY_STATE () { 92 }
190    sub AFTER_ELEMENT_NAME_STATE () { 93 }
191    sub BEFORE_ELEMENT_CONTENT_STATE () { 94 }
192    sub CONTENT_KEYWORD_STATE () { 95 }
193    sub AFTER_CM_GROUP_OPEN_STATE () { 96 }
194    sub CM_ELEMENT_NAME_STATE () { 97 }
195    sub AFTER_CM_ELEMENT_NAME_STATE () { 98 }
196    sub AFTER_CM_GROUP_CLOSE_STATE () { 99 }
197    sub AFTER_MD_DEF_STATE () { 100 }
198    sub BOGUS_MD_STATE () { 101 }
199    
200  ## Tree constructor state constants (see Whatpm::HTML for the full  ## Tree constructor state constants (see Whatpm::HTML for the full
201  ## list and descriptions)  ## list and descriptions)
# Line 844  sub _get_next_token ($) { Line 862  sub _get_next_token ($) {
862          $self->{s_kwd} = '';          $self->{s_kwd} = '';
863          # reconsume          # reconsume
864    
865          !!!emit ($self->{ct}); # start tag or end tag          ## Discard the token.
866            #!!!emit ($self->{ct}); # start tag or end tag
867    
868          redo A;          redo A;
869        } elsif ($self->{nc} == 0x002F) { # /        } elsif ($self->{nc} == 0x002F) { # /
# Line 925  sub _get_next_token ($) { Line 944  sub _get_next_token ($) {
944          $self->{s_kwd} = '';          $self->{s_kwd} = '';
945          # reconsume          # reconsume
946    
947          !!!emit ($self->{ct}); # start tag or end tag          ## Discard the token.
948            #!!!emit ($self->{ct}); # start tag or end tag
949    
950          redo A;          redo A;
951        } else {        } else {
952          if ({          if ({
953               0x0022 => 1, # "               0x0022 => 1, # "
954               0x0027 => 1, # '               0x0027 => 1, # '
955                 0x003C => 1, # <
956               0x003D => 1, # =               0x003D => 1, # =
957              }->{$self->{nc}}) {              }->{$self->{nc}}) {
958            !!!cp (55);            !!!cp (55);
# Line 1050  sub _get_next_token ($) { Line 1071  sub _get_next_token ($) {
1071          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1072          # reconsume          # reconsume
1073    
1074          !!!emit ($self->{ct}); # start tag or end tag          ## Discard the token.
1075            #!!!emit ($self->{ct}); # start tag or end tag
1076    
1077          redo A;          redo A;
1078        } else {        } else {
1079          if ($self->{nc} == 0x0022 or # "          if ({
1080              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1081                 0x0027 => 1, # '
1082                 0x003C => 1, # <
1083                }->{$self->{nc}}) {
1084            !!!cp (69);            !!!cp (69);
1085            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1086            !!!parse-error (type => 'bad attribute name');            !!!parse-error (type => 'bad attribute name');
# Line 1154  sub _get_next_token ($) { Line 1179  sub _get_next_token ($) {
1179          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1180          # reconsume          # reconsume
1181    
1182          !!!emit ($self->{ct}); # start tag or end tag          ## Discard the token.
1183            #!!!emit ($self->{ct}); # start tag or end tag
1184    
1185          redo A;          redo A;
1186        } else {        } else {
# Line 1166  sub _get_next_token ($) { Line 1192  sub _get_next_token ($) {
1192            !!!cp (78.2);            !!!cp (78.2);
1193          }          }
1194    
1195          if ($self->{nc} == 0x0022 or # "          if ({
1196              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1197                 0x0027 => 1, # '
1198                 0x003C => 1, # <
1199                }->{$self->{nc}}) {
1200            !!!cp (78);            !!!cp (78);
1201            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1202            !!!parse-error (type => 'bad attribute name');            !!!parse-error (type => 'bad attribute name');
# Line 1250  sub _get_next_token ($) { Line 1279  sub _get_next_token ($) {
1279          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1280          ## reconsume          ## reconsume
1281    
1282          !!!emit ($self->{ct}); # start tag or end tag          ## Discard the token.
1283            #!!!emit ($self->{ct}); # start tag or end tag
1284    
1285          redo A;          redo A;
1286        } else {        } else {
1287          if ($self->{nc} == 0x003D) { # =          if ($self->{nc} == 0x003D or $self->{nc} == 0x003C) { # =, <
1288            !!!cp (93);            !!!cp (93);
1289            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1290            !!!parse-error (type => 'bad attribute value');            !!!parse-error (type => 'bad attribute value');
# Line 1300  sub _get_next_token ($) { Line 1330  sub _get_next_token ($) {
1330          $self->{state} = ENTITY_STATE;          $self->{state} = ENTITY_STATE;
1331          !!!next-input-character;          !!!next-input-character;
1332          redo A;          redo A;
1333          } elsif ($self->{is_xml} and
1334                   $is_space->{$self->{nc}}) {
1335            !!!cp (97.1);
1336            $self->{ca}->{value} .= ' ';
1337            ## Stay in the state.
1338            !!!next-input-character;
1339            redo A;
1340        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1341          !!!parse-error (type => 'unclosed attribute value');          !!!parse-error (type => 'unclosed attribute value');
1342          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1324  sub _get_next_token ($) { Line 1361  sub _get_next_token ($) {
1361            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1362            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1363            ## reconsume            ## reconsume
1364            !!!emit ($self->{ct}); # end tag  
1365              ## Discard the token.
1366              #!!!emit ($self->{ct}); # end tag
1367    
1368            redo A;            redo A;
1369          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
1370            ## XML5: No parse error above; not defined yet.            ## XML5: No parse error above; not defined yet.
1371            push @{$self->{ct}->{attrdefs}}, $self->{ca};            push @{$self->{ct}->{attrdefs}}, $self->{ca};
1372            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1373            ## Reconsume.            ## Reconsume.
1374            !!!emit ($self->{ct}); # ATTLIST  
1375              ## Discard the token.
1376              #!!!emit ($self->{ct}); # ATTLIST
1377    
1378            redo A;            redo A;
1379          } else {          } else {
1380            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
# Line 1347  sub _get_next_token ($) { Line 1390  sub _get_next_token ($) {
1390          }          }
1391          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1392          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1393                                q["&<],                                qq["&<\x09\x0C\x20],
1394                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1395    
1396          ## Stay in the state          ## Stay in the state
# Line 1384  sub _get_next_token ($) { Line 1427  sub _get_next_token ($) {
1427          $self->{state} = ENTITY_STATE;          $self->{state} = ENTITY_STATE;
1428          !!!next-input-character;          !!!next-input-character;
1429          redo A;          redo A;
1430          } elsif ($self->{is_xml} and
1431                   $is_space->{$self->{nc}}) {
1432            !!!cp (103.1);
1433            $self->{ca}->{value} .= ' ';
1434            ## Stay in the state.
1435            !!!next-input-character;
1436            redo A;
1437        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1438          !!!parse-error (type => 'unclosed attribute value');          !!!parse-error (type => 'unclosed attribute value');
1439          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1393  sub _get_next_token ($) { Line 1443  sub _get_next_token ($) {
1443            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1444            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1445            ## reconsume            ## reconsume
1446            !!!emit ($self->{ct}); # start tag  
1447              ## Discard the token.
1448              #!!!emit ($self->{ct}); # start tag
1449    
1450            redo A;            redo A;
1451          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
1452            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1408  sub _get_next_token ($) { Line 1461  sub _get_next_token ($) {
1461            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1462            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1463            ## reconsume            ## reconsume
1464            !!!emit ($self->{ct}); # end tag  
1465              ## Discard the token.
1466              #!!!emit ($self->{ct}); # end tag
1467    
1468            redo A;            redo A;
1469          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
1470            ## XML5: No parse error above; not defined yet.            ## XML5: No parse error above; not defined yet.
1471            push @{$self->{ct}->{attrdefs}}, $self->{ca};            push @{$self->{ct}->{attrdefs}}, $self->{ca};
1472            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1473            ## Reconsume.            ## Reconsume.
1474            !!!emit ($self->{ct}); # ATTLIST  
1475              ## Discard the token.
1476              #!!!emit ($self->{ct}); # ATTLIST
1477    
1478            redo A;            redo A;
1479          } else {          } else {
1480            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
# Line 1431  sub _get_next_token ($) { Line 1490  sub _get_next_token ($) {
1490          }          }
1491          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1492          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1493                                q['&<],                                qq['&<\x09\x0C\x20],
1494                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1495    
1496          ## Stay in the state          ## Stay in the state
# Line 1510  sub _get_next_token ($) { Line 1569  sub _get_next_token ($) {
1569            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1570            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1571            ## reconsume            ## reconsume
1572            !!!emit ($self->{ct}); # start tag  
1573              ## Discard the token.
1574              #!!!emit ($self->{ct}); # start tag
1575              
1576            redo A;            redo A;
1577          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
1578            !!!parse-error (type => 'unclosed tag');            !!!parse-error (type => 'unclosed tag');
# Line 1526  sub _get_next_token ($) { Line 1588  sub _get_next_token ($) {
1588            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1589            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1590            ## reconsume            ## reconsume
1591            !!!emit ($self->{ct}); # end tag  
1592              ## Discard the token.
1593              #!!!emit ($self->{ct}); # end tag
1594    
1595            redo A;            redo A;
1596          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
1597            !!!parse-error (type => 'unclosed md'); ## TODO: type            !!!parse-error (type => 'unclosed md'); ## TODO: type
1598            push @{$self->{ct}->{attrdefs}}, $self->{ca};            push @{$self->{ct}->{attrdefs}}, $self->{ca};
1599            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1600            ## Reconsume.            ## Reconsume.
1601            !!!emit ($self->{ct}); # ATTLIST  
1602              ## Discard the token.
1603              #!!!emit ($self->{ct}); # ATTLIST
1604    
1605            redo A;            redo A;
1606          } else {          } else {
1607            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
# Line 1543  sub _get_next_token ($) { Line 1611  sub _get_next_token ($) {
1611               0x0022 => 1, # "               0x0022 => 1, # "
1612               0x0027 => 1, # '               0x0027 => 1, # '
1613               0x003D => 1, # =               0x003D => 1, # =
1614                 0x003C => 1, # <
1615              }->{$self->{nc}}) {              }->{$self->{nc}}) {
1616            !!!cp (115);            !!!cp (115);
1617            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 1552  sub _get_next_token ($) { Line 1621  sub _get_next_token ($) {
1621          }          }
1622          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1623          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1624                                q["'=& >],                                qq["'=& \x09\x0C>],
1625                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1626    
1627          ## Stay in the state          ## Stay in the state
# Line 1612  sub _get_next_token ($) { Line 1681  sub _get_next_token ($) {
1681          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1682          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1683          ## Reconsume.          ## Reconsume.
1684          !!!emit ($self->{ct}); # start tag or end tag  
1685            ## Discard the token.
1686            #!!!emit ($self->{ct}); # start tag or end tag
1687    
1688          redo A;          redo A;
1689        } else {        } else {
1690          !!!cp ('124.1');          !!!cp ('124.1');
# Line 1669  sub _get_next_token ($) { Line 1741  sub _get_next_token ($) {
1741          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1742          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1743          ## Reconsume.          ## Reconsume.
1744          !!!emit ($self->{ct}); # start tag or end tag  
1745            ## Discard the token.
1746            #!!!emit ($self->{ct}); # start tag or end tag
1747    
1748          redo A;          redo A;
1749        } else {        } else {
1750          !!!cp ('124.4');          !!!cp ('124.4');
# Line 2044  sub _get_next_token ($) { Line 2119  sub _get_next_token ($) {
2119          !!!next-input-character;          !!!next-input-character;
2120          redo A;          redo A;
2121        }        }
2122      } elsif ($self->{state} == COMMENT_END_STATE) {      } elsif ($self->{state} == COMMENT_END_STATE or
2123                 $self->{state} == COMMENT_END_BANG_STATE) {
2124        ## XML5: "Comment end state" and "DOCTYPE comment end state".        ## XML5: "Comment end state" and "DOCTYPE comment end state".
2125          ## (No comment end bang state.)
2126    
2127        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
2128          if ($self->{in_subset}) {          if ($self->{in_subset}) {
# Line 2062  sub _get_next_token ($) { Line 2139  sub _get_next_token ($) {
2139    
2140          redo A;          redo A;
2141        } elsif ($self->{nc} == 0x002D) { # -        } elsif ($self->{nc} == 0x002D) { # -
2142          !!!cp (152);          if ($self->{state} == COMMENT_END_BANG_STATE) {
2143          ## XML5: Not a parse error.            !!!cp (154.3);
2144          !!!parse-error (type => 'dash in comment',            $self->{ct}->{data} .= '--!'; # comment
2145                          line => $self->{line_prev},            $self->{state} = COMMENT_END_DASH_STATE;
2146                          column => $self->{column_prev});          } else {
2147          $self->{ct}->{data} .= '-'; # comment            !!!cp (152);
2148          ## Stay in the state            ## XML5: Not a parse error.
2149              !!!parse-error (type => 'dash in comment',
2150                              line => $self->{line_prev},
2151                              column => $self->{column_prev});
2152              $self->{ct}->{data} .= '-'; # comment
2153              ## Stay in the state
2154            }
2155            !!!next-input-character;
2156            redo A;
2157          } elsif ($self->{state} != COMMENT_END_BANG_STATE and
2158                   $is_space->{$self->{nc}}) {
2159            !!!cp (152.1);
2160            !!!parse-error (type => 'comment end space'); # XXX error type
2161            $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
2162            $self->{state} = COMMENT_END_SPACE_STATE;
2163            !!!next-input-character;
2164            redo A;
2165          } elsif ($self->{state} != COMMENT_END_BANG_STATE and
2166                   $self->{nc} == 0x0021) { # !
2167            !!!cp (152.2);
2168            !!!parse-error (type => 'comment end bang'); # XXX error type
2169            $self->{state} = COMMENT_END_BANG_STATE;
2170          !!!next-input-character;          !!!next-input-character;
2171          redo A;          redo A;
2172        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
# Line 2081  sub _get_next_token ($) { Line 2179  sub _get_next_token ($) {
2179            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
2180            $self->{s_kwd} = '';            $self->{s_kwd} = '';
2181          }          }
2182          ## reconsume          ## Reconsume.
2183    
2184          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
2185    
2186          redo A;          redo A;
2187        } else {        } else {
2188          !!!cp (154);          !!!cp (154);
2189          ## XML5: Not a parse error.          if ($self->{state} == COMMENT_END_BANG_STATE) {
2190          !!!parse-error (type => 'dash in comment',            $self->{ct}->{data} .= '--!' . chr ($self->{nc}); # comment
2191                          line => $self->{line_prev},          } else {
2192                          column => $self->{column_prev});            $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
2193          $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment          }
2194          $self->{state} = COMMENT_STATE;          $self->{state} = COMMENT_STATE;
2195          !!!next-input-character;          !!!next-input-character;
2196          redo A;          redo A;
2197        }        }
2198        } elsif ($self->{state} == COMMENT_END_SPACE_STATE) {
2199          ## XML5: Not exist.
2200    
2201          if ($self->{nc} == 0x003E) { # >
2202            if ($self->{in_subset}) {
2203              !!!cp (154.4);
2204              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2205            } else {
2206              !!!cp (154.5);
2207              $self->{state} = DATA_STATE;
2208              $self->{s_kwd} = '';
2209            }
2210            !!!next-input-character;
2211    
2212            !!!emit ($self->{ct}); # comment
2213    
2214            redo A;
2215          } elsif ($is_space->{$self->{nc}}) {
2216            !!!cp (154.6);
2217            $self->{ct}->{data} .= chr ($self->{nc}); # comment
2218            ## Stay in the state.
2219            !!!next-input-character;
2220            redo A;
2221          } elsif ($self->{nc} == -1) {
2222            !!!parse-error (type => 'unclosed comment');
2223            if ($self->{in_subset}) {
2224              !!!cp (154.7);
2225              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2226            } else {
2227              !!!cp (154.8);
2228              $self->{state} = DATA_STATE;
2229              $self->{s_kwd} = '';
2230            }
2231            ## Reconsume.
2232    
2233            !!!emit ($self->{ct}); # comment
2234    
2235            redo A;
2236          } else {
2237            !!!cp (154.9);
2238            $self->{ct}->{data} .= chr ($self->{nc}); # comment
2239            $self->{state} = COMMENT_STATE;
2240            !!!next-input-character;
2241            redo A;
2242          }
2243      } elsif ($self->{state} == DOCTYPE_STATE) {      } elsif ($self->{state} == DOCTYPE_STATE) {
2244        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
2245          !!!cp (155);          !!!cp (155);
2246          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
2247          !!!next-input-character;          !!!next-input-character;
2248          redo A;          redo A;
2249          } elsif ($self->{nc} == -1) {
2250            !!!cp (155.1);
2251            !!!parse-error (type => 'unclosed DOCTYPE');
2252            $self->{ct}->{quirks} = 1;
2253    
2254            $self->{state} = DATA_STATE;
2255            ## Reconsume.
2256            !!!emit ($self->{ct}); # DOCTYPE (quirks)
2257    
2258            redo A;
2259        } else {        } else {
2260          !!!cp (156);          !!!cp (156);
2261          ## XML5: Unless EOF, swith to the bogus comment state.          ## XML5: Swith to the bogus comment state.
2262          !!!parse-error (type => 'no space before DOCTYPE name');          !!!parse-error (type => 'no space before DOCTYPE name');
2263          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
2264          ## reconsume          ## reconsume
# Line 2130  sub _get_next_token ($) { Line 2283  sub _get_next_token ($) {
2283          !!!emit ($self->{ct}); # DOCTYPE (quirks)          !!!emit ($self->{ct}); # DOCTYPE (quirks)
2284    
2285          redo A;          redo A;
2286          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
2287            !!!cp (158.1);
2288            $self->{ct}->{name} # DOCTYPE
2289                = chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
2290            delete $self->{ct}->{quirks};
2291            $self->{state} = DOCTYPE_NAME_STATE;
2292            !!!next-input-character;
2293            redo A;
2294        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2295          !!!cp (159);          !!!cp (159);
2296          !!!parse-error (type => 'no DOCTYPE name');          !!!parse-error (type => 'no DOCTYPE name');
# Line 2176  sub _get_next_token ($) { Line 2337  sub _get_next_token ($) {
2337          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
2338    
2339          redo A;          redo A;
2340          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
2341            !!!cp (162.1);
2342            $self->{ct}->{name} # DOCTYPE
2343                .= chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
2344            delete $self->{ct}->{quirks};
2345            ## Stay in the state.
2346            !!!next-input-character;
2347            redo A;
2348        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2349          !!!cp (163);          !!!cp (163);
2350          !!!parse-error (type => 'unclosed DOCTYPE');          !!!parse-error (type => 'unclosed DOCTYPE');
# Line 2197  sub _get_next_token ($) { Line 2366  sub _get_next_token ($) {
2366          redo A;          redo A;
2367        } else {        } else {
2368          !!!cp (164);          !!!cp (164);
2369          $self->{ct}->{name}          $self->{ct}->{name} .= chr ($self->{nc}); # DOCTYPE
2370            .= chr ($self->{nc}); # DOCTYPE          ## Stay in the state.
         ## Stay in the state  
2371          !!!next-input-character;          !!!next-input-character;
2372          redo A;          redo A;
2373        }        }
# Line 2256  sub _get_next_token ($) { Line 2424  sub _get_next_token ($) {
2424          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
2425          !!!next-input-character;          !!!next-input-character;
2426          redo A;          redo A;
2427  ## TODO: " and ' for ENTITY        } elsif ($self->{nc} == 0x0022 and # "
2428                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
2429                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
2430            !!!cp (167.21);
2431            $self->{state} = DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE;
2432            $self->{ct}->{value} = ''; # ENTITY
2433            !!!next-input-character;
2434            redo A;
2435          } elsif ($self->{nc} == 0x0027 and # '
2436                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
2437                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
2438            !!!cp (167.22);
2439            $self->{state} = DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE;
2440            $self->{ct}->{value} = ''; # ENTITY
2441            !!!next-input-character;
2442            redo A;
2443        } elsif ($self->{is_xml} and        } elsif ($self->{is_xml} and
2444                 $self->{ct}->{type} == DOCTYPE_TOKEN and                 $self->{ct}->{type} == DOCTYPE_TOKEN and
2445                 $self->{nc} == 0x005B) { # [                 $self->{nc} == 0x005B) { # [
# Line 2812  sub _get_next_token ($) { Line 2995  sub _get_next_token ($) {
2995        }        }
2996      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
2997        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
2998          !!!cp (215);          if ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN) {
2999          ## Stay in the state            !!!cp (215.1);
3000              $self->{state} = BEFORE_NDATA_STATE;
3001            } else {
3002              !!!cp (215);
3003              ## Stay in the state
3004            }
3005          !!!next-input-character;          !!!next-input-character;
3006          redo A;          redo A;
3007        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
# Line 2829  sub _get_next_token ($) { Line 3017  sub _get_next_token ($) {
3017          !!!next-input-character;          !!!next-input-character;
3018          !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION          !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
3019          redo A;          redo A;
3020  ## TODO: "NDATA"        } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
3021                   ($self->{nc} == 0x004E or # N
3022                    $self->{nc} == 0x006E)) { # n
3023            !!!cp (216.2);
3024            !!!parse-error (type => 'no space before NDATA'); ## TODO: type
3025            $self->{state} = NDATA_STATE;
3026            $self->{kwd} = chr $self->{nc};
3027            !!!next-input-character;
3028            redo A;
3029        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3030          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3031            !!!cp (217);            !!!cp (217);
# Line 2871  sub _get_next_token ($) { Line 3067  sub _get_next_token ($) {
3067          !!!next-input-character;          !!!next-input-character;
3068          redo A;          redo A;
3069        }        }
3070        } elsif ($self->{state} == BEFORE_NDATA_STATE) {
3071          if ($is_space->{$self->{nc}}) {
3072            !!!cp (218.3);
3073            ## Stay in the state.
3074            !!!next-input-character;
3075            redo A;
3076          } elsif ($self->{nc} == 0x003E) { # >
3077            !!!cp (218.4);
3078            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3079            !!!next-input-character;
3080            !!!emit ($self->{ct}); # ENTITY
3081            redo A;
3082          } elsif ($self->{nc} == 0x004E or # N
3083                   $self->{nc} == 0x006E) { # n
3084            !!!cp (218.5);
3085            $self->{state} = NDATA_STATE;
3086            $self->{kwd} = chr $self->{nc};
3087            !!!next-input-character;
3088            redo A;
3089          } elsif ($self->{nc} == -1) {
3090            !!!cp (218.6);
3091            !!!parse-error (type => 'unclosed md'); ## TODO: type
3092            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3093            ## reconsume
3094            !!!emit ($self->{ct}); # ENTITY
3095            redo A;
3096          } else {
3097            !!!cp (218.7);
3098            !!!parse-error (type => 'string after SYSTEM literal');
3099            $self->{state} = BOGUS_MD_STATE;
3100            !!!next-input-character;
3101            redo A;
3102          }
3103      } elsif ($self->{state} == BOGUS_DOCTYPE_STATE) {      } elsif ($self->{state} == BOGUS_DOCTYPE_STATE) {
3104        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
3105          !!!cp (219);          !!!cp (219);
# Line 3001  sub _get_next_token ($) { Line 3230  sub _get_next_token ($) {
3230              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
3231              $self->{entity_add} => 1,              $self->{entity_add} => 1,
3232            }->{$self->{nc}}) {            }->{$self->{nc}}) {
3233          !!!cp (1001);          if ($self->{is_xml}) {
3234              !!!cp (1001.1);
3235              !!!parse-error (type => 'bare ero',
3236                              line => $self->{line_prev},
3237                              column => $self->{column_prev}
3238                                  + ($self->{nc} == -1 ? 1 : 0));
3239            } else {
3240              !!!cp (1001);
3241              ## No error
3242            }
3243          ## Don't consume          ## Don't consume
         ## No error  
3244          ## Return nothing.          ## Return nothing.
3245          #          #
3246        } elsif ($self->{nc} == 0x0023) { # #        } elsif ($self->{nc} == 0x0023) { # #
# Line 3012  sub _get_next_token ($) { Line 3249  sub _get_next_token ($) {
3249          $self->{kwd} = '#';          $self->{kwd} = '#';
3250          !!!next-input-character;          !!!next-input-character;
3251          redo A;          redo A;
3252        } elsif ((0x0041 <= $self->{nc} and        } elsif ($self->{is_xml} or
3253                   (0x0041 <= $self->{nc} and
3254                  $self->{nc} <= 0x005A) or # A..Z                  $self->{nc} <= 0x005A) or # A..Z
3255                 (0x0061 <= $self->{nc} and                 (0x0061 <= $self->{nc} and
3256                  $self->{nc} <= 0x007A)) { # a..z                  $self->{nc} <= 0x007A)) { # a..z
# Line 3056  sub _get_next_token ($) { Line 3294  sub _get_next_token ($) {
3294          redo A;          redo A;
3295        }        }
3296      } elsif ($self->{state} == ENTITY_HASH_STATE) {      } elsif ($self->{state} == ENTITY_HASH_STATE) {
3297        if ($self->{nc} == 0x0078 or # x        if ($self->{nc} == 0x0078) { # x
           $self->{nc} == 0x0058) { # X  
3298          !!!cp (995);          !!!cp (995);
3299          $self->{state} = HEXREF_X_STATE;          $self->{state} = HEXREF_X_STATE;
3300          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
3301          !!!next-input-character;          !!!next-input-character;
3302          redo A;          redo A;
3303          } elsif ($self->{nc} == 0x0058) { # X
3304            !!!cp (995.1);
3305            if ($self->{is_xml}) {
3306              !!!parse-error (type => 'uppercase hcro'); ## TODO: type
3307            }
3308            $self->{state} = HEXREF_X_STATE;
3309            $self->{kwd} .= chr $self->{nc};
3310            !!!next-input-character;
3311            redo A;
3312        } elsif (0x0030 <= $self->{nc} and        } elsif (0x0030 <= $self->{nc} and
3313                 $self->{nc} <= 0x0039) { # 0..9                 $self->{nc} <= 0x0039) { # 0..9
3314          !!!cp (994);          !!!cp (994);
# Line 3123  sub _get_next_token ($) { Line 3369  sub _get_next_token ($) {
3369        my $code = $self->{kwd};        my $code = $self->{kwd};
3370        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3371        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3372        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
3373              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
3374              ($self->{is_xml} and $code == 0x0000)) {
3375          !!!cp (1015);          !!!cp (1015);
3376          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3377                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 3236  sub _get_next_token ($) { Line 3484  sub _get_next_token ($) {
3484        my $code = $self->{kwd};        my $code = $self->{kwd};
3485        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3486        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3487        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
3488              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
3489              ($self->{is_xml} and $code == 0x0000)) {
3490          !!!cp (1008);          !!!cp (1008);
3491          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3492                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 3270  sub _get_next_token ($) { Line 3520  sub _get_next_token ($) {
3520          redo A;          redo A;
3521        }        }
3522      } elsif ($self->{state} == ENTITY_NAME_STATE) {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
3523        if (length $self->{kwd} < 30 and        if ((0x0041 <= $self->{nc} and # a
3524            ## NOTE: Some number greater than the maximum length of entity name             $self->{nc} <= 0x005A) or # x
3525            ((0x0041 <= $self->{nc} and # a            (0x0061 <= $self->{nc} and # a
3526              $self->{nc} <= 0x005A) or # x             $self->{nc} <= 0x007A) or # z
3527             (0x0061 <= $self->{nc} and # a            (0x0030 <= $self->{nc} and # 0
3528              $self->{nc} <= 0x007A) or # z             $self->{nc} <= 0x0039) or # 9
3529             (0x0030 <= $self->{nc} and # 0            $self->{nc} == 0x003B or # ;
3530              $self->{nc} <= 0x0039) or # 9            ($self->{is_xml} and
3531             $self->{nc} == 0x003B)) { # ;             not ($is_space->{$self->{nc}} or
3532                    {
3533                      0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
3534                      $self->{entity_add} => 1,
3535                    }->{$self->{nc}}))) {
3536          our $EntityChar;          our $EntityChar;
3537          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
3538          if (defined $EntityChar->{$self->{kwd}}) {          if (defined $EntityChar->{$self->{kwd}} or
3539                $self->{ge}->{$self->{kwd}}) {
3540            if ($self->{nc} == 0x003B) { # ;            if ($self->{nc} == 0x003B) { # ;
3541              !!!cp (1020);              if (defined $self->{ge}->{$self->{kwd}}) {
3542              $self->{entity__value} = $EntityChar->{$self->{kwd}};                if ($self->{ge}->{$self->{kwd}}->{only_text}) {
3543                    !!!cp (1020.1);
3544                    $self->{entity__value} = $self->{ge}->{$self->{kwd}}->{value};
3545                  } else {
3546                    if (defined $self->{ge}->{$self->{kwd}}->{notation}) {
3547                      !!!cp (1020.2);
3548                      !!!parse-error (type => 'unparsed entity', ## TODO: type
3549                                      value => $self->{kwd});
3550                    } else {
3551                      !!!cp (1020.3);
3552                    }
3553                    $self->{entity__value} = '&' . $self->{kwd}; ## TODO: expand
3554                  }
3555                } else {
3556                  if ($self->{is_xml}) {
3557                    !!!cp (1020.4);
3558                    !!!parse-error (type => 'entity not declared', ## TODO: type
3559                                    value => $self->{kwd},
3560                                    level => {
3561                                              'amp;' => $self->{level}->{warn},
3562                                              'quot;' => $self->{level}->{warn},
3563                                              'lt;' => $self->{level}->{warn},
3564                                              'gt;' => $self->{level}->{warn},
3565                                              'apos;' => $self->{level}->{warn},
3566                                             }->{$self->{kwd}} ||
3567                                             $self->{level}->{must});
3568                  } else {
3569                    !!!cp (1020);
3570                  }
3571                  $self->{entity__value} = $EntityChar->{$self->{kwd}};
3572                }
3573              $self->{entity__match} = 1;              $self->{entity__match} = 1;
3574              !!!next-input-character;              !!!next-input-character;
3575              #              #
# Line 3530  sub _get_next_token ($) { Line 3815  sub _get_next_token ($) {
3815          ## XML5: Not defined yet.          ## XML5: Not defined yet.
3816    
3817          ## TODO:          ## TODO:
3818    
3819            if (not $self->{stop_processing} and
3820                not $self->{document}->xml_standalone) {
3821              !!!parse-error (type => 'stop processing', ## TODO: type
3822                              level => $self->{level}->{info});
3823              $self->{stop_processing} = 1;
3824            }
3825    
3826          !!!next-input-character;          !!!next-input-character;
3827          redo A;          redo A;
3828        } elsif ($self->{nc} == 0x005D) { # ]        } elsif ($self->{nc} == 0x005D) { # ]
# Line 3764  sub _get_next_token ($) { Line 4057  sub _get_next_token ($) {
4057          }          }
4058          $self->{ct} = {type => ELEMENT_TOKEN, name => '',          $self->{ct} = {type => ELEMENT_TOKEN, name => '',
4059                         line => $self->{line_prev},                         line => $self->{line_prev},
4060                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
4061          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
4062          !!!next-input-character;          !!!next-input-character;
4063          redo A;          redo A;
# Line 3812  sub _get_next_token ($) { Line 4105  sub _get_next_token ($) {
4105          $self->{ct} = {type => ATTLIST_TOKEN, name => '',          $self->{ct} = {type => ATTLIST_TOKEN, name => '',
4106                         attrdefs => [],                         attrdefs => [],
4107                         line => $self->{line_prev},                         line => $self->{line_prev},
4108                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
4109          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
4110          !!!next-input-character;          !!!next-input-character;
4111          redo A;          redo A;
# Line 3861  sub _get_next_token ($) { Line 4154  sub _get_next_token ($) {
4154          }          }
4155          $self->{ct} = {type => NOTATION_TOKEN, name => '',          $self->{ct} = {type => NOTATION_TOKEN, name => '',
4156                         line => $self->{line_prev},                         line => $self->{line_prev},
4157                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 8};
4158          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
4159          !!!next-input-character;          !!!next-input-character;
4160          redo A;          redo A;
# Line 3973  sub _get_next_token ($) { Line 4266  sub _get_next_token ($) {
4266          if ($self->{ct}->{type} == ATTLIST_TOKEN) {          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
4267            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
4268          } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {          } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
4269            ## TODO: ...            $self->{state} = AFTER_ELEMENT_NAME_STATE;
           $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;  
4270          } else { # ENTITY/NOTATION          } else { # ENTITY/NOTATION
4271            $self->{state} = AFTER_DOCTYPE_NAME_STATE;            $self->{state} = AFTER_DOCTYPE_NAME_STATE;
4272          }          }
# Line 4502  sub _get_next_token ($) { Line 4794  sub _get_next_token ($) {
4794          ## Reconsume.          ## Reconsume.
4795          redo A;          redo A;
4796        }        }
4797        } elsif ($self->{state} == NDATA_STATE) {
4798          ## ASCII case-insensitive
4799          if ($self->{nc} == [
4800                undef,
4801                0x0044, # D
4802                0x0041, # A
4803                0x0054, # T
4804              ]->[length $self->{kwd}] or
4805              $self->{nc} == [
4806                undef,
4807                0x0064, # d
4808                0x0061, # a
4809                0x0074, # t
4810              ]->[length $self->{kwd}]) {
4811            !!!cp (172.2);
4812            ## Stay in the state.
4813            $self->{kwd} .= chr $self->{nc};
4814            !!!next-input-character;
4815            redo A;
4816          } elsif ((length $self->{kwd}) == 4 and
4817                   ($self->{nc} == 0x0041 or # A
4818                    $self->{nc} == 0x0061)) { # a
4819            if ($self->{kwd} ne 'NDAT' or $self->{nc} == 0x0061) { # a
4820              !!!cp (172.3);
4821              !!!parse-error (type => 'lowercase keyword', ## TODO: type
4822                              text => 'NDATA',
4823                              line => $self->{line_prev},
4824                              column => $self->{column_prev} - 4);
4825            } else {
4826              !!!cp (172.4);
4827            }
4828            $self->{state} = AFTER_NDATA_STATE;
4829            !!!next-input-character;
4830            redo A;
4831          } else {
4832            !!!parse-error (type => 'string after literal', ## TODO: type
4833                            line => $self->{line_prev},
4834                            column => $self->{column_prev} + 1
4835                                - length $self->{kwd});
4836            !!!cp (172.5);
4837            $self->{state} = BOGUS_MD_STATE;
4838            ## Reconsume.
4839            redo A;
4840          }
4841        } elsif ($self->{state} == AFTER_NDATA_STATE) {
4842          if ($is_space->{$self->{nc}}) {
4843            $self->{state} = BEFORE_NOTATION_NAME_STATE;
4844            !!!next-input-character;
4845            redo A;
4846          } elsif ($self->{nc} == 0x003E) { # >
4847            !!!parse-error (type => 'no notation name'); ## TODO: type
4848            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4849            !!!next-input-character;
4850            !!!emit ($self->{ct}); # ENTITY
4851            redo A;
4852          } elsif ($self->{nc} == -1) {
4853            !!!parse-error (type => 'unclosed md'); ## TODO: type
4854            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4855            !!!next-input-character;
4856            !!!emit ($self->{ct}); # ENTITY
4857            redo A;
4858          } else {
4859            !!!parse-error (type => 'string after literal', ## TODO: type
4860                            line => $self->{line_prev},
4861                            column => $self->{column_prev} + 1
4862                                - length $self->{kwd});
4863            $self->{state} = BOGUS_MD_STATE;
4864            ## Reconsume.
4865            redo A;
4866          }
4867        } elsif ($self->{state} == BEFORE_NOTATION_NAME_STATE) {
4868          if ($is_space->{$self->{nc}}) {
4869            ## Stay in the state.
4870            !!!next-input-character;
4871            redo A;
4872          } elsif ($self->{nc} == 0x003E) { # >
4873            !!!parse-error (type => 'no notation name'); ## TODO: type
4874            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4875            !!!next-input-character;
4876            !!!emit ($self->{ct}); # ENTITY
4877            redo A;
4878          } elsif ($self->{nc} == -1) {
4879            !!!parse-error (type => 'unclosed md'); ## TODO: type
4880            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4881            !!!next-input-character;
4882            !!!emit ($self->{ct}); # ENTITY
4883            redo A;
4884          } else {
4885            $self->{ct}->{notation} = chr $self->{nc}; # ENTITY
4886            $self->{state} = NOTATION_NAME_STATE;
4887            !!!next-input-character;
4888            redo A;
4889          }
4890        } elsif ($self->{state} == NOTATION_NAME_STATE) {
4891          if ($is_space->{$self->{nc}}) {
4892            $self->{state} = AFTER_MD_DEF_STATE;
4893            !!!next-input-character;
4894            redo A;
4895          } elsif ($self->{nc} == 0x003E) { # >
4896            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4897            !!!next-input-character;
4898            !!!emit ($self->{ct}); # ENTITY
4899            redo A;
4900          } elsif ($self->{nc} == -1) {
4901            !!!parse-error (type => 'unclosed md'); ## TODO: type
4902            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4903            !!!next-input-character;
4904            !!!emit ($self->{ct}); # ENTITY
4905            redo A;
4906          } else {
4907            $self->{ct}->{notation} .= chr $self->{nc}; # ENTITY
4908            ## Stay in the state.
4909            !!!next-input-character;
4910            redo A;
4911          }
4912        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE) {
4913          if ($self->{nc} == 0x0022) { # "
4914            $self->{state} = AFTER_MD_DEF_STATE;
4915            !!!next-input-character;
4916            redo A;
4917          } elsif ($self->{nc} == 0x0026) { # &
4918            $self->{prev_state} = $self->{state};
4919            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
4920            $self->{entity_add} = 0x0022; # "
4921            !!!next-input-character;
4922            redo A;
4923    ## TODO: %
4924          } elsif ($self->{nc} == -1) {
4925            !!!parse-error (type => 'unclosed entity value'); ## TODO: type
4926            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4927            ## Reconsume.
4928            !!!emit ($self->{ct}); # ENTITY
4929            redo A;
4930          } else {
4931            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
4932            !!!next-input-character;
4933            redo A;
4934          }
4935        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE) {
4936          if ($self->{nc} == 0x0027) { # '
4937            $self->{state} = AFTER_MD_DEF_STATE;
4938            !!!next-input-character;
4939            redo A;
4940          } elsif ($self->{nc} == 0x0026) { # &
4941            $self->{prev_state} = $self->{state};
4942            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
4943            $self->{entity_add} = 0x0027; # '
4944            !!!next-input-character;
4945            redo A;
4946    ## TODO: %
4947          } elsif ($self->{nc} == -1) {
4948            !!!parse-error (type => 'unclosed entity value'); ## TODO: type
4949            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4950            ## Reconsume.
4951            !!!emit ($self->{ct}); # ENTITY
4952            redo A;
4953          } else {
4954            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
4955            !!!next-input-character;
4956            redo A;
4957          }
4958        } elsif ($self->{state} == ENTITY_VALUE_ENTITY_STATE) {
4959          if ($is_space->{$self->{nc}} or
4960              {
4961                0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
4962                $self->{entity_add} => 1,
4963              }->{$self->{nc}}) {
4964            !!!parse-error (type => 'bare ero',
4965                            line => $self->{line_prev},
4966                            column => $self->{column_prev}
4967                                + ($self->{nc} == -1 ? 1 : 0));
4968            ## Don't consume
4969            ## Return nothing.
4970            #
4971          } elsif ($self->{nc} == 0x0023) { # #
4972            $self->{ca} = $self->{ct};
4973            $self->{state} = ENTITY_HASH_STATE;
4974            $self->{kwd} = '#';
4975            !!!next-input-character;
4976            redo A;
4977          } else {
4978            #
4979          }
4980    
4981          $self->{ct}->{value} .= '&';
4982          $self->{state} = $self->{prev_state};
4983          ## Reconsume.
4984          redo A;
4985        } elsif ($self->{state} == AFTER_ELEMENT_NAME_STATE) {
4986          if ($is_space->{$self->{nc}}) {
4987            $self->{state} = BEFORE_ELEMENT_CONTENT_STATE;
4988            !!!next-input-character;
4989            redo A;
4990          } elsif ($self->{nc} == 0x0028) { # (
4991            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
4992            $self->{ct}->{content} = ['('];
4993            $self->{group_depth} = 1;
4994            !!!next-input-character;
4995            redo A;
4996          } elsif ($self->{nc} == 0x003E) { # >
4997            !!!parse-error (type => 'no md def'); ## TODO: type
4998            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4999            !!!next-input-character;
5000            !!!emit ($self->{ct}); # ELEMENT
5001            redo A;
5002          } elsif ($self->{nc} == -1) {
5003            !!!parse-error (type => 'unclosed md'); ## TODO: type
5004            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5005            !!!next-input-character;
5006            !!!emit ($self->{ct}); # ELEMENT
5007            redo A;
5008          } else {
5009            $self->{ct}->{content} = [chr $self->{nc}];
5010            $self->{state} = CONTENT_KEYWORD_STATE;
5011            !!!next-input-character;
5012            redo A;
5013          }
5014        } elsif ($self->{state} == CONTENT_KEYWORD_STATE) {
5015          if ($is_space->{$self->{nc}}) {
5016            $self->{state} = AFTER_MD_DEF_STATE;
5017            !!!next-input-character;
5018            redo A;
5019          } elsif ($self->{nc} == 0x003E) { # >
5020            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5021            !!!next-input-character;
5022            !!!emit ($self->{ct}); # ELEMENT
5023            redo A;
5024          } elsif ($self->{nc} == -1) {
5025            !!!parse-error (type => 'unclosed md'); ## TODO: type
5026            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5027            !!!next-input-character;
5028            !!!emit ($self->{ct}); # ELEMENT
5029            redo A;
5030          } else {
5031            $self->{ct}->{content}->[-1] .= chr $self->{nc}; # ELEMENT
5032            ## Stay in the state.
5033            !!!next-input-character;
5034            redo A;
5035          }
5036        } elsif ($self->{state} == AFTER_CM_GROUP_OPEN_STATE) {
5037          if ($is_space->{$self->{nc}}) {
5038            ## Stay in the state.
5039            !!!next-input-character;
5040            redo A;
5041          } elsif ($self->{nc} == 0x0028) { # (
5042            $self->{group_depth}++;
5043            push @{$self->{ct}->{content}}, chr $self->{nc};
5044            ## Stay in the state.
5045            !!!next-input-character;
5046            redo A;
5047          } elsif ($self->{nc} == 0x007C or # |
5048                   $self->{nc} == 0x002C) { # ,
5049            !!!parse-error (type => 'empty element name'); ## TODO: type
5050            ## Stay in the state.
5051            !!!next-input-character;
5052            redo A;
5053          } elsif ($self->{nc} == 0x0029) { # )
5054            !!!parse-error (type => 'empty element name'); ## TODO: type
5055            push @{$self->{ct}->{content}}, chr $self->{nc};
5056            $self->{group_depth}--;
5057            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
5058            !!!next-input-character;
5059            redo A;
5060          } elsif ($self->{nc} == 0x003E) { # >
5061            !!!parse-error (type => 'unclosed cm group'); ## TODO: type
5062            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5063            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5064            !!!next-input-character;
5065            !!!emit ($self->{ct}); # ELEMENT
5066            redo A;
5067          } elsif ($self->{nc} == -1) {
5068            !!!parse-error (type => 'unclosed md'); ## TODO: type
5069            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5070            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5071            !!!next-input-character;
5072            !!!emit ($self->{ct}); # ELEMENT
5073            redo A;
5074          } else {
5075            push @{$self->{ct}->{content}}, chr $self->{nc};
5076            $self->{state} = CM_ELEMENT_NAME_STATE;
5077            !!!next-input-character;
5078            redo A;
5079          }
5080        } elsif ($self->{state} == CM_ELEMENT_NAME_STATE) {
5081          if ($is_space->{$self->{nc}}) {
5082            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5083            !!!next-input-character;
5084            redo A;
5085          } elsif ($self->{nc} == 0x002A or # *
5086                   $self->{nc} == 0x002B or # +
5087                   $self->{nc} == 0x003F) { # ?
5088            push @{$self->{ct}->{content}}, chr $self->{nc};
5089            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5090            !!!next-input-character;
5091            redo A;
5092          } elsif ($self->{nc} == 0x007C or # |
5093                   $self->{nc} == 0x002C) { # ,
5094            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
5095            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
5096            !!!next-input-character;
5097            redo A;
5098          } elsif ($self->{nc} == 0x0029) { # )
5099            $self->{group_depth}--;
5100            push @{$self->{ct}->{content}}, chr $self->{nc};
5101            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
5102            !!!next-input-character;
5103            redo A;
5104          } elsif ($self->{nc} == 0x003E) { # >
5105            !!!parse-error (type => 'unclosed cm group'); ## TODO: type
5106            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5107            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5108            !!!next-input-character;
5109            !!!emit ($self->{ct}); # ELEMENT
5110            redo A;
5111          } elsif ($self->{nc} == -1) {
5112            !!!parse-error (type => 'unclosed md'); ## TODO: type
5113            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5114            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5115            !!!next-input-character;
5116            !!!emit ($self->{ct}); # ELEMENT
5117            redo A;
5118          } else {
5119            $self->{ct}->{content}->[-1] .= chr $self->{nc};
5120            ## Stay in the state.
5121            !!!next-input-character;
5122            redo A;
5123          }
5124        } elsif ($self->{state} == AFTER_CM_ELEMENT_NAME_STATE) {
5125          if ($is_space->{$self->{nc}}) {
5126            ## Stay in the state.
5127            !!!next-input-character;
5128            redo A;
5129          } elsif ($self->{nc} == 0x007C or # |
5130                   $self->{nc} == 0x002C) { # ,
5131            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
5132            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
5133            !!!next-input-character;
5134            redo A;
5135          } elsif ($self->{nc} == 0x0029) { # )
5136            $self->{group_depth}--;
5137            push @{$self->{ct}->{content}}, chr $self->{nc};
5138            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
5139            !!!next-input-character;
5140            redo A;
5141          } elsif ($self->{nc} == 0x003E) { # >
5142            !!!parse-error (type => 'unclosed cm group'); ## TODO: type
5143            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5144            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5145            !!!next-input-character;
5146            !!!emit ($self->{ct}); # ELEMENT
5147            redo A;
5148          } elsif ($self->{nc} == -1) {
5149            !!!parse-error (type => 'unclosed md'); ## TODO: type
5150            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5151            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5152            !!!next-input-character;
5153            !!!emit ($self->{ct}); # ELEMENT
5154            redo A;
5155          } else {
5156            !!!parse-error (type => 'after element name'); ## TODO: type
5157            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5158            $self->{state} = BOGUS_MD_STATE;
5159            !!!next-input-character;
5160            redo A;
5161          }
5162        } elsif ($self->{state} == AFTER_CM_GROUP_CLOSE_STATE) {
5163          if ($is_space->{$self->{nc}}) {
5164            if ($self->{group_depth}) {
5165              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5166            } else {
5167              $self->{state} = AFTER_MD_DEF_STATE;
5168            }
5169            !!!next-input-character;
5170            redo A;
5171          } elsif ($self->{nc} == 0x002A or # *
5172                   $self->{nc} == 0x002B or # +
5173                   $self->{nc} == 0x003F) { # ?
5174            push @{$self->{ct}->{content}}, chr $self->{nc};
5175            if ($self->{group_depth}) {
5176              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5177            } else {
5178              $self->{state} = AFTER_MD_DEF_STATE;
5179            }
5180            !!!next-input-character;
5181            redo A;
5182          } elsif ($self->{nc} == 0x0029) { # )
5183            if ($self->{group_depth}) {
5184              $self->{group_depth}--;
5185              push @{$self->{ct}->{content}}, chr $self->{nc};
5186              ## Stay in the state.
5187              !!!next-input-character;
5188              redo A;
5189            } else {
5190              !!!parse-error (type => 'string after md def'); ## TODO: type
5191              $self->{state} = BOGUS_MD_STATE;
5192              ## Reconsume.
5193              redo A;
5194            }
5195          } elsif ($self->{nc} == 0x003E) { # >
5196            if ($self->{group_depth}) {
5197              !!!parse-error (type => 'unclosed cm group'); ## TODO: type
5198              push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5199            }
5200            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5201            !!!next-input-character;
5202            !!!emit ($self->{ct}); # ELEMENT
5203            redo A;
5204          } elsif ($self->{nc} == -1) {
5205            !!!parse-error (type => 'unclosed md'); ## TODO: type
5206            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5207            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5208            !!!next-input-character;
5209            !!!emit ($self->{ct}); # ELEMENT
5210            redo A;
5211          } else {
5212            if ($self->{group_depth}) {
5213              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5214            } else {
5215              !!!parse-error (type => 'string after md def'); ## TODO: type
5216              $self->{state} = BOGUS_MD_STATE;
5217            }
5218            ## Reconsume.
5219            redo A;
5220          }
5221        } elsif ($self->{state} == AFTER_MD_DEF_STATE) {
5222          if ($is_space->{$self->{nc}}) {
5223            ## Stay in the state.
5224            !!!next-input-character;
5225            redo A;
5226          } elsif ($self->{nc} == 0x003E) { # >
5227            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5228            !!!next-input-character;
5229            !!!emit ($self->{ct}); # ENTITY/ELEMENT
5230            redo A;
5231          } elsif ($self->{nc} == -1) {
5232            !!!parse-error (type => 'unclosed md'); ## TODO: type
5233            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5234            !!!next-input-character;
5235            !!!emit ($self->{ct}); # ENTITY/ELEMENT
5236            redo A;
5237          } else {
5238            !!!parse-error (type => 'string after md def'); ## TODO: type
5239            $self->{state} = BOGUS_MD_STATE;
5240            ## Reconsume.
5241            redo A;
5242          }
5243      } elsif ($self->{state} == BOGUS_MD_STATE) {      } elsif ($self->{state} == BOGUS_MD_STATE) {
5244        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
5245          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;

Legend:
Removed from v.1.17  
changed lines
  Added in v.1.33

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24