/[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.15 by wakaba, Sat Oct 18 08:05:29 2008 UTC revision 1.34 by wakaba, Sat Sep 5 11:31:58 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 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 187  sub FOREIGN_EL () { 0b1_00000000000 } Line 206  sub FOREIGN_EL () { 0b1_00000000000 }
206  ## Character reference mappings  ## Character reference mappings
207    
208  my $charref_map = {  my $charref_map = {
209      0x00 => 0xFFFD, # REPLACEMENT CHARACTER
210    0x0D => 0x000A,    0x0D => 0x000A,
211    0x80 => 0x20AC,    0x80 => 0x20AC,
212    0x81 => 0xFFFD,    0x81 => 0x0081,
213    0x82 => 0x201A,    0x82 => 0x201A,
214    0x83 => 0x0192,    0x83 => 0x0192,
215    0x84 => 0x201E,    0x84 => 0x201E,
# Line 201  my $charref_map = { Line 221  my $charref_map = {
221    0x8A => 0x0160,    0x8A => 0x0160,
222    0x8B => 0x2039,    0x8B => 0x2039,
223    0x8C => 0x0152,    0x8C => 0x0152,
224    0x8D => 0xFFFD,    0x8D => 0x008D,
225    0x8E => 0x017D,    0x8E => 0x017D,
226    0x8F => 0xFFFD,    0x8F => 0x008F,
227    0x90 => 0xFFFD,    0x90 => 0x0090,
228    0x91 => 0x2018,    0x91 => 0x2018,
229    0x92 => 0x2019,    0x92 => 0x2019,
230    0x93 => 0x201C,    0x93 => 0x201C,
# Line 217  my $charref_map = { Line 237  my $charref_map = {
237    0x9A => 0x0161,    0x9A => 0x0161,
238    0x9B => 0x203A,    0x9B => 0x203A,
239    0x9C => 0x0153,    0x9C => 0x0153,
240    0x9D => 0xFFFD,    0x9D => 0x009D,
241    0x9E => 0x017E,    0x9E => 0x017E,
242    0x9F => 0x0178,    0x9F => 0x0178,
243  }; # $charref_map  }; # $charref_map
244  $charref_map->{$_} = 0xFFFD  $charref_map->{$_} = $_
245      for 0x0000..0x0008, 0x000B, 0x000E..0x001F, 0x007F,      for 0x0001..0x0008, 0x000B, 0x000E..0x001F, 0x007F,
246          0xD800..0xDFFF, 0xFDD0..0xFDDF, ## ISSUE: 0xFDEF          0xD800..0xDFFF, 0xFDD0..0xFDEF,
247          0xFFFE, 0xFFFF, 0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF,          0xFFFE, 0xFFFF, 0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF,
248          0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE,          0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE,
249          0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF,          0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF,
# Line 843  sub _get_next_token ($) { Line 863  sub _get_next_token ($) {
863          $self->{s_kwd} = '';          $self->{s_kwd} = '';
864          # reconsume          # reconsume
865    
866          !!!emit ($self->{ct}); # start tag or end tag          ## Discard the token.
867            #!!!emit ($self->{ct}); # start tag or end tag
868    
869          redo A;          redo A;
870        } elsif ($self->{nc} == 0x002F) { # /        } elsif ($self->{nc} == 0x002F) { # /
# Line 924  sub _get_next_token ($) { Line 945  sub _get_next_token ($) {
945          $self->{s_kwd} = '';          $self->{s_kwd} = '';
946          # reconsume          # reconsume
947    
948          !!!emit ($self->{ct}); # start tag or end tag          ## Discard the token.
949            #!!!emit ($self->{ct}); # start tag or end tag
950    
951          redo A;          redo A;
952        } else {        } else {
953          if ({          if ({
954               0x0022 => 1, # "               0x0022 => 1, # "
955               0x0027 => 1, # '               0x0027 => 1, # '
956                 0x003C => 1, # <
957               0x003D => 1, # =               0x003D => 1, # =
958              }->{$self->{nc}}) {              }->{$self->{nc}}) {
959            !!!cp (55);            !!!cp (55);
# Line 1049  sub _get_next_token ($) { Line 1072  sub _get_next_token ($) {
1072          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1073          # reconsume          # reconsume
1074    
1075          !!!emit ($self->{ct}); # start tag or end tag          ## Discard the token.
1076            #!!!emit ($self->{ct}); # start tag or end tag
1077    
1078          redo A;          redo A;
1079        } else {        } else {
1080          if ($self->{nc} == 0x0022 or # "          if ({
1081              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1082                 0x0027 => 1, # '
1083                 0x003C => 1, # <
1084                }->{$self->{nc}}) {
1085            !!!cp (69);            !!!cp (69);
1086            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1087            !!!parse-error (type => 'bad attribute name');            !!!parse-error (type => 'bad attribute name');
# Line 1153  sub _get_next_token ($) { Line 1180  sub _get_next_token ($) {
1180          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1181          # reconsume          # reconsume
1182    
1183          !!!emit ($self->{ct}); # start tag or end tag          ## Discard the token.
1184            #!!!emit ($self->{ct}); # start tag or end tag
1185    
1186          redo A;          redo A;
1187        } else {        } else {
# Line 1165  sub _get_next_token ($) { Line 1193  sub _get_next_token ($) {
1193            !!!cp (78.2);            !!!cp (78.2);
1194          }          }
1195    
1196          if ($self->{nc} == 0x0022 or # "          if ({
1197              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1198                 0x0027 => 1, # '
1199                 0x003C => 1, # <
1200                }->{$self->{nc}}) {
1201            !!!cp (78);            !!!cp (78);
1202            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1203            !!!parse-error (type => 'bad attribute name');            !!!parse-error (type => 'bad attribute name');
# Line 1249  sub _get_next_token ($) { Line 1280  sub _get_next_token ($) {
1280          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1281          ## reconsume          ## reconsume
1282    
1283          !!!emit ($self->{ct}); # start tag or end tag          ## Discard the token.
1284            #!!!emit ($self->{ct}); # start tag or end tag
1285    
1286          redo A;          redo A;
1287        } else {        } else {
1288          if ($self->{nc} == 0x003D) { # =          if ($self->{nc} == 0x003D or $self->{nc} == 0x003C) { # =, <
1289            !!!cp (93);            !!!cp (93);
1290            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1291            !!!parse-error (type => 'bad attribute value');            !!!parse-error (type => 'bad attribute value');
# Line 1299  sub _get_next_token ($) { Line 1331  sub _get_next_token ($) {
1331          $self->{state} = ENTITY_STATE;          $self->{state} = ENTITY_STATE;
1332          !!!next-input-character;          !!!next-input-character;
1333          redo A;          redo A;
1334          } elsif ($self->{is_xml} and
1335                   $is_space->{$self->{nc}}) {
1336            !!!cp (97.1);
1337            $self->{ca}->{value} .= ' ';
1338            ## Stay in the state.
1339            !!!next-input-character;
1340            redo A;
1341        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1342          !!!parse-error (type => 'unclosed attribute value');          !!!parse-error (type => 'unclosed attribute value');
1343          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1323  sub _get_next_token ($) { Line 1362  sub _get_next_token ($) {
1362            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1363            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1364            ## reconsume            ## reconsume
1365            !!!emit ($self->{ct}); # end tag  
1366              ## Discard the token.
1367              #!!!emit ($self->{ct}); # end tag
1368    
1369            redo A;            redo A;
1370          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
1371            ## XML5: No parse error above; not defined yet.            ## XML5: No parse error above; not defined yet.
1372            push @{$self->{ct}->{attrdefs}}, $self->{ca};            push @{$self->{ct}->{attrdefs}}, $self->{ca};
1373            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1374            ## Reconsume.            ## Reconsume.
1375            !!!emit ($self->{ct}); # ATTLIST  
1376              ## Discard the token.
1377              #!!!emit ($self->{ct}); # ATTLIST
1378    
1379            redo A;            redo A;
1380          } else {          } else {
1381            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
# Line 1346  sub _get_next_token ($) { Line 1391  sub _get_next_token ($) {
1391          }          }
1392          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1393          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1394                                q["&<],                                qq["&<\x09\x0C\x20],
1395                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1396    
1397          ## Stay in the state          ## Stay in the state
# Line 1383  sub _get_next_token ($) { Line 1428  sub _get_next_token ($) {
1428          $self->{state} = ENTITY_STATE;          $self->{state} = ENTITY_STATE;
1429          !!!next-input-character;          !!!next-input-character;
1430          redo A;          redo A;
1431          } elsif ($self->{is_xml} and
1432                   $is_space->{$self->{nc}}) {
1433            !!!cp (103.1);
1434            $self->{ca}->{value} .= ' ';
1435            ## Stay in the state.
1436            !!!next-input-character;
1437            redo A;
1438        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1439          !!!parse-error (type => 'unclosed attribute value');          !!!parse-error (type => 'unclosed attribute value');
1440          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1392  sub _get_next_token ($) { Line 1444  sub _get_next_token ($) {
1444            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1445            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1446            ## reconsume            ## reconsume
1447            !!!emit ($self->{ct}); # start tag  
1448              ## Discard the token.
1449              #!!!emit ($self->{ct}); # start tag
1450    
1451            redo A;            redo A;
1452          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
1453            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1407  sub _get_next_token ($) { Line 1462  sub _get_next_token ($) {
1462            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1463            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1464            ## reconsume            ## reconsume
1465            !!!emit ($self->{ct}); # end tag  
1466              ## Discard the token.
1467              #!!!emit ($self->{ct}); # end tag
1468    
1469            redo A;            redo A;
1470          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
1471            ## XML5: No parse error above; not defined yet.            ## XML5: No parse error above; not defined yet.
1472            push @{$self->{ct}->{attrdefs}}, $self->{ca};            push @{$self->{ct}->{attrdefs}}, $self->{ca};
1473            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1474            ## Reconsume.            ## Reconsume.
1475            !!!emit ($self->{ct}); # ATTLIST  
1476              ## Discard the token.
1477              #!!!emit ($self->{ct}); # ATTLIST
1478    
1479            redo A;            redo A;
1480          } else {          } else {
1481            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
# Line 1430  sub _get_next_token ($) { Line 1491  sub _get_next_token ($) {
1491          }          }
1492          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1493          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1494                                q['&<],                                qq['&<\x09\x0C\x20],
1495                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1496    
1497          ## Stay in the state          ## Stay in the state
# Line 1509  sub _get_next_token ($) { Line 1570  sub _get_next_token ($) {
1570            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1571            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1572            ## reconsume            ## reconsume
1573            !!!emit ($self->{ct}); # start tag  
1574              ## Discard the token.
1575              #!!!emit ($self->{ct}); # start tag
1576              
1577            redo A;            redo A;
1578          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
1579            !!!parse-error (type => 'unclosed tag');            !!!parse-error (type => 'unclosed tag');
# Line 1525  sub _get_next_token ($) { Line 1589  sub _get_next_token ($) {
1589            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1590            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1591            ## reconsume            ## reconsume
1592            !!!emit ($self->{ct}); # end tag  
1593              ## Discard the token.
1594              #!!!emit ($self->{ct}); # end tag
1595    
1596            redo A;            redo A;
1597          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
1598            !!!parse-error (type => 'unclosed md'); ## TODO: type            !!!parse-error (type => 'unclosed md'); ## TODO: type
1599            push @{$self->{ct}->{attrdefs}}, $self->{ca};            push @{$self->{ct}->{attrdefs}}, $self->{ca};
1600            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1601            ## Reconsume.            ## Reconsume.
1602            !!!emit ($self->{ct}); # ATTLIST  
1603              ## Discard the token.
1604              #!!!emit ($self->{ct}); # ATTLIST
1605    
1606            redo A;            redo A;
1607          } else {          } else {
1608            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
# Line 1542  sub _get_next_token ($) { Line 1612  sub _get_next_token ($) {
1612               0x0022 => 1, # "               0x0022 => 1, # "
1613               0x0027 => 1, # '               0x0027 => 1, # '
1614               0x003D => 1, # =               0x003D => 1, # =
1615                 0x003C => 1, # <
1616              }->{$self->{nc}}) {              }->{$self->{nc}}) {
1617            !!!cp (115);            !!!cp (115);
1618            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 1551  sub _get_next_token ($) { Line 1622  sub _get_next_token ($) {
1622          }          }
1623          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1624          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1625                                q["'=& >],                                qq["'=& \x09\x0C>],
1626                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1627    
1628          ## Stay in the state          ## Stay in the state
# Line 1611  sub _get_next_token ($) { Line 1682  sub _get_next_token ($) {
1682          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1683          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1684          ## Reconsume.          ## Reconsume.
1685          !!!emit ($self->{ct}); # start tag or end tag  
1686            ## Discard the token.
1687            #!!!emit ($self->{ct}); # start tag or end tag
1688    
1689          redo A;          redo A;
1690        } else {        } else {
1691          !!!cp ('124.1');          !!!cp ('124.1');
# Line 1668  sub _get_next_token ($) { Line 1742  sub _get_next_token ($) {
1742          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1743          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1744          ## Reconsume.          ## Reconsume.
1745          !!!emit ($self->{ct}); # start tag or end tag  
1746            ## Discard the token.
1747            #!!!emit ($self->{ct}); # start tag or end tag
1748    
1749          redo A;          redo A;
1750        } else {        } else {
1751          !!!cp ('124.4');          !!!cp ('124.4');
# Line 2043  sub _get_next_token ($) { Line 2120  sub _get_next_token ($) {
2120          !!!next-input-character;          !!!next-input-character;
2121          redo A;          redo A;
2122        }        }
2123      } elsif ($self->{state} == COMMENT_END_STATE) {      } elsif ($self->{state} == COMMENT_END_STATE or
2124                 $self->{state} == COMMENT_END_BANG_STATE) {
2125        ## XML5: "Comment end state" and "DOCTYPE comment end state".        ## XML5: "Comment end state" and "DOCTYPE comment end state".
2126          ## (No comment end bang state.)
2127    
2128        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
2129          if ($self->{in_subset}) {          if ($self->{in_subset}) {
# Line 2061  sub _get_next_token ($) { Line 2140  sub _get_next_token ($) {
2140    
2141          redo A;          redo A;
2142        } elsif ($self->{nc} == 0x002D) { # -        } elsif ($self->{nc} == 0x002D) { # -
2143          !!!cp (152);          if ($self->{state} == COMMENT_END_BANG_STATE) {
2144          ## XML5: Not a parse error.            !!!cp (154.3);
2145          !!!parse-error (type => 'dash in comment',            $self->{ct}->{data} .= '--!'; # comment
2146                          line => $self->{line_prev},            $self->{state} = COMMENT_END_DASH_STATE;
2147                          column => $self->{column_prev});          } else {
2148          $self->{ct}->{data} .= '-'; # comment            !!!cp (152);
2149          ## Stay in the state            ## XML5: Not a parse error.
2150              !!!parse-error (type => 'dash in comment',
2151                              line => $self->{line_prev},
2152                              column => $self->{column_prev});
2153              $self->{ct}->{data} .= '-'; # comment
2154              ## Stay in the state
2155            }
2156            !!!next-input-character;
2157            redo A;
2158          } elsif ($self->{state} != COMMENT_END_BANG_STATE and
2159                   $is_space->{$self->{nc}}) {
2160            !!!cp (152.1);
2161            !!!parse-error (type => 'comment end space'); # XXX error type
2162            $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
2163            $self->{state} = COMMENT_END_SPACE_STATE;
2164            !!!next-input-character;
2165            redo A;
2166          } elsif ($self->{state} != COMMENT_END_BANG_STATE and
2167                   $self->{nc} == 0x0021) { # !
2168            !!!cp (152.2);
2169            !!!parse-error (type => 'comment end bang'); # XXX error type
2170            $self->{state} = COMMENT_END_BANG_STATE;
2171          !!!next-input-character;          !!!next-input-character;
2172          redo A;          redo A;
2173        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
# Line 2080  sub _get_next_token ($) { Line 2180  sub _get_next_token ($) {
2180            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
2181            $self->{s_kwd} = '';            $self->{s_kwd} = '';
2182          }          }
2183          ## reconsume          ## Reconsume.
2184    
2185          !!!emit ($self->{ct}); # comment          !!!emit ($self->{ct}); # comment
2186    
2187          redo A;          redo A;
2188        } else {        } else {
2189          !!!cp (154);          !!!cp (154);
2190          ## XML5: Not a parse error.          if ($self->{state} == COMMENT_END_BANG_STATE) {
2191          !!!parse-error (type => 'dash in comment',            $self->{ct}->{data} .= '--!' . chr ($self->{nc}); # comment
2192                          line => $self->{line_prev},          } else {
2193                          column => $self->{column_prev});            $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
2194          $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment          }
2195          $self->{state} = COMMENT_STATE;          $self->{state} = COMMENT_STATE;
2196          !!!next-input-character;          !!!next-input-character;
2197          redo A;          redo A;
2198        }        }
2199        } elsif ($self->{state} == COMMENT_END_SPACE_STATE) {
2200          ## XML5: Not exist.
2201    
2202          if ($self->{nc} == 0x003E) { # >
2203            if ($self->{in_subset}) {
2204              !!!cp (154.4);
2205              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2206            } else {
2207              !!!cp (154.5);
2208              $self->{state} = DATA_STATE;
2209              $self->{s_kwd} = '';
2210            }
2211            !!!next-input-character;
2212    
2213            !!!emit ($self->{ct}); # comment
2214    
2215            redo A;
2216          } elsif ($is_space->{$self->{nc}}) {
2217            !!!cp (154.6);
2218            $self->{ct}->{data} .= chr ($self->{nc}); # comment
2219            ## Stay in the state.
2220            !!!next-input-character;
2221            redo A;
2222          } elsif ($self->{nc} == -1) {
2223            !!!parse-error (type => 'unclosed comment');
2224            if ($self->{in_subset}) {
2225              !!!cp (154.7);
2226              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2227            } else {
2228              !!!cp (154.8);
2229              $self->{state} = DATA_STATE;
2230              $self->{s_kwd} = '';
2231            }
2232            ## Reconsume.
2233    
2234            !!!emit ($self->{ct}); # comment
2235    
2236            redo A;
2237          } else {
2238            !!!cp (154.9);
2239            $self->{ct}->{data} .= chr ($self->{nc}); # comment
2240            $self->{state} = COMMENT_STATE;
2241            !!!next-input-character;
2242            redo A;
2243          }
2244      } elsif ($self->{state} == DOCTYPE_STATE) {      } elsif ($self->{state} == DOCTYPE_STATE) {
2245        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
2246          !!!cp (155);          !!!cp (155);
2247          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
2248          !!!next-input-character;          !!!next-input-character;
2249          redo A;          redo A;
2250          } elsif ($self->{nc} == -1) {
2251            !!!cp (155.1);
2252            !!!parse-error (type => 'unclosed DOCTYPE');
2253            $self->{ct}->{quirks} = 1;
2254    
2255            $self->{state} = DATA_STATE;
2256            ## Reconsume.
2257            !!!emit ($self->{ct}); # DOCTYPE (quirks)
2258    
2259            redo A;
2260        } else {        } else {
2261          !!!cp (156);          !!!cp (156);
2262          ## XML5: Unless EOF, swith to the bogus comment state.          ## XML5: Swith to the bogus comment state.
2263          !!!parse-error (type => 'no space before DOCTYPE name');          !!!parse-error (type => 'no space before DOCTYPE name');
2264          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
2265          ## reconsume          ## reconsume
# Line 2129  sub _get_next_token ($) { Line 2284  sub _get_next_token ($) {
2284          !!!emit ($self->{ct}); # DOCTYPE (quirks)          !!!emit ($self->{ct}); # DOCTYPE (quirks)
2285    
2286          redo A;          redo A;
2287          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
2288            !!!cp (158.1);
2289            $self->{ct}->{name} # DOCTYPE
2290                = chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
2291            delete $self->{ct}->{quirks};
2292            $self->{state} = DOCTYPE_NAME_STATE;
2293            !!!next-input-character;
2294            redo A;
2295        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2296          !!!cp (159);          !!!cp (159);
2297          !!!parse-error (type => 'no DOCTYPE name');          !!!parse-error (type => 'no DOCTYPE name');
# Line 2175  sub _get_next_token ($) { Line 2338  sub _get_next_token ($) {
2338          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
2339    
2340          redo A;          redo A;
2341          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
2342            !!!cp (162.1);
2343            $self->{ct}->{name} # DOCTYPE
2344                .= chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
2345            delete $self->{ct}->{quirks};
2346            ## Stay in the state.
2347            !!!next-input-character;
2348            redo A;
2349        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2350          !!!cp (163);          !!!cp (163);
2351          !!!parse-error (type => 'unclosed DOCTYPE');          !!!parse-error (type => 'unclosed DOCTYPE');
# Line 2196  sub _get_next_token ($) { Line 2367  sub _get_next_token ($) {
2367          redo A;          redo A;
2368        } else {        } else {
2369          !!!cp (164);          !!!cp (164);
2370          $self->{ct}->{name}          $self->{ct}->{name} .= chr ($self->{nc}); # DOCTYPE
2371            .= chr ($self->{nc}); # DOCTYPE          ## Stay in the state.
         ## Stay in the state  
2372          !!!next-input-character;          !!!next-input-character;
2373          redo A;          redo A;
2374        }        }
# Line 2212  sub _get_next_token ($) { Line 2382  sub _get_next_token ($) {
2382          !!!next-input-character;          !!!next-input-character;
2383          redo A;          redo A;
2384        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
2385          !!!cp (166);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2386          $self->{state} = DATA_STATE;            !!!cp (166);
2387          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
2388              $self->{s_kwd} = '';
2389            } else {
2390              !!!cp (166.1);
2391              !!!parse-error (type => 'no md def'); ## TODO: type
2392              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2393            }
2394            
2395          !!!next-input-character;          !!!next-input-character;
2396            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         !!!emit ($self->{ct}); # DOCTYPE  
   
2397          redo A;          redo A;
2398        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2399          !!!cp (167);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2400          !!!parse-error (type => 'unclosed DOCTYPE');            !!!cp (167);
2401          $self->{state} = DATA_STATE;            !!!parse-error (type => 'unclosed DOCTYPE');
2402          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
2403          ## reconsume            $self->{s_kwd} = '';
2404              $self->{ct}->{quirks} = 1;
2405          $self->{ct}->{quirks} = 1;          } else {
2406          !!!emit ($self->{ct}); # DOCTYPE            !!!cp (167.12);
2407              !!!parse-error (type => 'unclosed md'); ## TODO: type
2408              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2409            }
2410            
2411            ## Reconsume.
2412            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
2413          redo A;          redo A;
2414        } elsif ($self->{nc} == 0x0050 or # P        } elsif ($self->{nc} == 0x0050 or # P
2415                 $self->{nc} == 0x0070) { # p                 $self->{nc} == 0x0070) { # p
# Line 2245  sub _get_next_token ($) { Line 2425  sub _get_next_token ($) {
2425          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
2426          !!!next-input-character;          !!!next-input-character;
2427          redo A;          redo A;
2428        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{nc} == 0x0022 and # "
2429                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
2430                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
2431            !!!cp (167.21);
2432            $self->{state} = DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE;
2433            $self->{ct}->{value} = ''; # ENTITY
2434            !!!next-input-character;
2435            redo A;
2436          } elsif ($self->{nc} == 0x0027 and # '
2437                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
2438                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
2439            !!!cp (167.22);
2440            $self->{state} = DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE;
2441            $self->{ct}->{value} = ''; # ENTITY
2442            !!!next-input-character;
2443            redo A;
2444          } elsif ($self->{is_xml} and
2445                   $self->{ct}->{type} == DOCTYPE_TOKEN and
2446                   $self->{nc} == 0x005B) { # [
2447          !!!cp (167.3);          !!!cp (167.3);
2448          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2449          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 2254  sub _get_next_token ($) { Line 2452  sub _get_next_token ($) {
2452          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
2453          redo A;          redo A;
2454        } else {        } else {
2455          !!!cp (180);          !!!parse-error (type => 'string after DOCTYPE name'); ## TODO: type
2456          !!!parse-error (type => 'string after DOCTYPE name');  
2457          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2458              !!!cp (180);
2459              $self->{ct}->{quirks} = 1;
2460              $self->{state} = BOGUS_DOCTYPE_STATE;
2461            } else {
2462              !!!cp (180.1);
2463              $self->{state} = BOGUS_MD_STATE;
2464            }
2465    
         $self->{state} = BOGUS_DOCTYPE_STATE;  
2466          !!!next-input-character;          !!!next-input-character;
2467          redo A;          redo A;
2468        }        }
# Line 2300  sub _get_next_token ($) { Line 2504  sub _get_next_token ($) {
2504          !!!next-input-character;          !!!next-input-character;
2505          redo A;          redo A;
2506        } else {        } else {
2507          !!!cp (169);          !!!parse-error (type => 'string after DOCTYPE name', ## TODO: type
         !!!parse-error (type => 'string after DOCTYPE name',  
2508                          line => $self->{line_prev},                          line => $self->{line_prev},
2509                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
2510          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2511              !!!cp (169);
2512          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
2513              $self->{state} = BOGUS_DOCTYPE_STATE;
2514            } else {
2515              !!!cp (169.1);
2516              $self->{state} = BOGUS_MD_STATE;
2517            }
2518          ## Reconsume.          ## Reconsume.
2519          redo A;          redo A;
2520        }        }
# Line 2348  sub _get_next_token ($) { Line 2556  sub _get_next_token ($) {
2556          !!!next-input-character;          !!!next-input-character;
2557          redo A;          redo A;
2558        } else {        } else {
2559          !!!cp (172);          !!!parse-error (type => 'string after DOCTYPE name', ## TODO: type
         !!!parse-error (type => 'string after DOCTYPE name',  
2560                          line => $self->{line_prev},                          line => $self->{line_prev},
2561                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
2562          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2563              !!!cp (172);
2564          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
2565              $self->{state} = BOGUS_DOCTYPE_STATE;
2566            } else {
2567              !!!cp (172.1);
2568              $self->{state} = BOGUS_MD_STATE;
2569            }
2570          ## Reconsume.          ## Reconsume.
2571          redo A;          redo A;
2572        }        }
# Line 2377  sub _get_next_token ($) { Line 2589  sub _get_next_token ($) {
2589          !!!next-input-character;          !!!next-input-character;
2590          redo A;          redo A;
2591        } elsif ($self->{nc} eq 0x003E) { # >        } elsif ($self->{nc} eq 0x003E) { # >
         !!!cp (184);  
2592          !!!parse-error (type => 'no PUBLIC literal');          !!!parse-error (type => 'no PUBLIC literal');
2593            
2594          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2595          $self->{s_kwd} = '';            !!!cp (184);
2596              $self->{state} = DATA_STATE;
2597              $self->{s_kwd} = '';
2598              $self->{ct}->{quirks} = 1;
2599            } else {
2600              !!!cp (184.1);
2601              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2602            }
2603            
2604          !!!next-input-character;          !!!next-input-character;
2605            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         !!!emit ($self->{ct}); # DOCTYPE  
   
2606          redo A;          redo A;
2607        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2608          !!!cp (185);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2609          !!!parse-error (type => 'unclosed DOCTYPE');            !!!cp (185);
2610              !!!parse-error (type => 'unclosed DOCTYPE');
2611          $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
2612          $self->{s_kwd} = '';            $self->{s_kwd} = '';
2613              $self->{ct}->{quirks} = 1;
2614            } else {
2615              !!!cp (185.1);
2616              !!!parse-error (type => 'unclosed md'); ## TODO: type
2617              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2618            }
2619            
2620          ## reconsume          ## reconsume
   
         $self->{ct}->{quirks} = 1;  
2621          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
   
2622          redo A;          redo A;
2623        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
2624                   $self->{ct}->{type} == DOCTYPE_TOKEN and
2625                   $self->{nc} == 0x005B) { # [
2626          !!!cp (186.1);          !!!cp (186.1);
2627          !!!parse-error (type => 'no PUBLIC literal');          !!!parse-error (type => 'no PUBLIC literal');
2628          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 2410  sub _get_next_token ($) { Line 2632  sub _get_next_token ($) {
2632          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
2633          redo A;          redo A;
2634        } else {        } else {
         !!!cp (186);  
2635          !!!parse-error (type => 'string after PUBLIC');          !!!parse-error (type => 'string after PUBLIC');
         $self->{ct}->{quirks} = 1;  
2636    
2637          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2638              !!!cp (186);
2639              $self->{ct}->{quirks} = 1;
2640              $self->{state} = BOGUS_DOCTYPE_STATE;
2641            } else {
2642              !!!cp (186.2);
2643              $self->{state} = BOGUS_MD_STATE;
2644            }
2645    
2646          !!!next-input-character;          !!!next-input-character;
2647          redo A;          redo A;
2648        }        }
# Line 2425  sub _get_next_token ($) { Line 2653  sub _get_next_token ($) {
2653          !!!next-input-character;          !!!next-input-character;
2654          redo A;          redo A;
2655        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
         !!!cp (188);  
2656          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed PUBLIC literal');
2657    
2658          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2659          $self->{s_kwd} = '';            !!!cp (188);
2660          !!!next-input-character;            $self->{state} = DATA_STATE;
2661              $self->{s_kwd} = '';
2662          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
2663          !!!emit ($self->{ct}); # DOCTYPE          } else {
2664              !!!cp (188.1);
2665              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2666            }
2667    
2668            !!!next-input-character;
2669            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
2670          redo A;          redo A;
2671        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!cp (189);  
2672          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed PUBLIC literal');
2673    
2674          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2675          $self->{s_kwd} = '';            !!!cp (189);
2676          ## reconsume            $self->{state} = DATA_STATE;
2677              $self->{s_kwd} = '';
2678          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
2679            } else {
2680              !!!cp (189.1);
2681              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2682            }
2683            
2684            ## Reconsume.
2685          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
   
2686          redo A;          redo A;
2687        } else {        } else {
2688          !!!cp (190);          !!!cp (190);
2689          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
2690          $self->{read_until}->($self->{ct}->{pubid}, q[">],          $self->{read_until}->($self->{ct}->{pubid}, q[">],
2691                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
2692    
# Line 2466  sub _get_next_token ($) { Line 2701  sub _get_next_token ($) {
2701          !!!next-input-character;          !!!next-input-character;
2702          redo A;          redo A;
2703        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
         !!!cp (192);  
2704          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed PUBLIC literal');
2705    
2706          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2707          $self->{s_kwd} = '';            !!!cp (192);
2708          !!!next-input-character;            $self->{state} = DATA_STATE;
2709              $self->{s_kwd} = '';
2710          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
2711          !!!emit ($self->{ct}); # DOCTYPE          } else {
2712              !!!cp (192.1);
2713              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2714            }
2715    
2716            !!!next-input-character;
2717            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
2718          redo A;          redo A;
2719        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!cp (193);  
2720          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed PUBLIC literal');
2721    
2722          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2723          $self->{s_kwd} = '';            !!!cp (193);
2724              $self->{state} = DATA_STATE;
2725              $self->{s_kwd} = '';
2726              $self->{ct}->{quirks} = 1;
2727            } else {
2728              !!!cp (193.1);
2729              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2730            }
2731          
2732          ## reconsume          ## reconsume
2733            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         !!!emit ($self->{ct}); # DOCTYPE  
   
2734          redo A;          redo A;
2735        } else {        } else {
2736          !!!cp (194);          !!!cp (194);
2737          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
2738          $self->{read_until}->($self->{ct}->{pubid}, q['>],          $self->{read_until}->($self->{ct}->{pubid}, q['>],
2739                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
2740    
# Line 2508  sub _get_next_token ($) { Line 2750  sub _get_next_token ($) {
2750          redo A;          redo A;
2751        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
2752          !!!cp (196);          !!!cp (196);
2753          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
2754          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;
2755          !!!next-input-character;          !!!next-input-character;
2756          redo A;          redo A;
2757        } elsif ($self->{nc} == 0x0027) { # '        } elsif ($self->{nc} == 0x0027) { # '
2758          !!!cp (197);          !!!cp (197);
2759          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
2760          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;
2761          !!!next-input-character;          !!!next-input-character;
2762          redo A;          redo A;
2763        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
2764          if ($self->{is_xml}) {          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2765            !!!cp (198.1);            if ($self->{is_xml}) {
2766            !!!parse-error (type => 'no SYSTEM literal');              !!!cp (198.1);
2767                !!!parse-error (type => 'no SYSTEM literal');
2768              } else {
2769                !!!cp (198);
2770              }
2771              $self->{state} = DATA_STATE;
2772              $self->{s_kwd} = '';
2773          } else {          } else {
2774            !!!cp (198);            if ($self->{ct}->{type} == NOTATION_TOKEN) {
2775                !!!cp (198.2);
2776              } else {
2777                !!!cp (198.3);
2778                !!!parse-error (type => 'no SYSTEM literal');            
2779              }
2780              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2781          }          }
2782          $self->{state} = DATA_STATE;          
         $self->{s_kwd} = '';  
2783          !!!next-input-character;          !!!next-input-character;
2784            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         !!!emit ($self->{ct}); # DOCTYPE  
   
2785          redo A;          redo A;
2786        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2787          !!!cp (199);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2788          !!!parse-error (type => 'unclosed DOCTYPE');            !!!cp (199);
2789              !!!parse-error (type => 'unclosed DOCTYPE');
2790          $self->{state} = DATA_STATE;            
2791          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
2792              $self->{s_kwd} = '';
2793              $self->{ct}->{quirks} = 1;
2794            } else {
2795              !!!parse-error (type => 'unclosed md'); ## TODO: type
2796              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2797            }
2798            
2799          ## reconsume          ## reconsume
2800            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         !!!emit ($self->{ct}); # DOCTYPE  
   
2801          redo A;          redo A;
2802        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
2803                   $self->{ct}->{type} == DOCTYPE_TOKEN and
2804                   $self->{nc} == 0x005B) { # [
2805          !!!cp (200.1);          !!!cp (200.1);
2806          !!!parse-error (type => 'no SYSTEM literal');          !!!parse-error (type => 'no SYSTEM literal');
2807          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 2554  sub _get_next_token ($) { Line 2811  sub _get_next_token ($) {
2811          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
2812          redo A;          redo A;
2813        } else {        } else {
         !!!cp (200);  
2814          !!!parse-error (type => 'string after PUBLIC literal');          !!!parse-error (type => 'string after PUBLIC literal');
         $self->{ct}->{quirks} = 1;  
2815    
2816          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2817              !!!cp (200);
2818              $self->{ct}->{quirks} = 1;
2819              $self->{state} = BOGUS_DOCTYPE_STATE;
2820            } else {
2821              !!!cp (200.2);
2822              $self->{state} = BOGUS_MD_STATE;
2823            }
2824    
2825          !!!next-input-character;          !!!next-input-character;
2826          redo A;          redo A;
2827        }        }
# Line 2581  sub _get_next_token ($) { Line 2844  sub _get_next_token ($) {
2844          !!!next-input-character;          !!!next-input-character;
2845          redo A;          redo A;
2846        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
         !!!cp (204);  
2847          !!!parse-error (type => 'no SYSTEM literal');          !!!parse-error (type => 'no SYSTEM literal');
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
2848          !!!next-input-character;          !!!next-input-character;
2849    
2850          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2851          !!!emit ($self->{ct}); # DOCTYPE            !!!cp (204);
2852              $self->{state} = DATA_STATE;
2853              $self->{s_kwd} = '';
2854              $self->{ct}->{quirks} = 1;
2855            } else {
2856              !!!cp (204.1);
2857              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2858            }
2859    
2860            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
2861          redo A;          redo A;
2862        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2863          !!!cp (205);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2864          !!!parse-error (type => 'unclosed DOCTYPE');            !!!cp (205);
2865              !!!parse-error (type => 'unclosed DOCTYPE');
2866          $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
2867          $self->{s_kwd} = '';            $self->{s_kwd} = '';
2868              $self->{ct}->{quirks} = 1;
2869            } else {
2870              !!!cp (205.1);
2871              !!!parse-error (type => 'unclosed md'); ## TODO: type
2872              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2873            }
2874            
2875          ## reconsume          ## reconsume
2876            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         !!!emit ($self->{ct}); # DOCTYPE  
   
2877          redo A;          redo A;
2878        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
2879                   $self->{ct}->{type} == DOCTYPE_TOKEN and
2880                   $self->{nc} == 0x005B) { # [
2881          !!!cp (206.1);          !!!cp (206.1);
2882          !!!parse-error (type => 'no SYSTEM literal');          !!!parse-error (type => 'no SYSTEM literal');
2883    
# Line 2614  sub _get_next_token ($) { Line 2888  sub _get_next_token ($) {
2888          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
2889          redo A;          redo A;
2890        } else {        } else {
         !!!cp (206);  
2891          !!!parse-error (type => 'string after SYSTEM');          !!!parse-error (type => 'string after SYSTEM');
         $self->{ct}->{quirks} = 1;  
2892    
2893          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2894              !!!cp (206);          
2895              $self->{ct}->{quirks} = 1;
2896              $self->{state} = BOGUS_DOCTYPE_STATE;
2897            } else {
2898              !!!cp (206.2);
2899              $self->{state} = BOGUS_MD_STATE;
2900            }
2901    
2902          !!!next-input-character;          !!!next-input-character;
2903          redo A;          redo A;
2904        }        }
# Line 2629  sub _get_next_token ($) { Line 2909  sub _get_next_token ($) {
2909          !!!next-input-character;          !!!next-input-character;
2910          redo A;          redo A;
2911        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >
         !!!cp (208);  
2912          !!!parse-error (type => 'unclosed SYSTEM literal');          !!!parse-error (type => 'unclosed SYSTEM literal');
2913    
2914          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2915          $self->{s_kwd} = '';            !!!cp (208);
2916              $self->{state} = DATA_STATE;
2917              $self->{s_kwd} = '';
2918              $self->{ct}->{quirks} = 1;
2919            } else {
2920              !!!cp (208.1);
2921              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2922            }
2923            
2924          !!!next-input-character;          !!!next-input-character;
2925            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         !!!emit ($self->{ct}); # DOCTYPE  
   
2926          redo A;          redo A;
2927        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!cp (209);  
2928          !!!parse-error (type => 'unclosed SYSTEM literal');          !!!parse-error (type => 'unclosed SYSTEM literal');
2929    
2930          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2931          $self->{s_kwd} = '';            !!!cp (209);
2932              $self->{state} = DATA_STATE;
2933              $self->{s_kwd} = '';
2934              $self->{ct}->{quirks} = 1;
2935            } else {
2936              !!!cp (209.1);
2937              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2938            }
2939            
2940          ## reconsume          ## reconsume
2941            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         !!!emit ($self->{ct}); # DOCTYPE  
   
2942          redo A;          redo A;
2943        } else {        } else {
2944          !!!cp (210);          !!!cp (210);
2945          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
2946          $self->{read_until}->($self->{ct}->{sysid}, q[">],          $self->{read_until}->($self->{ct}->{sysid}, q[">],
2947                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
2948    
# Line 2682  sub _get_next_token ($) { Line 2969  sub _get_next_token ($) {
2969    
2970          redo A;          redo A;
2971        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
         !!!cp (213);  
2972          !!!parse-error (type => 'unclosed SYSTEM literal');          !!!parse-error (type => 'unclosed SYSTEM literal');
2973    
2974          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2975          $self->{s_kwd} = '';            !!!cp (213);
2976          ## reconsume            $self->{state} = DATA_STATE;
2977              $self->{s_kwd} = '';
2978          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
2979          !!!emit ($self->{ct}); # DOCTYPE          } else {
2980              !!!cp (213.1);
2981              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2982            }
2983    
2984            ## reconsume
2985            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
2986          redo A;          redo A;
2987        } else {        } else {
2988          !!!cp (214);          !!!cp (214);
2989          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
2990          $self->{read_until}->($self->{ct}->{sysid}, q['>],          $self->{read_until}->($self->{ct}->{sysid}, q['>],
2991                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
2992    
# Line 2706  sub _get_next_token ($) { Line 2996  sub _get_next_token ($) {
2996        }        }
2997      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
2998        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
2999          !!!cp (215);          if ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN) {
3000          ## Stay in the state            !!!cp (215.1);
3001              $self->{state} = BEFORE_NDATA_STATE;
3002            } else {
3003              !!!cp (215);
3004              ## Stay in the state
3005            }
3006          !!!next-input-character;          !!!next-input-character;
3007          redo A;          redo A;
3008        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
3009          !!!cp (216);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3010          $self->{state} = DATA_STATE;            !!!cp (216);
3011          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
3012          !!!next-input-character;            $self->{s_kwd} = '';
3013            } else {
3014          !!!emit ($self->{ct}); # DOCTYPE            !!!cp (216.1);
3015              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3016            }
3017    
3018            !!!next-input-character;
3019            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
3020            redo A;
3021          } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
3022                   ($self->{nc} == 0x004E or # N
3023                    $self->{nc} == 0x006E)) { # n
3024            !!!cp (216.2);
3025            !!!parse-error (type => 'no space before NDATA'); ## TODO: type
3026            $self->{state} = NDATA_STATE;
3027            $self->{kwd} = chr $self->{nc};
3028            !!!next-input-character;
3029          redo A;          redo A;
3030        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3031          !!!cp (217);          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3032          !!!parse-error (type => 'unclosed DOCTYPE');            !!!cp (217);
3033          $self->{state} = DATA_STATE;            !!!parse-error (type => 'unclosed DOCTYPE');
3034          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
3035          ## reconsume            $self->{s_kwd} = '';
3036              $self->{ct}->{quirks} = 1;
3037          $self->{ct}->{quirks} = 1;          } else {
3038          !!!emit ($self->{ct}); # DOCTYPE            !!!cp (217.1);
3039              !!!parse-error (type => 'unclosed md'); ## TODO: type
3040              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3041            }
3042    
3043            ## reconsume
3044            !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
3045          redo A;          redo A;
3046        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
3047                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3048                   $self->{nc} == 0x005B) { # [
3049          !!!cp (218.1);          !!!cp (218.1);
3050          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3051          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 2739  sub _get_next_token ($) { Line 3054  sub _get_next_token ($) {
3054          !!!emit ($self->{ct}); # DOCTYPE          !!!emit ($self->{ct}); # DOCTYPE
3055          redo A;          redo A;
3056        } else {        } else {
         !!!cp (218);  
3057          !!!parse-error (type => 'string after SYSTEM literal');          !!!parse-error (type => 'string after SYSTEM literal');
         #$self->{ct}->{quirks} = 1;  
3058    
3059          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3060              !!!cp (218);
3061              #$self->{ct}->{quirks} = 1;
3062              $self->{state} = BOGUS_DOCTYPE_STATE;
3063            } else {
3064              !!!cp (218.2);
3065              $self->{state} = BOGUS_MD_STATE;
3066            }
3067    
3068            !!!next-input-character;
3069            redo A;
3070          }
3071        } elsif ($self->{state} == BEFORE_NDATA_STATE) {
3072          if ($is_space->{$self->{nc}}) {
3073            !!!cp (218.3);
3074            ## Stay in the state.
3075            !!!next-input-character;
3076            redo A;
3077          } elsif ($self->{nc} == 0x003E) { # >
3078            !!!cp (218.4);
3079            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3080            !!!next-input-character;
3081            !!!emit ($self->{ct}); # ENTITY
3082            redo A;
3083          } elsif ($self->{nc} == 0x004E or # N
3084                   $self->{nc} == 0x006E) { # n
3085            !!!cp (218.5);
3086            $self->{state} = NDATA_STATE;
3087            $self->{kwd} = chr $self->{nc};
3088            !!!next-input-character;
3089            redo A;
3090          } elsif ($self->{nc} == -1) {
3091            !!!cp (218.6);
3092            !!!parse-error (type => 'unclosed md'); ## TODO: type
3093            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3094            ## reconsume
3095            !!!emit ($self->{ct}); # ENTITY
3096            redo A;
3097          } else {
3098            !!!cp (218.7);
3099            !!!parse-error (type => 'string after SYSTEM literal');
3100            $self->{state} = BOGUS_MD_STATE;
3101          !!!next-input-character;          !!!next-input-character;
3102          redo A;          redo A;
3103        }        }
# Line 2877  sub _get_next_token ($) { Line 3231  sub _get_next_token ($) {
3231              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
3232              $self->{entity_add} => 1,              $self->{entity_add} => 1,
3233            }->{$self->{nc}}) {            }->{$self->{nc}}) {
3234          !!!cp (1001);          if ($self->{is_xml}) {
3235              !!!cp (1001.1);
3236              !!!parse-error (type => 'bare ero',
3237                              line => $self->{line_prev},
3238                              column => $self->{column_prev}
3239                                  + ($self->{nc} == -1 ? 1 : 0));
3240            } else {
3241              !!!cp (1001);
3242              ## No error
3243            }
3244          ## Don't consume          ## Don't consume
         ## No error  
3245          ## Return nothing.          ## Return nothing.
3246          #          #
3247        } elsif ($self->{nc} == 0x0023) { # #        } elsif ($self->{nc} == 0x0023) { # #
# Line 2888  sub _get_next_token ($) { Line 3250  sub _get_next_token ($) {
3250          $self->{kwd} = '#';          $self->{kwd} = '#';
3251          !!!next-input-character;          !!!next-input-character;
3252          redo A;          redo A;
3253        } elsif ((0x0041 <= $self->{nc} and        } elsif ($self->{is_xml} or
3254                   (0x0041 <= $self->{nc} and
3255                  $self->{nc} <= 0x005A) or # A..Z                  $self->{nc} <= 0x005A) or # A..Z
3256                 (0x0061 <= $self->{nc} and                 (0x0061 <= $self->{nc} and
3257                  $self->{nc} <= 0x007A)) { # a..z                  $self->{nc} <= 0x007A)) { # a..z
# Line 2932  sub _get_next_token ($) { Line 3295  sub _get_next_token ($) {
3295          redo A;          redo A;
3296        }        }
3297      } elsif ($self->{state} == ENTITY_HASH_STATE) {      } elsif ($self->{state} == ENTITY_HASH_STATE) {
3298        if ($self->{nc} == 0x0078 or # x        if ($self->{nc} == 0x0078) { # x
           $self->{nc} == 0x0058) { # X  
3299          !!!cp (995);          !!!cp (995);
3300          $self->{state} = HEXREF_X_STATE;          $self->{state} = HEXREF_X_STATE;
3301          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
3302          !!!next-input-character;          !!!next-input-character;
3303          redo A;          redo A;
3304          } elsif ($self->{nc} == 0x0058) { # X
3305            !!!cp (995.1);
3306            if ($self->{is_xml}) {
3307              !!!parse-error (type => 'uppercase hcro'); ## TODO: type
3308            }
3309            $self->{state} = HEXREF_X_STATE;
3310            $self->{kwd} .= chr $self->{nc};
3311            !!!next-input-character;
3312            redo A;
3313        } elsif (0x0030 <= $self->{nc} and        } elsif (0x0030 <= $self->{nc} and
3314                 $self->{nc} <= 0x0039) { # 0..9                 $self->{nc} <= 0x0039) { # 0..9
3315          !!!cp (994);          !!!cp (994);
# Line 2999  sub _get_next_token ($) { Line 3370  sub _get_next_token ($) {
3370        my $code = $self->{kwd};        my $code = $self->{kwd};
3371        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3372        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3373        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
3374              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
3375              ($self->{is_xml} and $code == 0x0000)) {
3376          !!!cp (1015);          !!!cp (1015);
3377          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3378                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 3112  sub _get_next_token ($) { Line 3485  sub _get_next_token ($) {
3485        my $code = $self->{kwd};        my $code = $self->{kwd};
3486        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3487        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3488        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
3489              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
3490              ($self->{is_xml} and $code == 0x0000)) {
3491          !!!cp (1008);          !!!cp (1008);
3492          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3493                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 3146  sub _get_next_token ($) { Line 3521  sub _get_next_token ($) {
3521          redo A;          redo A;
3522        }        }
3523      } elsif ($self->{state} == ENTITY_NAME_STATE) {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
3524        if (length $self->{kwd} < 30 and        if ((0x0041 <= $self->{nc} and # a
3525            ## NOTE: Some number greater than the maximum length of entity name             $self->{nc} <= 0x005A) or # x
3526            ((0x0041 <= $self->{nc} and # a            (0x0061 <= $self->{nc} and # a
3527              $self->{nc} <= 0x005A) or # x             $self->{nc} <= 0x007A) or # z
3528             (0x0061 <= $self->{nc} and # a            (0x0030 <= $self->{nc} and # 0
3529              $self->{nc} <= 0x007A) or # z             $self->{nc} <= 0x0039) or # 9
3530             (0x0030 <= $self->{nc} and # 0            $self->{nc} == 0x003B or # ;
3531              $self->{nc} <= 0x0039) or # 9            ($self->{is_xml} and
3532             $self->{nc} == 0x003B)) { # ;             not ($is_space->{$self->{nc}} or
3533                    {
3534                      0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
3535                      $self->{entity_add} => 1,
3536                    }->{$self->{nc}}))) {
3537          our $EntityChar;          our $EntityChar;
3538          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
3539          if (defined $EntityChar->{$self->{kwd}}) {          if (defined $EntityChar->{$self->{kwd}} or
3540                $self->{ge}->{$self->{kwd}}) {
3541            if ($self->{nc} == 0x003B) { # ;            if ($self->{nc} == 0x003B) { # ;
3542              !!!cp (1020);              if (defined $self->{ge}->{$self->{kwd}}) {
3543              $self->{entity__value} = $EntityChar->{$self->{kwd}};                if ($self->{ge}->{$self->{kwd}}->{only_text}) {
3544                    !!!cp (1020.1);
3545                    $self->{entity__value} = $self->{ge}->{$self->{kwd}}->{value};
3546                  } else {
3547                    if (defined $self->{ge}->{$self->{kwd}}->{notation}) {
3548                      !!!cp (1020.2);
3549                      !!!parse-error (type => 'unparsed entity', ## TODO: type
3550                                      value => $self->{kwd});
3551                    } else {
3552                      !!!cp (1020.3);
3553                    }
3554                    $self->{entity__value} = '&' . $self->{kwd}; ## TODO: expand
3555                  }
3556                } else {
3557                  if ($self->{is_xml}) {
3558                    !!!cp (1020.4);
3559                    !!!parse-error (type => 'entity not declared', ## TODO: type
3560                                    value => $self->{kwd},
3561                                    level => {
3562                                              'amp;' => $self->{level}->{warn},
3563                                              'quot;' => $self->{level}->{warn},
3564                                              'lt;' => $self->{level}->{warn},
3565                                              'gt;' => $self->{level}->{warn},
3566                                              'apos;' => $self->{level}->{warn},
3567                                             }->{$self->{kwd}} ||
3568                                             $self->{level}->{must});
3569                  } else {
3570                    !!!cp (1020);
3571                  }
3572                  $self->{entity__value} = $EntityChar->{$self->{kwd}};
3573                }
3574              $self->{entity__match} = 1;              $self->{entity__match} = 1;
3575              !!!next-input-character;              !!!next-input-character;
3576              #              #
# Line 3406  sub _get_next_token ($) { Line 3816  sub _get_next_token ($) {
3816          ## XML5: Not defined yet.          ## XML5: Not defined yet.
3817    
3818          ## TODO:          ## TODO:
3819    
3820            if (not $self->{stop_processing} and
3821                not $self->{document}->xml_standalone) {
3822              !!!parse-error (type => 'stop processing', ## TODO: type
3823                              level => $self->{level}->{info});
3824              $self->{stop_processing} = 1;
3825            }
3826    
3827          !!!next-input-character;          !!!next-input-character;
3828          redo A;          redo A;
3829        } elsif ($self->{nc} == 0x005D) { # ]        } elsif ($self->{nc} == 0x005D) { # ]
# Line 3508  sub _get_next_token ($) { Line 3926  sub _get_next_token ($) {
3926          $self->{state} = MD_HYPHEN_STATE;          $self->{state} = MD_HYPHEN_STATE;
3927          !!!next-input-character;          !!!next-input-character;
3928          redo A;          redo A;
3929        } elsif ($self->{nc} == 0x0045) { # E        } elsif ($self->{nc} == 0x0045 or # E
3930                   $self->{nc} == 0x0065) { # e
3931          $self->{state} = MD_E_STATE;          $self->{state} = MD_E_STATE;
3932          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
3933          !!!next-input-character;          !!!next-input-character;
3934          redo A;          redo A;
3935        } elsif ($self->{nc} == 0x0041) { # A        } elsif ($self->{nc} == 0x0041 or # A
3936                   $self->{nc} == 0x0061) { # a
3937          $self->{state} = MD_ATTLIST_STATE;          $self->{state} = MD_ATTLIST_STATE;
3938          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
3939          !!!next-input-character;          !!!next-input-character;
3940          redo A;          redo A;
3941        } elsif ($self->{nc} == 0x004E) { # N        } elsif ($self->{nc} == 0x004E or # N
3942                   $self->{nc} == 0x006E) { # n
3943          $self->{state} = MD_NOTATION_STATE;          $self->{state} = MD_NOTATION_STATE;
3944          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
3945          !!!next-input-character;          !!!next-input-character;
# Line 3536  sub _get_next_token ($) { Line 3957  sub _get_next_token ($) {
3957        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.
3958        redo A;        redo A;
3959      } elsif ($self->{state} == MD_E_STATE) {      } elsif ($self->{state} == MD_E_STATE) {
3960        if ($self->{nc} == 0x004E) { # N        if ($self->{nc} == 0x004E or # N
3961              $self->{nc} == 0x006E) { # n
3962          $self->{state} = MD_ENTITY_STATE;          $self->{state} = MD_ENTITY_STATE;
3963          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
3964          !!!next-input-character;          !!!next-input-character;
3965          redo A;          redo A;
3966        } elsif ($self->{nc} == 0x004C) { # L        } elsif ($self->{nc} == 0x004C or # L
3967                   $self->{nc} == 0x006C) { # l
3968          ## XML5: <!ELEMENT> not supported.          ## XML5: <!ELEMENT> not supported.
3969          $self->{state} = MD_ELEMENT_STATE;          $self->{state} = MD_ELEMENT_STATE;
3970          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
# Line 3559  sub _get_next_token ($) { Line 3982  sub _get_next_token ($) {
3982          redo A;          redo A;
3983        }        }
3984      } elsif ($self->{state} == MD_ENTITY_STATE) {      } elsif ($self->{state} == MD_ENTITY_STATE) {
3985        if ($self->{nc} == {        if ($self->{nc} == [
3986              'EN' => 0x0054, # T              undef,
3987              'ENT' => 0x0049, # I              undef,
3988              'ENTI' => 0x0054, # T              0x0054, # T
3989            }->{$self->{kwd}}) {              0x0049, # I
3990                0x0054, # T
3991              ]->[length $self->{kwd}] or
3992              $self->{nc} == [
3993                undef,
3994                undef,
3995                0x0074, # t
3996                0x0069, # i
3997                0x0074, # t
3998              ]->[length $self->{kwd}]) {
3999          ## Stay in the state.          ## Stay in the state.
4000          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
4001          !!!next-input-character;          !!!next-input-character;
4002          redo A;          redo A;
4003        } elsif ($self->{kwd} eq 'ENTIT' and        } elsif ((length $self->{kwd}) == 5 and
4004                 $self->{nc} == 0x0059) { # Y                 ($self->{nc} == 0x0059 or # Y
4005          $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '', text => '',                  $self->{nc} == 0x0079)) { # y
4006            if ($self->{kwd} ne 'ENTIT' or $self->{nc} == 0x0079) {
4007              !!!parse-error (type => 'lowercase keyword', ## TODO: type
4008                              text => 'ENTITY',
4009                              line => $self->{line_prev},
4010                              column => $self->{column_prev} - 4);
4011            }
4012            $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '',
4013                         line => $self->{line_prev},                         line => $self->{line_prev},
4014                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 6};
4015          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
# Line 3588  sub _get_next_token ($) { Line 4027  sub _get_next_token ($) {
4027          redo A;          redo A;
4028        }        }
4029      } elsif ($self->{state} == MD_ELEMENT_STATE) {      } elsif ($self->{state} == MD_ELEMENT_STATE) {
4030        if ($self->{nc} == {        if ($self->{nc} == [
4031              'EL' => 0x0045, # E             undef,
4032              'ELE' => 0x004D, # M             undef,
4033              'ELEM' => 0x0045, # E             0x0045, # E
4034              'ELEME' => 0x004E, # N             0x004D, # M
4035            }->{$self->{kwd}}) {             0x0045, # E
4036               0x004E, # N
4037              ]->[length $self->{kwd}] or
4038              $self->{nc} == [
4039               undef,
4040               undef,
4041               0x0065, # e
4042               0x006D, # m
4043               0x0065, # e
4044               0x006E, # n
4045              ]->[length $self->{kwd}]) {
4046          ## Stay in the state.          ## Stay in the state.
4047          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
4048          !!!next-input-character;          !!!next-input-character;
4049          redo A;          redo A;
4050        } elsif ($self->{kwd} eq 'ELEMEN' and        } elsif ((length $self->{kwd}) == 6 and
4051                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
4052                    $self->{nc} == 0x0074)) { # t
4053            if ($self->{kwd} ne 'ELEMEN' or $self->{nc} == 0x0074) {
4054              !!!parse-error (type => 'lowercase keyword', ## TODO: type
4055                              text => 'ELEMENT',
4056                              line => $self->{line_prev},
4057                              column => $self->{column_prev} - 5);
4058            }
4059          $self->{ct} = {type => ELEMENT_TOKEN, name => '',          $self->{ct} = {type => ELEMENT_TOKEN, name => '',
4060                         line => $self->{line_prev},                         line => $self->{line_prev},
4061                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
4062          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
4063          !!!next-input-character;          !!!next-input-character;
4064          redo A;          redo A;
# Line 3618  sub _get_next_token ($) { Line 4074  sub _get_next_token ($) {
4074          redo A;          redo A;
4075        }        }
4076      } elsif ($self->{state} == MD_ATTLIST_STATE) {      } elsif ($self->{state} == MD_ATTLIST_STATE) {
4077        if ($self->{nc} == {        if ($self->{nc} == [
4078              'A' => 0x0054, # T             undef,
4079              'AT' => 0x0054, # T             0x0054, # T
4080              'ATT' => 0x004C, # L             0x0054, # T
4081              'ATTL' => 0x0049, # I             0x004C, # L
4082              'ATTLI' => 0x0053, # S             0x0049, # I
4083            }->{$self->{kwd}}) {             0x0053, # S
4084              ]->[length $self->{kwd}] or
4085              $self->{nc} == [
4086               undef,
4087               0x0074, # t
4088               0x0074, # t
4089               0x006C, # l
4090               0x0069, # i
4091               0x0073, # s
4092              ]->[length $self->{kwd}]) {
4093          ## Stay in the state.          ## Stay in the state.
4094          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
4095          !!!next-input-character;          !!!next-input-character;
4096          redo A;          redo A;
4097        } elsif ($self->{kwd} eq 'ATTLIS' and        } elsif ((length $self->{kwd}) == 6 and
4098                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
4099                    $self->{nc} == 0x0074)) { # t
4100            if ($self->{kwd} ne 'ATTLIS' or $self->{nc} == 0x0074) {
4101              !!!parse-error (type => 'lowercase keyword', ## TODO: type
4102                              text => 'ATTLIST',
4103                              line => $self->{line_prev},
4104                              column => $self->{column_prev} - 5);
4105            }
4106          $self->{ct} = {type => ATTLIST_TOKEN, name => '',          $self->{ct} = {type => ATTLIST_TOKEN, name => '',
4107                         attrdefs => [],                         attrdefs => [],
4108                         line => $self->{line_prev},                         line => $self->{line_prev},
4109                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
4110          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
4111          !!!next-input-character;          !!!next-input-character;
4112          redo A;          redo A;
# Line 3650  sub _get_next_token ($) { Line 4122  sub _get_next_token ($) {
4122          redo A;          redo A;
4123        }        }
4124      } elsif ($self->{state} == MD_NOTATION_STATE) {      } elsif ($self->{state} == MD_NOTATION_STATE) {
4125        if ($self->{nc} == {        if ($self->{nc} == [
4126              'N' => 0x004F, # O             undef,
4127              'NO' => 0x0054, # T             0x004F, # O
4128              'NOT' => 0x0041, # A             0x0054, # T
4129              'NOTA' => 0x0054, # T             0x0041, # A
4130              'NOTAT' => 0x0049, # I             0x0054, # T
4131              'NOTATI' => 0x004F, # O             0x0049, # I
4132            }->{$self->{kwd}}) {             0x004F, # O
4133              ]->[length $self->{kwd}] or
4134              $self->{nc} == [
4135               undef,
4136               0x006F, # o
4137               0x0074, # t
4138               0x0061, # a
4139               0x0074, # t
4140               0x0069, # i
4141               0x006F, # o
4142              ]->[length $self->{kwd}]) {
4143          ## Stay in the state.          ## Stay in the state.
4144          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
4145          !!!next-input-character;          !!!next-input-character;
4146          redo A;          redo A;
4147        } elsif ($self->{kwd} eq 'NOTATIO' and        } elsif ((length $self->{kwd}) == 7 and
4148                 $self->{nc} == 0x004E) { # N                 ($self->{nc} == 0x004E or # N
4149                    $self->{nc} == 0x006E)) { # n
4150            if ($self->{kwd} ne 'NOTATIO' or $self->{nc} == 0x006E) {
4151              !!!parse-error (type => 'lowercase keyword', ## TODO: type
4152                              text => 'NOTATION',
4153                              line => $self->{line_prev},
4154                              column => $self->{column_prev} - 6);
4155            }
4156          $self->{ct} = {type => NOTATION_TOKEN, name => '',          $self->{ct} = {type => NOTATION_TOKEN, name => '',
4157                         line => $self->{line_prev},                         line => $self->{line_prev},
4158                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 8};
4159          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
4160          !!!next-input-character;          !!!next-input-character;
4161          redo A;          redo A;
# Line 3775  sub _get_next_token ($) { Line 4264  sub _get_next_token ($) {
4264        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".
4265                
4266        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
4267          ## TODO:          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
4268          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
4269            } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
4270              $self->{state} = AFTER_ELEMENT_NAME_STATE;
4271            } else { # ENTITY/NOTATION
4272              $self->{state} = AFTER_DOCTYPE_NAME_STATE;
4273            }
4274          !!!next-input-character;          !!!next-input-character;
4275          redo A;          redo A;
4276        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
4277          if ($self->{ct}->{type} == ATTLIST_TOKEN) {          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
4278            #            #
4279          } else {          } else {
4280            !!!parse-error (type => 'no md body'); ## TODO: type            !!!parse-error (type => 'no md def'); ## TODO: type
4281          }          }
4282          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4283          !!!next-input-character;          !!!next-input-character;
# Line 4173  sub _get_next_token ($) { Line 4667  sub _get_next_token ($) {
4667        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
4668          ## XML5: No parse error.          ## XML5: No parse error.
4669          !!!parse-error (type => 'no default type'); ## TODO: type          !!!parse-error (type => 'no default type'); ## TODO: type
4670          $self->{state} = BOGUS_COMMENT_STATE;          $self->{state} = BOGUS_MD_STATE;
         $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded  
4671          ## Reconsume.          ## Reconsume.
4672          redo A;          redo A;
4673        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
# Line 4301  sub _get_next_token ($) { Line 4794  sub _get_next_token ($) {
4794          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
4795          ## Reconsume.          ## Reconsume.
4796          redo A;          redo A;
4797        }              }
4798        } elsif ($self->{state} == NDATA_STATE) {
4799          ## ASCII case-insensitive
4800          if ($self->{nc} == [
4801                undef,
4802                0x0044, # D
4803                0x0041, # A
4804                0x0054, # T
4805              ]->[length $self->{kwd}] or
4806              $self->{nc} == [
4807                undef,
4808                0x0064, # d
4809                0x0061, # a
4810                0x0074, # t
4811              ]->[length $self->{kwd}]) {
4812            !!!cp (172.2);
4813            ## Stay in the state.
4814            $self->{kwd} .= chr $self->{nc};
4815            !!!next-input-character;
4816            redo A;
4817          } elsif ((length $self->{kwd}) == 4 and
4818                   ($self->{nc} == 0x0041 or # A
4819                    $self->{nc} == 0x0061)) { # a
4820            if ($self->{kwd} ne 'NDAT' or $self->{nc} == 0x0061) { # a
4821              !!!cp (172.3);
4822              !!!parse-error (type => 'lowercase keyword', ## TODO: type
4823                              text => 'NDATA',
4824                              line => $self->{line_prev},
4825                              column => $self->{column_prev} - 4);
4826            } else {
4827              !!!cp (172.4);
4828            }
4829            $self->{state} = AFTER_NDATA_STATE;
4830            !!!next-input-character;
4831            redo A;
4832          } else {
4833            !!!parse-error (type => 'string after literal', ## TODO: type
4834                            line => $self->{line_prev},
4835                            column => $self->{column_prev} + 1
4836                                - length $self->{kwd});
4837            !!!cp (172.5);
4838            $self->{state} = BOGUS_MD_STATE;
4839            ## Reconsume.
4840            redo A;
4841          }
4842        } elsif ($self->{state} == AFTER_NDATA_STATE) {
4843          if ($is_space->{$self->{nc}}) {
4844            $self->{state} = BEFORE_NOTATION_NAME_STATE;
4845            !!!next-input-character;
4846            redo A;
4847          } elsif ($self->{nc} == 0x003E) { # >
4848            !!!parse-error (type => 'no notation name'); ## TODO: type
4849            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4850            !!!next-input-character;
4851            !!!emit ($self->{ct}); # ENTITY
4852            redo A;
4853          } elsif ($self->{nc} == -1) {
4854            !!!parse-error (type => 'unclosed md'); ## TODO: type
4855            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4856            !!!next-input-character;
4857            !!!emit ($self->{ct}); # ENTITY
4858            redo A;
4859          } else {
4860            !!!parse-error (type => 'string after literal', ## TODO: type
4861                            line => $self->{line_prev},
4862                            column => $self->{column_prev} + 1
4863                                - length $self->{kwd});
4864            $self->{state} = BOGUS_MD_STATE;
4865            ## Reconsume.
4866            redo A;
4867          }
4868        } elsif ($self->{state} == BEFORE_NOTATION_NAME_STATE) {
4869          if ($is_space->{$self->{nc}}) {
4870            ## Stay in the state.
4871            !!!next-input-character;
4872            redo A;
4873          } elsif ($self->{nc} == 0x003E) { # >
4874            !!!parse-error (type => 'no notation name'); ## TODO: type
4875            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4876            !!!next-input-character;
4877            !!!emit ($self->{ct}); # ENTITY
4878            redo A;
4879          } elsif ($self->{nc} == -1) {
4880            !!!parse-error (type => 'unclosed md'); ## TODO: type
4881            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4882            !!!next-input-character;
4883            !!!emit ($self->{ct}); # ENTITY
4884            redo A;
4885          } else {
4886            $self->{ct}->{notation} = chr $self->{nc}; # ENTITY
4887            $self->{state} = NOTATION_NAME_STATE;
4888            !!!next-input-character;
4889            redo A;
4890          }
4891        } elsif ($self->{state} == NOTATION_NAME_STATE) {
4892          if ($is_space->{$self->{nc}}) {
4893            $self->{state} = AFTER_MD_DEF_STATE;
4894            !!!next-input-character;
4895            redo A;
4896          } elsif ($self->{nc} == 0x003E) { # >
4897            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4898            !!!next-input-character;
4899            !!!emit ($self->{ct}); # ENTITY
4900            redo A;
4901          } elsif ($self->{nc} == -1) {
4902            !!!parse-error (type => 'unclosed md'); ## TODO: type
4903            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4904            !!!next-input-character;
4905            !!!emit ($self->{ct}); # ENTITY
4906            redo A;
4907          } else {
4908            $self->{ct}->{notation} .= chr $self->{nc}; # ENTITY
4909            ## Stay in the state.
4910            !!!next-input-character;
4911            redo A;
4912          }
4913        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE) {
4914          if ($self->{nc} == 0x0022) { # "
4915            $self->{state} = AFTER_MD_DEF_STATE;
4916            !!!next-input-character;
4917            redo A;
4918          } elsif ($self->{nc} == 0x0026) { # &
4919            $self->{prev_state} = $self->{state};
4920            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
4921            $self->{entity_add} = 0x0022; # "
4922            !!!next-input-character;
4923            redo A;
4924    ## TODO: %
4925          } elsif ($self->{nc} == -1) {
4926            !!!parse-error (type => 'unclosed entity value'); ## TODO: type
4927            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4928            ## Reconsume.
4929            !!!emit ($self->{ct}); # ENTITY
4930            redo A;
4931          } else {
4932            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
4933            !!!next-input-character;
4934            redo A;
4935          }
4936        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE) {
4937          if ($self->{nc} == 0x0027) { # '
4938            $self->{state} = AFTER_MD_DEF_STATE;
4939            !!!next-input-character;
4940            redo A;
4941          } elsif ($self->{nc} == 0x0026) { # &
4942            $self->{prev_state} = $self->{state};
4943            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
4944            $self->{entity_add} = 0x0027; # '
4945            !!!next-input-character;
4946            redo A;
4947    ## TODO: %
4948          } elsif ($self->{nc} == -1) {
4949            !!!parse-error (type => 'unclosed entity value'); ## TODO: type
4950            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4951            ## Reconsume.
4952            !!!emit ($self->{ct}); # ENTITY
4953            redo A;
4954          } else {
4955            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
4956            !!!next-input-character;
4957            redo A;
4958          }
4959        } elsif ($self->{state} == ENTITY_VALUE_ENTITY_STATE) {
4960          if ($is_space->{$self->{nc}} or
4961              {
4962                0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
4963                $self->{entity_add} => 1,
4964              }->{$self->{nc}}) {
4965            !!!parse-error (type => 'bare ero',
4966                            line => $self->{line_prev},
4967                            column => $self->{column_prev}
4968                                + ($self->{nc} == -1 ? 1 : 0));
4969            ## Don't consume
4970            ## Return nothing.
4971            #
4972          } elsif ($self->{nc} == 0x0023) { # #
4973            $self->{ca} = $self->{ct};
4974            $self->{state} = ENTITY_HASH_STATE;
4975            $self->{kwd} = '#';
4976            !!!next-input-character;
4977            redo A;
4978          } else {
4979            #
4980          }
4981    
4982          $self->{ct}->{value} .= '&';
4983          $self->{state} = $self->{prev_state};
4984          ## Reconsume.
4985          redo A;
4986        } elsif ($self->{state} == AFTER_ELEMENT_NAME_STATE) {
4987          if ($is_space->{$self->{nc}}) {
4988            $self->{state} = BEFORE_ELEMENT_CONTENT_STATE;
4989            !!!next-input-character;
4990            redo A;
4991          } elsif ($self->{nc} == 0x0028) { # (
4992            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
4993            $self->{ct}->{content} = ['('];
4994            $self->{group_depth} = 1;
4995            !!!next-input-character;
4996            redo A;
4997          } elsif ($self->{nc} == 0x003E) { # >
4998            !!!parse-error (type => 'no md def'); ## TODO: type
4999            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5000            !!!next-input-character;
5001            !!!emit ($self->{ct}); # ELEMENT
5002            redo A;
5003          } elsif ($self->{nc} == -1) {
5004            !!!parse-error (type => 'unclosed md'); ## TODO: type
5005            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5006            !!!next-input-character;
5007            !!!emit ($self->{ct}); # ELEMENT
5008            redo A;
5009          } else {
5010            $self->{ct}->{content} = [chr $self->{nc}];
5011            $self->{state} = CONTENT_KEYWORD_STATE;
5012            !!!next-input-character;
5013            redo A;
5014          }
5015        } elsif ($self->{state} == CONTENT_KEYWORD_STATE) {
5016          if ($is_space->{$self->{nc}}) {
5017            $self->{state} = AFTER_MD_DEF_STATE;
5018            !!!next-input-character;
5019            redo A;
5020          } elsif ($self->{nc} == 0x003E) { # >
5021            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5022            !!!next-input-character;
5023            !!!emit ($self->{ct}); # ELEMENT
5024            redo A;
5025          } elsif ($self->{nc} == -1) {
5026            !!!parse-error (type => 'unclosed md'); ## TODO: type
5027            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5028            !!!next-input-character;
5029            !!!emit ($self->{ct}); # ELEMENT
5030            redo A;
5031          } else {
5032            $self->{ct}->{content}->[-1] .= chr $self->{nc}; # ELEMENT
5033            ## Stay in the state.
5034            !!!next-input-character;
5035            redo A;
5036          }
5037        } elsif ($self->{state} == AFTER_CM_GROUP_OPEN_STATE) {
5038          if ($is_space->{$self->{nc}}) {
5039            ## Stay in the state.
5040            !!!next-input-character;
5041            redo A;
5042          } elsif ($self->{nc} == 0x0028) { # (
5043            $self->{group_depth}++;
5044            push @{$self->{ct}->{content}}, chr $self->{nc};
5045            ## Stay in the state.
5046            !!!next-input-character;
5047            redo A;
5048          } elsif ($self->{nc} == 0x007C or # |
5049                   $self->{nc} == 0x002C) { # ,
5050            !!!parse-error (type => 'empty element name'); ## TODO: type
5051            ## Stay in the state.
5052            !!!next-input-character;
5053            redo A;
5054          } elsif ($self->{nc} == 0x0029) { # )
5055            !!!parse-error (type => 'empty element name'); ## TODO: type
5056            push @{$self->{ct}->{content}}, chr $self->{nc};
5057            $self->{group_depth}--;
5058            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
5059            !!!next-input-character;
5060            redo A;
5061          } elsif ($self->{nc} == 0x003E) { # >
5062            !!!parse-error (type => 'unclosed cm group'); ## TODO: type
5063            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5064            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5065            !!!next-input-character;
5066            !!!emit ($self->{ct}); # ELEMENT
5067            redo A;
5068          } elsif ($self->{nc} == -1) {
5069            !!!parse-error (type => 'unclosed md'); ## TODO: type
5070            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5071            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5072            !!!next-input-character;
5073            !!!emit ($self->{ct}); # ELEMENT
5074            redo A;
5075          } else {
5076            push @{$self->{ct}->{content}}, chr $self->{nc};
5077            $self->{state} = CM_ELEMENT_NAME_STATE;
5078            !!!next-input-character;
5079            redo A;
5080          }
5081        } elsif ($self->{state} == CM_ELEMENT_NAME_STATE) {
5082          if ($is_space->{$self->{nc}}) {
5083            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5084            !!!next-input-character;
5085            redo A;
5086          } elsif ($self->{nc} == 0x002A or # *
5087                   $self->{nc} == 0x002B or # +
5088                   $self->{nc} == 0x003F) { # ?
5089            push @{$self->{ct}->{content}}, chr $self->{nc};
5090            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5091            !!!next-input-character;
5092            redo A;
5093          } elsif ($self->{nc} == 0x007C or # |
5094                   $self->{nc} == 0x002C) { # ,
5095            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
5096            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
5097            !!!next-input-character;
5098            redo A;
5099          } elsif ($self->{nc} == 0x0029) { # )
5100            $self->{group_depth}--;
5101            push @{$self->{ct}->{content}}, chr $self->{nc};
5102            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
5103            !!!next-input-character;
5104            redo A;
5105          } elsif ($self->{nc} == 0x003E) { # >
5106            !!!parse-error (type => 'unclosed cm group'); ## TODO: type
5107            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5108            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5109            !!!next-input-character;
5110            !!!emit ($self->{ct}); # ELEMENT
5111            redo A;
5112          } elsif ($self->{nc} == -1) {
5113            !!!parse-error (type => 'unclosed md'); ## TODO: type
5114            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5115            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5116            !!!next-input-character;
5117            !!!emit ($self->{ct}); # ELEMENT
5118            redo A;
5119          } else {
5120            $self->{ct}->{content}->[-1] .= chr $self->{nc};
5121            ## Stay in the state.
5122            !!!next-input-character;
5123            redo A;
5124          }
5125        } elsif ($self->{state} == AFTER_CM_ELEMENT_NAME_STATE) {
5126          if ($is_space->{$self->{nc}}) {
5127            ## Stay in the state.
5128            !!!next-input-character;
5129            redo A;
5130          } elsif ($self->{nc} == 0x007C or # |
5131                   $self->{nc} == 0x002C) { # ,
5132            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
5133            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
5134            !!!next-input-character;
5135            redo A;
5136          } elsif ($self->{nc} == 0x0029) { # )
5137            $self->{group_depth}--;
5138            push @{$self->{ct}->{content}}, chr $self->{nc};
5139            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
5140            !!!next-input-character;
5141            redo A;
5142          } elsif ($self->{nc} == 0x003E) { # >
5143            !!!parse-error (type => 'unclosed cm group'); ## TODO: type
5144            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5145            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5146            !!!next-input-character;
5147            !!!emit ($self->{ct}); # ELEMENT
5148            redo A;
5149          } elsif ($self->{nc} == -1) {
5150            !!!parse-error (type => 'unclosed md'); ## TODO: type
5151            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5152            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5153            !!!next-input-character;
5154            !!!emit ($self->{ct}); # ELEMENT
5155            redo A;
5156          } else {
5157            !!!parse-error (type => 'after element name'); ## TODO: type
5158            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5159            $self->{state} = BOGUS_MD_STATE;
5160            !!!next-input-character;
5161            redo A;
5162          }
5163        } elsif ($self->{state} == AFTER_CM_GROUP_CLOSE_STATE) {
5164          if ($is_space->{$self->{nc}}) {
5165            if ($self->{group_depth}) {
5166              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5167            } else {
5168              $self->{state} = AFTER_MD_DEF_STATE;
5169            }
5170            !!!next-input-character;
5171            redo A;
5172          } elsif ($self->{nc} == 0x002A or # *
5173                   $self->{nc} == 0x002B or # +
5174                   $self->{nc} == 0x003F) { # ?
5175            push @{$self->{ct}->{content}}, chr $self->{nc};
5176            if ($self->{group_depth}) {
5177              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5178            } else {
5179              $self->{state} = AFTER_MD_DEF_STATE;
5180            }
5181            !!!next-input-character;
5182            redo A;
5183          } elsif ($self->{nc} == 0x0029) { # )
5184            if ($self->{group_depth}) {
5185              $self->{group_depth}--;
5186              push @{$self->{ct}->{content}}, chr $self->{nc};
5187              ## Stay in the state.
5188              !!!next-input-character;
5189              redo A;
5190            } else {
5191              !!!parse-error (type => 'string after md def'); ## TODO: type
5192              $self->{state} = BOGUS_MD_STATE;
5193              ## Reconsume.
5194              redo A;
5195            }
5196          } elsif ($self->{nc} == 0x003E) { # >
5197            if ($self->{group_depth}) {
5198              !!!parse-error (type => 'unclosed cm group'); ## TODO: type
5199              push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5200            }
5201            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5202            !!!next-input-character;
5203            !!!emit ($self->{ct}); # ELEMENT
5204            redo A;
5205          } elsif ($self->{nc} == -1) {
5206            !!!parse-error (type => 'unclosed md'); ## TODO: type
5207            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5208            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5209            !!!next-input-character;
5210            !!!emit ($self->{ct}); # ELEMENT
5211            redo A;
5212          } else {
5213            if ($self->{group_depth}) {
5214              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5215            } else {
5216              !!!parse-error (type => 'string after md def'); ## TODO: type
5217              $self->{state} = BOGUS_MD_STATE;
5218            }
5219            ## Reconsume.
5220            redo A;
5221          }
5222        } elsif ($self->{state} == AFTER_MD_DEF_STATE) {
5223          if ($is_space->{$self->{nc}}) {
5224            ## Stay in the state.
5225            !!!next-input-character;
5226            redo A;
5227          } elsif ($self->{nc} == 0x003E) { # >
5228            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5229            !!!next-input-character;
5230            !!!emit ($self->{ct}); # ENTITY/ELEMENT
5231            redo A;
5232          } elsif ($self->{nc} == -1) {
5233            !!!parse-error (type => 'unclosed md'); ## TODO: type
5234            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5235            !!!next-input-character;
5236            !!!emit ($self->{ct}); # ENTITY/ELEMENT
5237            redo A;
5238          } else {
5239            !!!parse-error (type => 'string after md def'); ## TODO: type
5240            $self->{state} = BOGUS_MD_STATE;
5241            ## Reconsume.
5242            redo A;
5243          }
5244        } elsif ($self->{state} == BOGUS_MD_STATE) {
5245          if ($self->{nc} == 0x003E) { # >
5246            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5247            !!!next-input-character;
5248            !!!emit ($self->{ct}); # ATTLIST/ENTITY/NOTATION
5249            redo A;
5250          } elsif ($self->{nc} == -1) {
5251            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5252            ## Reconsume.
5253            !!!emit ($self->{ct}); # ATTLIST/ENTITY/NOTATION
5254            redo A;
5255          } else {
5256            ## Stay in the state.
5257            !!!next-input-character;
5258            redo A;
5259          }
5260      } else {      } else {
5261        die "$0: $self->{state}: Unknown state";        die "$0: $self->{state}: Unknown state";
5262      }      }

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.34

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24