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

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

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.33 by wakaba, Sat Sep 5 10:41:07 2009 UTC
# Line 105  sub COMMENT_START_STATE () { 14 } Line 105  sub COMMENT_START_STATE () { 14 }
105  sub COMMENT_START_DASH_STATE () { 15 }  sub COMMENT_START_DASH_STATE () { 15 }
106  sub COMMENT_STATE () { 16 }  sub COMMENT_STATE () { 16 }
107  sub COMMENT_END_STATE () { 17 }  sub COMMENT_END_STATE () { 17 }
108    sub COMMENT_END_BANG_STATE () { 102 }
109    sub COMMENT_END_SPACE_STATE () { 103 } ## LAST
110  sub COMMENT_END_DASH_STATE () { 18 }  sub COMMENT_END_DASH_STATE () { 18 }
111  sub BOGUS_COMMENT_STATE () { 19 }  sub BOGUS_COMMENT_STATE () { 19 }
112  sub DOCTYPE_STATE () { 20 }  sub DOCTYPE_STATE () { 20 }
# Line 177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO Line 179  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO
179  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }
180  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }
181  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }
182    sub 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 1083  sub _get_next_token ($) { Line 1102  sub _get_next_token ($) {
1102          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1103          # reconsume          # reconsume
1104    
1105          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1106            #return  ($self->{ct}); # start tag or end tag
1107    
1108          redo A;          redo A;
1109        } elsif ($self->{nc} == 0x002F) { # /        } elsif ($self->{nc} == 0x002F) { # /
# Line 1224  sub _get_next_token ($) { Line 1244  sub _get_next_token ($) {
1244          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1245          # reconsume          # reconsume
1246    
1247          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1248            #return  ($self->{ct}); # start tag or end tag
1249    
1250          redo A;          redo A;
1251        } else {        } else {
1252          if ({          if ({
1253               0x0022 => 1, # "               0x0022 => 1, # "
1254               0x0027 => 1, # '               0x0027 => 1, # '
1255                 0x003C => 1, # <
1256               0x003D => 1, # =               0x003D => 1, # =
1257              }->{$self->{nc}}) {              }->{$self->{nc}}) {
1258                        
# Line 1409  sub _get_next_token ($) { Line 1431  sub _get_next_token ($) {
1431          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1432          # reconsume          # reconsume
1433    
1434          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1435            #return  ($self->{ct}); # start tag or end tag
1436    
1437          redo A;          redo A;
1438        } else {        } else {
1439          if ($self->{nc} == 0x0022 or # "          if ({
1440              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1441                 0x0027 => 1, # '
1442                 0x003C => 1, # <
1443                }->{$self->{nc}}) {
1444                        
1445            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1446            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');
# Line 1573  sub _get_next_token ($) { Line 1599  sub _get_next_token ($) {
1599          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
1600          # reconsume          # reconsume
1601    
1602          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1603            #return  ($self->{ct}); # start tag or end tag
1604    
1605          redo A;          redo A;
1606        } else {        } else {
# Line 1585  sub _get_next_token ($) { Line 1612  sub _get_next_token ($) {
1612                        
1613          }          }
1614    
1615          if ($self->{nc} == 0x0022 or # "          if ({
1616              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1617                 0x0027 => 1, # '
1618                 0x003C => 1, # <
1619                }->{$self->{nc}}) {
1620                        
1621            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1622            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');
# Line 1719  sub _get_next_token ($) { Line 1749  sub _get_next_token ($) {
1749          $self->{s_kwd} = '';          $self->{s_kwd} = '';
1750          ## reconsume          ## reconsume
1751    
1752          return  ($self->{ct}); # start tag or end tag          ## Discard the token.
1753            #return  ($self->{ct}); # start tag or end tag
1754    
1755          redo A;          redo A;
1756        } else {        } else {
1757          if ($self->{nc} == 0x003D) { # =          if ($self->{nc} == 0x003D or $self->{nc} == 0x003C) { # =, <
1758                        
1759            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1760            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute value');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute value');
# Line 1799  sub _get_next_token ($) { Line 1830  sub _get_next_token ($) {
1830      }      }
1831        
1832          redo A;          redo A;
1833          } elsif ($self->{is_xml} and
1834                   $is_space->{$self->{nc}}) {
1835            
1836            $self->{ca}->{value} .= ' ';
1837            ## Stay in the state.
1838            
1839        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1840          $self->{line_prev} = $self->{line};
1841          $self->{column_prev} = $self->{column};
1842          $self->{column}++;
1843          $self->{nc}
1844              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1845        } else {
1846          $self->{set_nc}->($self);
1847        }
1848      
1849            redo A;
1850        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1851          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1852          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1823  sub _get_next_token ($) { Line 1871  sub _get_next_token ($) {
1871            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1872            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1873            ## reconsume            ## reconsume
1874            return  ($self->{ct}); # end tag  
1875              ## Discard the token.
1876              #return  ($self->{ct}); # end tag
1877    
1878            redo A;            redo A;
1879          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
1880            ## XML5: No parse error above; not defined yet.            ## XML5: No parse error above; not defined yet.
1881            push @{$self->{ct}->{attrdefs}}, $self->{ca};            push @{$self->{ct}->{attrdefs}}, $self->{ca};
1882            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
1883            ## Reconsume.            ## Reconsume.
1884            return  ($self->{ct}); # ATTLIST  
1885              ## Discard the token.
1886              #return  ($self->{ct}); # ATTLIST
1887    
1888            redo A;            redo A;
1889          } else {          } else {
1890            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
# Line 1846  sub _get_next_token ($) { Line 1900  sub _get_next_token ($) {
1900          }          }
1901          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1902          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1903                                q["&<],                                qq["&<\x09\x0C\x20],
1904                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1905    
1906          ## Stay in the state          ## Stay in the state
# Line 1913  sub _get_next_token ($) { Line 1967  sub _get_next_token ($) {
1967      }      }
1968        
1969          redo A;          redo A;
1970          } elsif ($self->{is_xml} and
1971                   $is_space->{$self->{nc}}) {
1972            
1973            $self->{ca}->{value} .= ' ';
1974            ## Stay in the state.
1975            
1976        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1977          $self->{line_prev} = $self->{line};
1978          $self->{column_prev} = $self->{column};
1979          $self->{column}++;
1980          $self->{nc}
1981              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1982        } else {
1983          $self->{set_nc}->($self);
1984        }
1985      
1986            redo A;
1987        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1988          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1989          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1922  sub _get_next_token ($) { Line 1993  sub _get_next_token ($) {
1993            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1994            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1995            ## reconsume            ## reconsume
1996            return  ($self->{ct}); # start tag  
1997              ## Discard the token.
1998              #return  ($self->{ct}); # start tag
1999    
2000            redo A;            redo A;
2001          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
2002            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1937  sub _get_next_token ($) { Line 2011  sub _get_next_token ($) {
2011            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
2012            $self->{s_kwd} = '';            $self->{s_kwd} = '';
2013            ## reconsume            ## reconsume
2014            return  ($self->{ct}); # end tag  
2015              ## Discard the token.
2016              #return  ($self->{ct}); # end tag
2017    
2018            redo A;            redo A;
2019          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
2020            ## XML5: No parse error above; not defined yet.            ## XML5: No parse error above; not defined yet.
2021            push @{$self->{ct}->{attrdefs}}, $self->{ca};            push @{$self->{ct}->{attrdefs}}, $self->{ca};
2022            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2023            ## Reconsume.            ## Reconsume.
2024            return  ($self->{ct}); # ATTLIST  
2025              ## Discard the token.
2026              #return  ($self->{ct}); # ATTLIST
2027    
2028            redo A;            redo A;
2029          } else {          } else {
2030            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
# Line 1960  sub _get_next_token ($) { Line 2040  sub _get_next_token ($) {
2040          }          }
2041          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2042          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2043                                q['&<],                                qq['&<\x09\x0C\x20],
2044                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2045    
2046          ## Stay in the state          ## Stay in the state
# Line 2099  sub _get_next_token ($) { Line 2179  sub _get_next_token ($) {
2179            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
2180            $self->{s_kwd} = '';            $self->{s_kwd} = '';
2181            ## reconsume            ## reconsume
2182            return  ($self->{ct}); # start tag  
2183              ## Discard the token.
2184              #return  ($self->{ct}); # start tag
2185              
2186            redo A;            redo A;
2187          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {          } elsif ($self->{ct}->{type} == END_TAG_TOKEN) {
2188            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed tag');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed tag');
# Line 2115  sub _get_next_token ($) { Line 2198  sub _get_next_token ($) {
2198            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
2199            $self->{s_kwd} = '';            $self->{s_kwd} = '';
2200            ## reconsume            ## reconsume
2201            return  ($self->{ct}); # end tag  
2202              ## Discard the token.
2203              #return  ($self->{ct}); # end tag
2204    
2205            redo A;            redo A;
2206          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {          } elsif ($self->{ct}->{type} == ATTLIST_TOKEN) {
2207            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
2208            push @{$self->{ct}->{attrdefs}}, $self->{ca};            push @{$self->{ct}->{attrdefs}}, $self->{ca};
2209            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2210            ## Reconsume.            ## Reconsume.
2211            return  ($self->{ct}); # ATTLIST  
2212              ## Discard the token.
2213              #return  ($self->{ct}); # ATTLIST
2214    
2215            redo A;            redo A;
2216          } else {          } else {
2217            die "$0: $self->{ct}->{type}: Unknown token type";            die "$0: $self->{ct}->{type}: Unknown token type";
# Line 2132  sub _get_next_token ($) { Line 2221  sub _get_next_token ($) {
2221               0x0022 => 1, # "               0x0022 => 1, # "
2222               0x0027 => 1, # '               0x0027 => 1, # '
2223               0x003D => 1, # =               0x003D => 1, # =
2224                 0x003C => 1, # <
2225              }->{$self->{nc}}) {              }->{$self->{nc}}) {
2226                        
2227            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 2141  sub _get_next_token ($) { Line 2231  sub _get_next_token ($) {
2231          }          }
2232          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2233          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2234                                q["'=& >],                                qq["'=& \x09\x0C>],
2235                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2236    
2237          ## Stay in the state          ## Stay in the state
# Line 2241  sub _get_next_token ($) { Line 2331  sub _get_next_token ($) {
2331          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2332          $self->{s_kwd} = '';          $self->{s_kwd} = '';
2333          ## Reconsume.          ## Reconsume.
2334          return  ($self->{ct}); # start tag or end tag  
2335            ## Discard the token.
2336            #return  ($self->{ct}); # start tag or end tag
2337    
2338          redo A;          redo A;
2339        } else {        } else {
2340                    
# Line 2308  sub _get_next_token ($) { Line 2401  sub _get_next_token ($) {
2401          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2402          $self->{s_kwd} = '';          $self->{s_kwd} = '';
2403          ## Reconsume.          ## Reconsume.
2404          return  ($self->{ct}); # start tag or end tag  
2405            ## Discard the token.
2406            #return  ($self->{ct}); # start tag or end tag
2407    
2408          redo A;          redo A;
2409        } else {        } else {
2410                    
# Line 2883  sub _get_next_token ($) { Line 2979  sub _get_next_token ($) {
2979        
2980          redo A;          redo A;
2981        }        }
2982      } elsif ($self->{state} == COMMENT_END_STATE) {      } elsif ($self->{state} == COMMENT_END_STATE or
2983                 $self->{state} == COMMENT_END_BANG_STATE) {
2984        ## XML5: "Comment end state" and "DOCTYPE comment end state".        ## XML5: "Comment end state" and "DOCTYPE comment end state".
2985          ## (No comment end bang state.)
2986    
2987        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
2988          if ($self->{in_subset}) {          if ($self->{in_subset}) {
# Line 2911  sub _get_next_token ($) { Line 3009  sub _get_next_token ($) {
3009    
3010          redo A;          redo A;
3011        } elsif ($self->{nc} == 0x002D) { # -        } elsif ($self->{nc} == 0x002D) { # -
3012            if ($self->{state} == COMMENT_END_BANG_STATE) {
3013              
3014              $self->{ct}->{data} .= '--!'; # comment
3015              $self->{state} = COMMENT_END_DASH_STATE;
3016            } else {
3017              
3018              ## XML5: Not a parse error.
3019              $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',
3020                              line => $self->{line_prev},
3021                              column => $self->{column_prev});
3022              $self->{ct}->{data} .= '-'; # comment
3023              ## Stay in the state
3024            }
3025                    
3026          ## XML5: Not a parse error.      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3027          $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',        $self->{line_prev} = $self->{line};
3028                          line => $self->{line_prev},        $self->{column_prev} = $self->{column};
3029                          column => $self->{column_prev});        $self->{column}++;
3030          $self->{ct}->{data} .= '-'; # comment        $self->{nc}
3031          ## Stay in the state            = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3032        } else {
3033          $self->{set_nc}->($self);
3034        }
3035      
3036            redo A;
3037          } elsif ($self->{state} != COMMENT_END_BANG_STATE and
3038                   $is_space->{$self->{nc}}) {
3039            
3040            $self->{parse_error}->(level => $self->{level}->{must}, type => 'comment end space'); # XXX error type
3041            $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
3042            $self->{state} = COMMENT_END_SPACE_STATE;
3043            
3044        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3045          $self->{line_prev} = $self->{line};
3046          $self->{column_prev} = $self->{column};
3047          $self->{column}++;
3048          $self->{nc}
3049              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3050        } else {
3051          $self->{set_nc}->($self);
3052        }
3053      
3054            redo A;
3055          } elsif ($self->{state} != COMMENT_END_BANG_STATE and
3056                   $self->{nc} == 0x0021) { # !
3057            
3058            $self->{parse_error}->(level => $self->{level}->{must}, type => 'comment end bang'); # XXX error type
3059            $self->{state} = COMMENT_END_BANG_STATE;
3060                    
3061      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3062        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 2940  sub _get_next_token ($) { Line 3079  sub _get_next_token ($) {
3079            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
3080            $self->{s_kwd} = '';            $self->{s_kwd} = '';
3081          }          }
3082          ## reconsume          ## Reconsume.
3083    
3084          return  ($self->{ct}); # comment          return  ($self->{ct}); # comment
3085    
3086          redo A;          redo A;
3087        } else {        } else {
3088                    
3089          ## XML5: Not a parse error.          if ($self->{state} == COMMENT_END_BANG_STATE) {
3090          $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',            $self->{ct}->{data} .= '--!' . chr ($self->{nc}); # comment
3091                          line => $self->{line_prev},          } else {
3092                          column => $self->{column_prev});            $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
3093          $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment          }
3094          $self->{state} = COMMENT_STATE;          $self->{state} = COMMENT_STATE;
3095                    
3096      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 2966  sub _get_next_token ($) { Line 3105  sub _get_next_token ($) {
3105        
3106          redo A;          redo A;
3107        }        }
3108        } elsif ($self->{state} == COMMENT_END_SPACE_STATE) {
3109          ## XML5: Not exist.
3110    
3111          if ($self->{nc} == 0x003E) { # >
3112            if ($self->{in_subset}) {
3113              
3114              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3115            } else {
3116              
3117              $self->{state} = DATA_STATE;
3118              $self->{s_kwd} = '';
3119            }
3120            
3121        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3122          $self->{line_prev} = $self->{line};
3123          $self->{column_prev} = $self->{column};
3124          $self->{column}++;
3125          $self->{nc}
3126              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3127        } else {
3128          $self->{set_nc}->($self);
3129        }
3130      
3131    
3132            return  ($self->{ct}); # comment
3133    
3134            redo A;
3135          } elsif ($is_space->{$self->{nc}}) {
3136            
3137            $self->{ct}->{data} .= chr ($self->{nc}); # comment
3138            ## Stay in the state.
3139            
3140        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3141          $self->{line_prev} = $self->{line};
3142          $self->{column_prev} = $self->{column};
3143          $self->{column}++;
3144          $self->{nc}
3145              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3146        } else {
3147          $self->{set_nc}->($self);
3148        }
3149      
3150            redo A;
3151          } elsif ($self->{nc} == -1) {
3152            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed comment');
3153            if ($self->{in_subset}) {
3154              
3155              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3156            } else {
3157              
3158              $self->{state} = DATA_STATE;
3159              $self->{s_kwd} = '';
3160            }
3161            ## Reconsume.
3162    
3163            return  ($self->{ct}); # comment
3164    
3165            redo A;
3166          } else {
3167            
3168            $self->{ct}->{data} .= chr ($self->{nc}); # comment
3169            $self->{state} = COMMENT_STATE;
3170            
3171        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3172          $self->{line_prev} = $self->{line};
3173          $self->{column_prev} = $self->{column};
3174          $self->{column}++;
3175          $self->{nc}
3176              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3177        } else {
3178          $self->{set_nc}->($self);
3179        }
3180      
3181            redo A;
3182          }
3183      } elsif ($self->{state} == DOCTYPE_STATE) {      } elsif ($self->{state} == DOCTYPE_STATE) {
3184        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
3185                    
# Line 2982  sub _get_next_token ($) { Line 3196  sub _get_next_token ($) {
3196      }      }
3197        
3198          redo A;          redo A;
3199          } elsif ($self->{nc} == -1) {
3200            
3201            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3202            $self->{ct}->{quirks} = 1;
3203    
3204            $self->{state} = DATA_STATE;
3205            ## Reconsume.
3206            return  ($self->{ct}); # DOCTYPE (quirks)
3207    
3208            redo A;
3209        } else {        } else {
3210                    
3211          ## XML5: Unless EOF, swith to the bogus comment state.          ## XML5: Swith to the bogus comment state.
3212          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before DOCTYPE name');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before DOCTYPE name');
3213          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
3214          ## reconsume          ## reconsume
# Line 3029  sub _get_next_token ($) { Line 3253  sub _get_next_token ($) {
3253          return  ($self->{ct}); # DOCTYPE (quirks)          return  ($self->{ct}); # DOCTYPE (quirks)
3254    
3255          redo A;          redo A;
3256          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
3257            
3258            $self->{ct}->{name} # DOCTYPE
3259                = chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
3260            delete $self->{ct}->{quirks};
3261            $self->{state} = DOCTYPE_NAME_STATE;
3262            
3263        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3264          $self->{line_prev} = $self->{line};
3265          $self->{column_prev} = $self->{column};
3266          $self->{column}++;
3267          $self->{nc}
3268              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3269        } else {
3270          $self->{set_nc}->($self);
3271        }
3272      
3273            redo A;
3274        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3275                    
3276          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no DOCTYPE name');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no DOCTYPE name');
# Line 3115  sub _get_next_token ($) { Line 3357  sub _get_next_token ($) {
3357          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3358    
3359          redo A;          redo A;
3360          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
3361            
3362            $self->{ct}->{name} # DOCTYPE
3363                .= chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
3364            delete $self->{ct}->{quirks};
3365            ## Stay in the state.
3366            
3367        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3368          $self->{line_prev} = $self->{line};
3369          $self->{column_prev} = $self->{column};
3370          $self->{column}++;
3371          $self->{nc}
3372              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3373        } else {
3374          $self->{set_nc}->($self);
3375        }
3376      
3377            redo A;
3378        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3379                    
3380          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
# Line 3146  sub _get_next_token ($) { Line 3406  sub _get_next_token ($) {
3406          redo A;          redo A;
3407        } else {        } else {
3408                    
3409          $self->{ct}->{name}          $self->{ct}->{name} .= chr ($self->{nc}); # DOCTYPE
3410            .= chr ($self->{nc}); # DOCTYPE          ## Stay in the state.
         ## Stay in the state  
3411                    
3412      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3413        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3182  sub _get_next_token ($) { Line 3441  sub _get_next_token ($) {
3441        
3442          redo A;          redo A;
3443        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
3444            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3445              
3446              $self->{state} = DATA_STATE;
3447              $self->{s_kwd} = '';
3448            } else {
3449              
3450              $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
3451              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3452            }
3453                    
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3454                    
3455      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3456        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3196  sub _get_next_token ($) { Line 3462  sub _get_next_token ($) {
3462        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3463      }      }
3464        
3465            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
3466          redo A;          redo A;
3467        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3468            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3469              
3470              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3471              $self->{state} = DATA_STATE;
3472              $self->{s_kwd} = '';
3473              $self->{ct}->{quirks} = 1;
3474            } else {
3475              
3476              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3477              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3478            }
3479                    
3480          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');          ## Reconsume.
3481          $self->{state} = DATA_STATE;          return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{s_kwd} = '';  
         ## reconsume  
   
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3482          redo A;          redo A;
3483        } elsif ($self->{nc} == 0x0050 or # P        } elsif ($self->{nc} == 0x0050 or # P
3484                 $self->{nc} == 0x0070) { # p                 $self->{nc} == 0x0070) { # p
# Line 3245  sub _get_next_token ($) { Line 3514  sub _get_next_token ($) {
3514      }      }
3515        
3516          redo A;          redo A;
3517        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{nc} == 0x0022 and # "
3518                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3519                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3520            
3521            $self->{state} = DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE;
3522            $self->{ct}->{value} = ''; # ENTITY
3523            
3524        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3525          $self->{line_prev} = $self->{line};
3526          $self->{column_prev} = $self->{column};
3527          $self->{column}++;
3528          $self->{nc}
3529              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3530        } else {
3531          $self->{set_nc}->($self);
3532        }
3533      
3534            redo A;
3535          } elsif ($self->{nc} == 0x0027 and # '
3536                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3537                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3538            
3539            $self->{state} = DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE;
3540            $self->{ct}->{value} = ''; # ENTITY
3541            
3542        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3543          $self->{line_prev} = $self->{line};
3544          $self->{column_prev} = $self->{column};
3545          $self->{column}++;
3546          $self->{nc}
3547              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3548        } else {
3549          $self->{set_nc}->($self);
3550        }
3551      
3552            redo A;
3553          } elsif ($self->{is_xml} and
3554                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3555                   $self->{nc} == 0x005B) { # [
3556                    
3557          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3558          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 3264  sub _get_next_token ($) { Line 3571  sub _get_next_token ($) {
3571          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3572          redo A;          redo A;
3573        } else {        } else {
3574                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name'); ## TODO: type
3575          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name');  
3576          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3577              
3578              $self->{ct}->{quirks} = 1;
3579              $self->{state} = BOGUS_DOCTYPE_STATE;
3580            } else {
3581              
3582              $self->{state} = BOGUS_MD_STATE;
3583            }
3584    
         $self->{state} = BOGUS_DOCTYPE_STATE;  
3585                    
3586      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3587        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3340  sub _get_next_token ($) { Line 3653  sub _get_next_token ($) {
3653        
3654          redo A;          redo A;
3655        } else {        } else {
3656                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name', ## TODO: type
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name',  
3657                          line => $self->{line_prev},                          line => $self->{line_prev},
3658                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3659          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3660              
3661          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3662              $self->{state} = BOGUS_DOCTYPE_STATE;
3663            } else {
3664              
3665              $self->{state} = BOGUS_MD_STATE;
3666            }
3667          ## Reconsume.          ## Reconsume.
3668          redo A;          redo A;
3669        }        }
# Line 3408  sub _get_next_token ($) { Line 3725  sub _get_next_token ($) {
3725        
3726          redo A;          redo A;
3727        } else {        } else {
3728                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name', ## TODO: type
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name',  
3729                          line => $self->{line_prev},                          line => $self->{line_prev},
3730                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3731          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3732              
3733          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3734              $self->{state} = BOGUS_DOCTYPE_STATE;
3735            } else {
3736              
3737              $self->{state} = BOGUS_MD_STATE;
3738            }
3739          ## Reconsume.          ## Reconsume.
3740          redo A;          redo A;
3741        }        }
# Line 3467  sub _get_next_token ($) { Line 3788  sub _get_next_token ($) {
3788        
3789          redo A;          redo A;
3790        } elsif ($self->{nc} eq 0x003E) { # >        } elsif ($self->{nc} eq 0x003E) { # >
           
3791          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3792            
3793          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3794          $self->{s_kwd} = '';            
3795              $self->{state} = DATA_STATE;
3796              $self->{s_kwd} = '';
3797              $self->{ct}->{quirks} = 1;
3798            } else {
3799              
3800              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3801            }
3802            
3803                    
3804      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3805        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3483  sub _get_next_token ($) { Line 3811  sub _get_next_token ($) {
3811        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3812      }      }
3813        
3814            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3815          redo A;          redo A;
3816        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3817            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3818              
3819              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3820              $self->{state} = DATA_STATE;
3821              $self->{s_kwd} = '';
3822              $self->{ct}->{quirks} = 1;
3823            } else {
3824              
3825              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3826              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3827            }
3828                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3829          ## reconsume          ## reconsume
   
         $self->{ct}->{quirks} = 1;  
3830          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3831          redo A;          redo A;
3832        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
3833                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3834                   $self->{nc} == 0x005B) { # [
3835                    
3836          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3837          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3520  sub _get_next_token ($) { Line 3851  sub _get_next_token ($) {
3851          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3852          redo A;          redo A;
3853        } else {        } else {
           
3854          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after PUBLIC');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after PUBLIC');
         $self->{ct}->{quirks} = 1;  
3855    
3856          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3857              
3858              $self->{ct}->{quirks} = 1;
3859              $self->{state} = BOGUS_DOCTYPE_STATE;
3860            } else {
3861              
3862              $self->{state} = BOGUS_MD_STATE;
3863            }
3864    
3865                    
3866      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3867        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3555  sub _get_next_token ($) { Line 3892  sub _get_next_token ($) {
3892        
3893          redo A;          redo A;
3894        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3895          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3896    
3897          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3898          $self->{s_kwd} = '';            
3899              $self->{state} = DATA_STATE;
3900              $self->{s_kwd} = '';
3901              $self->{ct}->{quirks} = 1;
3902            } else {
3903              
3904              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3905            }
3906    
3907                    
3908      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3909        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3571  sub _get_next_token ($) { Line 3915  sub _get_next_token ($) {
3915        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3916      }      }
3917        
3918            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3919          redo A;          redo A;
3920        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
3921          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3922    
3923          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3924          $self->{s_kwd} = '';            
3925          ## reconsume            $self->{state} = DATA_STATE;
3926              $self->{s_kwd} = '';
3927          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
3928            } else {
3929              
3930              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3931            }
3932            
3933            ## Reconsume.
3934          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3935          redo A;          redo A;
3936        } else {        } else {
3937                    
3938          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
3939          $self->{read_until}->($self->{ct}->{pubid}, q[">],          $self->{read_until}->($self->{ct}->{pubid}, q[">],
3940                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
3941    
# Line 3626  sub _get_next_token ($) { Line 3970  sub _get_next_token ($) {
3970        
3971          redo A;          redo A;
3972        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3973          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3974    
3975          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3976          $self->{s_kwd} = '';            
3977              $self->{state} = DATA_STATE;
3978              $self->{s_kwd} = '';
3979              $self->{ct}->{quirks} = 1;
3980            } else {
3981              
3982              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3983            }
3984    
3985                    
3986      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3987        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3642  sub _get_next_token ($) { Line 3993  sub _get_next_token ($) {
3993        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3994      }      }
3995        
3996            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3997          redo A;          redo A;
3998        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
3999          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
4000    
4001          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4002          $self->{s_kwd} = '';            
4003              $self->{state} = DATA_STATE;
4004              $self->{s_kwd} = '';
4005              $self->{ct}->{quirks} = 1;
4006            } else {
4007              
4008              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4009            }
4010          
4011          ## reconsume          ## reconsume
4012            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4013          redo A;          redo A;
4014        } else {        } else {
4015                    
4016          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4017          $self->{read_until}->($self->{ct}->{pubid}, q['>],          $self->{read_until}->($self->{ct}->{pubid}, q['>],
4018                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
4019    
# Line 3698  sub _get_next_token ($) { Line 4049  sub _get_next_token ($) {
4049          redo A;          redo A;
4050        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
4051                    
4052          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
4053          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;
4054                    
4055      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 3714  sub _get_next_token ($) { Line 4065  sub _get_next_token ($) {
4065          redo A;          redo A;
4066        } elsif ($self->{nc} == 0x0027) { # '        } elsif ($self->{nc} == 0x0027) { # '
4067                    
4068          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
4069          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;
4070                    
4071      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 3729  sub _get_next_token ($) { Line 4080  sub _get_next_token ($) {
4080        
4081          redo A;          redo A;
4082        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
4083          if ($self->{is_xml}) {          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4084                        if ($self->{is_xml}) {
4085            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');              
4086                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
4087              } else {
4088                
4089              }
4090              $self->{state} = DATA_STATE;
4091              $self->{s_kwd} = '';
4092          } else {          } else {
4093                        if ($self->{ct}->{type} == NOTATION_TOKEN) {
4094                
4095              } else {
4096                
4097                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');            
4098              }
4099              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4100          }          }
4101          $self->{state} = DATA_STATE;          
         $self->{s_kwd} = '';  
4102                    
4103      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4104        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3748  sub _get_next_token ($) { Line 4110  sub _get_next_token ($) {
4110        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4111      }      }
4112        
4113            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
4114          redo A;          redo A;
4115        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4116            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4117              
4118              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4119              
4120              $self->{state} = DATA_STATE;
4121              $self->{s_kwd} = '';
4122              $self->{ct}->{quirks} = 1;
4123            } else {
4124              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4125              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4126            }
4127                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
4128          ## reconsume          ## reconsume
4129            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4130          redo A;          redo A;
4131        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4132                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4133                   $self->{nc} == 0x005B) { # [
4134                    
4135          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
4136          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3784  sub _get_next_token ($) { Line 4150  sub _get_next_token ($) {
4150          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4151          redo A;          redo A;
4152        } else {        } else {
           
4153          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after PUBLIC literal');
         $self->{ct}->{quirks} = 1;  
4154    
4155          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4156              
4157              $self->{ct}->{quirks} = 1;
4158              $self->{state} = BOGUS_DOCTYPE_STATE;
4159            } else {
4160              
4161              $self->{state} = BOGUS_MD_STATE;
4162            }
4163    
4164                    
4165      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4166        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3851  sub _get_next_token ($) { Line 4223  sub _get_next_token ($) {
4223        
4224          redo A;          redo A;
4225        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
4226          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
4227                    
4228      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4229        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3867  sub _get_next_token ($) { Line 4236  sub _get_next_token ($) {
4236      }      }
4237        
4238    
4239          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4240          return  ($self->{ct}); # DOCTYPE            
4241              $self->{state} = DATA_STATE;
4242              $self->{s_kwd} = '';
4243              $self->{ct}->{quirks} = 1;
4244            } else {
4245              
4246              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4247            }
4248    
4249            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4250          redo A;          redo A;
4251        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4252            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4253              
4254              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4255              $self->{state} = DATA_STATE;
4256              $self->{s_kwd} = '';
4257              $self->{ct}->{quirks} = 1;
4258            } else {
4259              
4260              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4261              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4262            }
4263                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
4264          ## reconsume          ## reconsume
4265            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4266          redo A;          redo A;
4267        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4268                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4269                   $self->{nc} == 0x005B) { # [
4270                    
4271          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
4272    
# Line 3904  sub _get_next_token ($) { Line 4287  sub _get_next_token ($) {
4287          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4288          redo A;          redo A;
4289        } else {        } else {
           
4290          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM');
         $self->{ct}->{quirks} = 1;  
4291    
4292          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4293                        
4294              $self->{ct}->{quirks} = 1;
4295              $self->{state} = BOGUS_DOCTYPE_STATE;
4296            } else {
4297              
4298              $self->{state} = BOGUS_MD_STATE;
4299            }
4300    
4301                    
4302      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4303        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3939  sub _get_next_token ($) { Line 4328  sub _get_next_token ($) {
4328        
4329          redo A;          redo A;
4330        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >
           
4331          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4332    
4333          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4334          $self->{s_kwd} = '';            
4335              $self->{state} = DATA_STATE;
4336              $self->{s_kwd} = '';
4337              $self->{ct}->{quirks} = 1;
4338            } else {
4339              
4340              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4341            }
4342            
4343                    
4344      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4345        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3955  sub _get_next_token ($) { Line 4351  sub _get_next_token ($) {
4351        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4352      }      }
4353        
4354            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4355          redo A;          redo A;
4356        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4357          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4358    
4359          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4360          $self->{s_kwd} = '';            
4361              $self->{state} = DATA_STATE;
4362              $self->{s_kwd} = '';
4363              $self->{ct}->{quirks} = 1;
4364            } else {
4365              
4366              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4367            }
4368            
4369          ## reconsume          ## reconsume
4370            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4371          redo A;          redo A;
4372        } else {        } else {
4373                    
4374          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4375          $self->{read_until}->($self->{ct}->{sysid}, q[">],          $self->{read_until}->($self->{ct}->{sysid}, q[">],
4376                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4377    
# Line 4032  sub _get_next_token ($) { Line 4428  sub _get_next_token ($) {
4428    
4429          redo A;          redo A;
4430        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4431          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4432    
4433          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4434          $self->{s_kwd} = '';            
4435          ## reconsume            $self->{state} = DATA_STATE;
4436              $self->{s_kwd} = '';
4437          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
4438          return  ($self->{ct}); # DOCTYPE          } else {
4439              
4440              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4441            }
4442    
4443            ## reconsume
4444            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4445          redo A;          redo A;
4446        } else {        } else {
4447                    
4448          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4449          $self->{read_until}->($self->{ct}->{sysid}, q['>],          $self->{read_until}->($self->{ct}->{sysid}, q['>],
4450                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4451    
# Line 4066  sub _get_next_token ($) { Line 4465  sub _get_next_token ($) {
4465        }        }
4466      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
4467        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
4468                    if ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN) {
4469          ## Stay in the state            
4470              $self->{state} = BEFORE_NDATA_STATE;
4471            } else {
4472              
4473              ## Stay in the state
4474            }
4475                    
4476      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4477        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4081  sub _get_next_token ($) { Line 4485  sub _get_next_token ($) {
4485        
4486          redo A;          redo A;
4487        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
4488            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4489              
4490              $self->{state} = DATA_STATE;
4491              $self->{s_kwd} = '';
4492            } else {
4493              
4494              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4495            }
4496    
4497                    
4498          $self->{state} = DATA_STATE;      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4499          $self->{s_kwd} = '';        $self->{line_prev} = $self->{line};
4500          $self->{column_prev} = $self->{column};
4501          $self->{column}++;
4502          $self->{nc}
4503              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4504        } else {
4505          $self->{set_nc}->($self);
4506        }
4507      
4508            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4509            redo A;
4510          } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
4511                   ($self->{nc} == 0x004E or # N
4512                    $self->{nc} == 0x006E)) { # n
4513            
4514            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before NDATA'); ## TODO: type
4515            $self->{state} = NDATA_STATE;
4516            $self->{kwd} = chr $self->{nc};
4517                    
4518      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4519        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4095  sub _get_next_token ($) { Line 4525  sub _get_next_token ($) {
4525        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4526      }      }
4527        
   
         return  ($self->{ct}); # DOCTYPE  
   
4528          redo A;          redo A;
4529        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4530                    if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4531          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');            
4532          $self->{state} = DATA_STATE;            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4533          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
4534          ## reconsume            $self->{s_kwd} = '';
4535              $self->{ct}->{quirks} = 1;
4536          $self->{ct}->{quirks} = 1;          } else {
4537          return  ($self->{ct}); # DOCTYPE            
4538              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4539              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4540            }
4541    
4542            ## reconsume
4543            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4544          redo A;          redo A;
4545        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4546                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4547                   $self->{nc} == 0x005B) { # [
4548                    
4549          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4550          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 4129  sub _get_next_token ($) { Line 4563  sub _get_next_token ($) {
4563          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4564          redo A;          redo A;
4565        } else {        } else {
           
4566          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM literal');
         #$self->{ct}->{quirks} = 1;  
4567    
4568          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4569              
4570              #$self->{ct}->{quirks} = 1;
4571              $self->{state} = BOGUS_DOCTYPE_STATE;
4572            } else {
4573              
4574              $self->{state} = BOGUS_MD_STATE;
4575            }
4576    
4577            
4578        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4579          $self->{line_prev} = $self->{line};
4580          $self->{column_prev} = $self->{column};
4581          $self->{column}++;
4582          $self->{nc}
4583              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4584        } else {
4585          $self->{set_nc}->($self);
4586        }
4587      
4588            redo A;
4589          }
4590        } elsif ($self->{state} == BEFORE_NDATA_STATE) {
4591          if ($is_space->{$self->{nc}}) {
4592            
4593            ## Stay in the state.
4594            
4595        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4596          $self->{line_prev} = $self->{line};
4597          $self->{column_prev} = $self->{column};
4598          $self->{column}++;
4599          $self->{nc}
4600              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4601        } else {
4602          $self->{set_nc}->($self);
4603        }
4604      
4605            redo A;
4606          } elsif ($self->{nc} == 0x003E) { # >
4607            
4608            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4609            
4610        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4611          $self->{line_prev} = $self->{line};
4612          $self->{column_prev} = $self->{column};
4613          $self->{column}++;
4614          $self->{nc}
4615              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4616        } else {
4617          $self->{set_nc}->($self);
4618        }
4619      
4620            return  ($self->{ct}); # ENTITY
4621            redo A;
4622          } elsif ($self->{nc} == 0x004E or # N
4623                   $self->{nc} == 0x006E) { # n
4624            
4625            $self->{state} = NDATA_STATE;
4626            $self->{kwd} = chr $self->{nc};
4627            
4628        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4629          $self->{line_prev} = $self->{line};
4630          $self->{column_prev} = $self->{column};
4631          $self->{column}++;
4632          $self->{nc}
4633              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4634        } else {
4635          $self->{set_nc}->($self);
4636        }
4637      
4638            redo A;
4639          } elsif ($self->{nc} == -1) {
4640            
4641            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4642            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4643            ## reconsume
4644            return  ($self->{ct}); # ENTITY
4645            redo A;
4646          } else {
4647            
4648            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM literal');
4649            $self->{state} = BOGUS_MD_STATE;
4650                    
4651      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4652        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4357  sub _get_next_token ($) { Line 4870  sub _get_next_token ($) {
4870              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
4871              $self->{entity_add} => 1,              $self->{entity_add} => 1,
4872            }->{$self->{nc}}) {            }->{$self->{nc}}) {
4873                    if ($self->{is_xml}) {
4874              
4875              $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
4876                              line => $self->{line_prev},
4877                              column => $self->{column_prev}
4878                                  + ($self->{nc} == -1 ? 1 : 0));
4879            } else {
4880              
4881              ## No error
4882            }
4883          ## Don't consume          ## Don't consume
         ## No error  
4884          ## Return nothing.          ## Return nothing.
4885          #          #
4886        } elsif ($self->{nc} == 0x0023) { # #        } elsif ($self->{nc} == 0x0023) { # #
# Line 4378  sub _get_next_token ($) { Line 4899  sub _get_next_token ($) {
4899      }      }
4900        
4901          redo A;          redo A;
4902        } elsif ((0x0041 <= $self->{nc} and        } elsif ($self->{is_xml} or
4903                   (0x0041 <= $self->{nc} and
4904                  $self->{nc} <= 0x005A) or # A..Z                  $self->{nc} <= 0x005A) or # A..Z
4905                 (0x0061 <= $self->{nc} and                 (0x0061 <= $self->{nc} and
4906                  $self->{nc} <= 0x007A)) { # a..z                  $self->{nc} <= 0x007A)) { # a..z
# Line 4432  sub _get_next_token ($) { Line 4954  sub _get_next_token ($) {
4954          redo A;          redo A;
4955        }        }
4956      } elsif ($self->{state} == ENTITY_HASH_STATE) {      } elsif ($self->{state} == ENTITY_HASH_STATE) {
4957        if ($self->{nc} == 0x0078 or # x        if ($self->{nc} == 0x0078) { # x
4958            $self->{nc} == 0x0058) { # X          
4959            $self->{state} = HEXREF_X_STATE;
4960            $self->{kwd} .= chr $self->{nc};
4961            
4962        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4963          $self->{line_prev} = $self->{line};
4964          $self->{column_prev} = $self->{column};
4965          $self->{column}++;
4966          $self->{nc}
4967              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4968        } else {
4969          $self->{set_nc}->($self);
4970        }
4971      
4972            redo A;
4973          } elsif ($self->{nc} == 0x0058) { # X
4974                    
4975            if ($self->{is_xml}) {
4976              $self->{parse_error}->(level => $self->{level}->{must}, type => 'uppercase hcro'); ## TODO: type
4977            }
4978          $self->{state} = HEXREF_X_STATE;          $self->{state} = HEXREF_X_STATE;
4979          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
4980                    
# Line 4539  sub _get_next_token ($) { Line 5079  sub _get_next_token ($) {
5079        my $code = $self->{kwd};        my $code = $self->{kwd};
5080        my $l = $self->{line_prev};        my $l = $self->{line_prev};
5081        my $c = $self->{column_prev};        my $c = $self->{column_prev};
5082        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
5083              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
5084              ($self->{is_xml} and $code == 0x0000)) {
5085                    
5086          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
5087                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4692  sub _get_next_token ($) { Line 5234  sub _get_next_token ($) {
5234        my $code = $self->{kwd};        my $code = $self->{kwd};
5235        my $l = $self->{line_prev};        my $l = $self->{line_prev};
5236        my $c = $self->{column_prev};        my $c = $self->{column_prev};
5237        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
5238              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
5239              ($self->{is_xml} and $code == 0x0000)) {
5240                    
5241          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
5242                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4726  sub _get_next_token ($) { Line 5270  sub _get_next_token ($) {
5270          redo A;          redo A;
5271        }        }
5272      } elsif ($self->{state} == ENTITY_NAME_STATE) {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
5273        if (length $self->{kwd} < 30 and        if ((0x0041 <= $self->{nc} and # a
5274            ## NOTE: Some number greater than the maximum length of entity name             $self->{nc} <= 0x005A) or # x
5275            ((0x0041 <= $self->{nc} and # a            (0x0061 <= $self->{nc} and # a
5276              $self->{nc} <= 0x005A) or # x             $self->{nc} <= 0x007A) or # z
5277             (0x0061 <= $self->{nc} and # a            (0x0030 <= $self->{nc} and # 0
5278              $self->{nc} <= 0x007A) or # z             $self->{nc} <= 0x0039) or # 9
5279             (0x0030 <= $self->{nc} and # 0            $self->{nc} == 0x003B or # ;
5280              $self->{nc} <= 0x0039) or # 9            ($self->{is_xml} and
5281             $self->{nc} == 0x003B)) { # ;             not ($is_space->{$self->{nc}} or
5282                    {
5283                      0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
5284                      $self->{entity_add} => 1,
5285                    }->{$self->{nc}}))) {
5286          our $EntityChar;          our $EntityChar;
5287          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5288          if (defined $EntityChar->{$self->{kwd}}) {          if (defined $EntityChar->{$self->{kwd}} or
5289                $self->{ge}->{$self->{kwd}}) {
5290            if ($self->{nc} == 0x003B) { # ;            if ($self->{nc} == 0x003B) { # ;
5291                            if (defined $self->{ge}->{$self->{kwd}}) {
5292              $self->{entity__value} = $EntityChar->{$self->{kwd}};                if ($self->{ge}->{$self->{kwd}}->{only_text}) {
5293                    
5294                    $self->{entity__value} = $self->{ge}->{$self->{kwd}}->{value};
5295                  } else {
5296                    if (defined $self->{ge}->{$self->{kwd}}->{notation}) {
5297                      
5298                      $self->{parse_error}->(level => $self->{level}->{must}, type => 'unparsed entity', ## TODO: type
5299                                      value => $self->{kwd});
5300                    } else {
5301                      
5302                    }
5303                    $self->{entity__value} = '&' . $self->{kwd}; ## TODO: expand
5304                  }
5305                } else {
5306                  if ($self->{is_xml}) {
5307                    
5308                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'entity not declared', ## TODO: type
5309                                    value => $self->{kwd},
5310                                    level => {
5311                                              'amp;' => $self->{level}->{warn},
5312                                              'quot;' => $self->{level}->{warn},
5313                                              'lt;' => $self->{level}->{warn},
5314                                              'gt;' => $self->{level}->{warn},
5315                                              'apos;' => $self->{level}->{warn},
5316                                             }->{$self->{kwd}} ||
5317                                             $self->{level}->{must});
5318                  } else {
5319                    
5320                  }
5321                  $self->{entity__value} = $EntityChar->{$self->{kwd}};
5322                }
5323              $self->{entity__match} = 1;              $self->{entity__match} = 1;
5324                            
5325      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5136  sub _get_next_token ($) { Line 5715  sub _get_next_token ($) {
5715          ## XML5: Not defined yet.          ## XML5: Not defined yet.
5716    
5717          ## TODO:          ## TODO:
5718    
5719            if (not $self->{stop_processing} and
5720                not $self->{document}->xml_standalone) {
5721              $self->{parse_error}->(level => $self->{level}->{must}, type => 'stop processing', ## TODO: type
5722                              level => $self->{level}->{info});
5723              $self->{stop_processing} = 1;
5724            }
5725    
5726                    
5727      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
5728        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5358  sub _get_next_token ($) { Line 5945  sub _get_next_token ($) {
5945      }      }
5946        
5947          redo A;          redo A;
5948        } elsif ($self->{nc} == 0x0045) { # E        } elsif ($self->{nc} == 0x0045 or # E
5949                   $self->{nc} == 0x0065) { # e
5950          $self->{state} = MD_E_STATE;          $self->{state} = MD_E_STATE;
5951          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5952                    
# Line 5373  sub _get_next_token ($) { Line 5961  sub _get_next_token ($) {
5961      }      }
5962        
5963          redo A;          redo A;
5964        } elsif ($self->{nc} == 0x0041) { # A        } elsif ($self->{nc} == 0x0041 or # A
5965                   $self->{nc} == 0x0061) { # a
5966          $self->{state} = MD_ATTLIST_STATE;          $self->{state} = MD_ATTLIST_STATE;
5967          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5968                    
# Line 5388  sub _get_next_token ($) { Line 5977  sub _get_next_token ($) {
5977      }      }
5978        
5979          redo A;          redo A;
5980        } elsif ($self->{nc} == 0x004E) { # N        } elsif ($self->{nc} == 0x004E or # N
5981                   $self->{nc} == 0x006E) { # n
5982          $self->{state} = MD_NOTATION_STATE;          $self->{state} = MD_NOTATION_STATE;
5983          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5984                    
# Line 5416  sub _get_next_token ($) { Line 6006  sub _get_next_token ($) {
6006        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.
6007        redo A;        redo A;
6008      } elsif ($self->{state} == MD_E_STATE) {      } elsif ($self->{state} == MD_E_STATE) {
6009        if ($self->{nc} == 0x004E) { # N        if ($self->{nc} == 0x004E or # N
6010              $self->{nc} == 0x006E) { # n
6011          $self->{state} = MD_ENTITY_STATE;          $self->{state} = MD_ENTITY_STATE;
6012          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6013                    
# Line 5431  sub _get_next_token ($) { Line 6022  sub _get_next_token ($) {
6022      }      }
6023        
6024          redo A;          redo A;
6025        } elsif ($self->{nc} == 0x004C) { # L        } elsif ($self->{nc} == 0x004C or # L
6026                   $self->{nc} == 0x006C) { # l
6027          ## XML5: <!ELEMENT> not supported.          ## XML5: <!ELEMENT> not supported.
6028          $self->{state} = MD_ELEMENT_STATE;          $self->{state} = MD_ELEMENT_STATE;
6029          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
# Line 5459  sub _get_next_token ($) { Line 6051  sub _get_next_token ($) {
6051          redo A;          redo A;
6052        }        }
6053      } elsif ($self->{state} == MD_ENTITY_STATE) {      } elsif ($self->{state} == MD_ENTITY_STATE) {
6054        if ($self->{nc} == {        if ($self->{nc} == [
6055              'EN' => 0x0054, # T              undef,
6056              'ENT' => 0x0049, # I              undef,
6057              'ENTI' => 0x0054, # T              0x0054, # T
6058            }->{$self->{kwd}}) {              0x0049, # I
6059                0x0054, # T
6060              ]->[length $self->{kwd}] or
6061              $self->{nc} == [
6062                undef,
6063                undef,
6064                0x0074, # t
6065                0x0069, # i
6066                0x0074, # t
6067              ]->[length $self->{kwd}]) {
6068          ## Stay in the state.          ## Stay in the state.
6069          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6070                    
# Line 5478  sub _get_next_token ($) { Line 6079  sub _get_next_token ($) {
6079      }      }
6080        
6081          redo A;          redo A;
6082        } elsif ($self->{kwd} eq 'ENTIT' and        } elsif ((length $self->{kwd}) == 5 and
6083                 $self->{nc} == 0x0059) { # Y                 ($self->{nc} == 0x0059 or # Y
6084          $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '', text => '',                  $self->{nc} == 0x0079)) { # y
6085            if ($self->{kwd} ne 'ENTIT' or $self->{nc} == 0x0079) {
6086              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6087                              text => 'ENTITY',
6088                              line => $self->{line_prev},
6089                              column => $self->{column_prev} - 4);
6090            }
6091            $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '',
6092                         line => $self->{line_prev},                         line => $self->{line_prev},
6093                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 6};
6094          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
# Line 5508  sub _get_next_token ($) { Line 6116  sub _get_next_token ($) {
6116          redo A;          redo A;
6117        }        }
6118      } elsif ($self->{state} == MD_ELEMENT_STATE) {      } elsif ($self->{state} == MD_ELEMENT_STATE) {
6119        if ($self->{nc} == {        if ($self->{nc} == [
6120              'EL' => 0x0045, # E             undef,
6121              'ELE' => 0x004D, # M             undef,
6122              'ELEM' => 0x0045, # E             0x0045, # E
6123              'ELEME' => 0x004E, # N             0x004D, # M
6124            }->{$self->{kwd}}) {             0x0045, # E
6125               0x004E, # N
6126              ]->[length $self->{kwd}] or
6127              $self->{nc} == [
6128               undef,
6129               undef,
6130               0x0065, # e
6131               0x006D, # m
6132               0x0065, # e
6133               0x006E, # n
6134              ]->[length $self->{kwd}]) {
6135          ## Stay in the state.          ## Stay in the state.
6136          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6137                    
# Line 5528  sub _get_next_token ($) { Line 6146  sub _get_next_token ($) {
6146      }      }
6147        
6148          redo A;          redo A;
6149        } elsif ($self->{kwd} eq 'ELEMEN' and        } elsif ((length $self->{kwd}) == 6 and
6150                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
6151                    $self->{nc} == 0x0074)) { # t
6152            if ($self->{kwd} ne 'ELEMEN' or $self->{nc} == 0x0074) {
6153              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6154                              text => 'ELEMENT',
6155                              line => $self->{line_prev},
6156                              column => $self->{column_prev} - 5);
6157            }
6158          $self->{ct} = {type => ELEMENT_TOKEN, name => '',          $self->{ct} = {type => ELEMENT_TOKEN, name => '',
6159                         line => $self->{line_prev},                         line => $self->{line_prev},
6160                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
6161          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6162                    
6163      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5558  sub _get_next_token ($) { Line 6183  sub _get_next_token ($) {
6183          redo A;          redo A;
6184        }        }
6185      } elsif ($self->{state} == MD_ATTLIST_STATE) {      } elsif ($self->{state} == MD_ATTLIST_STATE) {
6186        if ($self->{nc} == {        if ($self->{nc} == [
6187              'A' => 0x0054, # T             undef,
6188              'AT' => 0x0054, # T             0x0054, # T
6189              'ATT' => 0x004C, # L             0x0054, # T
6190              'ATTL' => 0x0049, # I             0x004C, # L
6191              'ATTLI' => 0x0053, # S             0x0049, # I
6192            }->{$self->{kwd}}) {             0x0053, # S
6193              ]->[length $self->{kwd}] or
6194              $self->{nc} == [
6195               undef,
6196               0x0074, # t
6197               0x0074, # t
6198               0x006C, # l
6199               0x0069, # i
6200               0x0073, # s
6201              ]->[length $self->{kwd}]) {
6202          ## Stay in the state.          ## Stay in the state.
6203          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6204                    
# Line 5579  sub _get_next_token ($) { Line 6213  sub _get_next_token ($) {
6213      }      }
6214        
6215          redo A;          redo A;
6216        } elsif ($self->{kwd} eq 'ATTLIS' and        } elsif ((length $self->{kwd}) == 6 and
6217                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
6218                    $self->{nc} == 0x0074)) { # t
6219            if ($self->{kwd} ne 'ATTLIS' or $self->{nc} == 0x0074) {
6220              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6221                              text => 'ATTLIST',
6222                              line => $self->{line_prev},
6223                              column => $self->{column_prev} - 5);
6224            }
6225          $self->{ct} = {type => ATTLIST_TOKEN, name => '',          $self->{ct} = {type => ATTLIST_TOKEN, name => '',
6226                         attrdefs => [],                         attrdefs => [],
6227                         line => $self->{line_prev},                         line => $self->{line_prev},
6228                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
6229          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6230                    
6231      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5610  sub _get_next_token ($) { Line 6251  sub _get_next_token ($) {
6251          redo A;          redo A;
6252        }        }
6253      } elsif ($self->{state} == MD_NOTATION_STATE) {      } elsif ($self->{state} == MD_NOTATION_STATE) {
6254        if ($self->{nc} == {        if ($self->{nc} == [
6255              'N' => 0x004F, # O             undef,
6256              'NO' => 0x0054, # T             0x004F, # O
6257              'NOT' => 0x0041, # A             0x0054, # T
6258              'NOTA' => 0x0054, # T             0x0041, # A
6259              'NOTAT' => 0x0049, # I             0x0054, # T
6260              'NOTATI' => 0x004F, # O             0x0049, # I
6261            }->{$self->{kwd}}) {             0x004F, # O
6262              ]->[length $self->{kwd}] or
6263              $self->{nc} == [
6264               undef,
6265               0x006F, # o
6266               0x0074, # t
6267               0x0061, # a
6268               0x0074, # t
6269               0x0069, # i
6270               0x006F, # o
6271              ]->[length $self->{kwd}]) {
6272          ## Stay in the state.          ## Stay in the state.
6273          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6274                    
# Line 5632  sub _get_next_token ($) { Line 6283  sub _get_next_token ($) {
6283      }      }
6284        
6285          redo A;          redo A;
6286        } elsif ($self->{kwd} eq 'NOTATIO' and        } elsif ((length $self->{kwd}) == 7 and
6287                 $self->{nc} == 0x004E) { # N                 ($self->{nc} == 0x004E or # N
6288                    $self->{nc} == 0x006E)) { # n
6289            if ($self->{kwd} ne 'NOTATIO' or $self->{nc} == 0x006E) {
6290              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6291                              text => 'NOTATION',
6292                              line => $self->{line_prev},
6293                              column => $self->{column_prev} - 6);
6294            }
6295          $self->{ct} = {type => NOTATION_TOKEN, name => '',          $self->{ct} = {type => NOTATION_TOKEN, name => '',
6296                         line => $self->{line_prev},                         line => $self->{line_prev},
6297                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 8};
6298          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6299                    
6300      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5845  sub _get_next_token ($) { Line 6503  sub _get_next_token ($) {
6503        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".
6504                
6505        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
6506          ## TODO:          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6507          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
6508            } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
6509              $self->{state} = AFTER_ELEMENT_NAME_STATE;
6510            } else { # ENTITY/NOTATION
6511              $self->{state} = AFTER_DOCTYPE_NAME_STATE;
6512            }
6513                    
6514      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6515        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5863  sub _get_next_token ($) { Line 6526  sub _get_next_token ($) {
6526          if ($self->{ct}->{type} == ATTLIST_TOKEN) {          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6527            #            #
6528          } else {          } else {
6529            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md body'); ## TODO: type            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
6530          }          }
6531          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
6532                    
# Line 6853  sub _get_next_token ($) { Line 7516  sub _get_next_token ($) {
7516        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
7517          ## XML5: No parse error.          ## XML5: No parse error.
7518          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no default type'); ## TODO: type          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no default type'); ## TODO: type
7519          $self->{state} = BOGUS_COMMENT_STATE;          $self->{state} = BOGUS_MD_STATE;
         $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded  
7520          ## Reconsume.          ## Reconsume.
7521          redo A;          redo A;
7522        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
# Line 7141  sub _get_next_token ($) { Line 7803  sub _get_next_token ($) {
7803          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
7804          ## Reconsume.          ## Reconsume.
7805          redo A;          redo A;
7806        }              }
7807        } elsif ($self->{state} == NDATA_STATE) {
7808          ## ASCII case-insensitive
7809          if ($self->{nc} == [
7810                undef,
7811                0x0044, # D
7812                0x0041, # A
7813                0x0054, # T
7814              ]->[length $self->{kwd}] or
7815              $self->{nc} == [
7816                undef,
7817                0x0064, # d
7818                0x0061, # a
7819                0x0074, # t
7820              ]->[length $self->{kwd}]) {
7821            
7822            ## Stay in the state.
7823            $self->{kwd} .= chr $self->{nc};
7824            
7825        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7826          $self->{line_prev} = $self->{line};
7827          $self->{column_prev} = $self->{column};
7828          $self->{column}++;
7829          $self->{nc}
7830              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7831        } else {
7832          $self->{set_nc}->($self);
7833        }
7834      
7835            redo A;
7836          } elsif ((length $self->{kwd}) == 4 and
7837                   ($self->{nc} == 0x0041 or # A
7838                    $self->{nc} == 0x0061)) { # a
7839            if ($self->{kwd} ne 'NDAT' or $self->{nc} == 0x0061) { # a
7840              
7841              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
7842                              text => 'NDATA',
7843                              line => $self->{line_prev},
7844                              column => $self->{column_prev} - 4);
7845            } else {
7846              
7847            }
7848            $self->{state} = AFTER_NDATA_STATE;
7849            
7850        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7851          $self->{line_prev} = $self->{line};
7852          $self->{column_prev} = $self->{column};
7853          $self->{column}++;
7854          $self->{nc}
7855              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7856        } else {
7857          $self->{set_nc}->($self);
7858        }
7859      
7860            redo A;
7861          } else {
7862            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7863                            line => $self->{line_prev},
7864                            column => $self->{column_prev} + 1
7865                                - length $self->{kwd});
7866            
7867            $self->{state} = BOGUS_MD_STATE;
7868            ## Reconsume.
7869            redo A;
7870          }
7871        } elsif ($self->{state} == AFTER_NDATA_STATE) {
7872          if ($is_space->{$self->{nc}}) {
7873            $self->{state} = BEFORE_NOTATION_NAME_STATE;
7874            
7875        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7876          $self->{line_prev} = $self->{line};
7877          $self->{column_prev} = $self->{column};
7878          $self->{column}++;
7879          $self->{nc}
7880              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7881        } else {
7882          $self->{set_nc}->($self);
7883        }
7884      
7885            redo A;
7886          } elsif ($self->{nc} == 0x003E) { # >
7887            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7888            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7889            
7890        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7891          $self->{line_prev} = $self->{line};
7892          $self->{column_prev} = $self->{column};
7893          $self->{column}++;
7894          $self->{nc}
7895              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7896        } else {
7897          $self->{set_nc}->($self);
7898        }
7899      
7900            return  ($self->{ct}); # ENTITY
7901            redo A;
7902          } elsif ($self->{nc} == -1) {
7903            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7904            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7905            
7906        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7907          $self->{line_prev} = $self->{line};
7908          $self->{column_prev} = $self->{column};
7909          $self->{column}++;
7910          $self->{nc}
7911              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7912        } else {
7913          $self->{set_nc}->($self);
7914        }
7915      
7916            return  ($self->{ct}); # ENTITY
7917            redo A;
7918          } else {
7919            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7920                            line => $self->{line_prev},
7921                            column => $self->{column_prev} + 1
7922                                - length $self->{kwd});
7923            $self->{state} = BOGUS_MD_STATE;
7924            ## Reconsume.
7925            redo A;
7926          }
7927        } elsif ($self->{state} == BEFORE_NOTATION_NAME_STATE) {
7928          if ($is_space->{$self->{nc}}) {
7929            ## Stay in the state.
7930            
7931        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7932          $self->{line_prev} = $self->{line};
7933          $self->{column_prev} = $self->{column};
7934          $self->{column}++;
7935          $self->{nc}
7936              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7937        } else {
7938          $self->{set_nc}->($self);
7939        }
7940      
7941            redo A;
7942          } elsif ($self->{nc} == 0x003E) { # >
7943            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7944            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7945            
7946        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7947          $self->{line_prev} = $self->{line};
7948          $self->{column_prev} = $self->{column};
7949          $self->{column}++;
7950          $self->{nc}
7951              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7952        } else {
7953          $self->{set_nc}->($self);
7954        }
7955      
7956            return  ($self->{ct}); # ENTITY
7957            redo A;
7958          } elsif ($self->{nc} == -1) {
7959            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7960            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7961            
7962        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7963          $self->{line_prev} = $self->{line};
7964          $self->{column_prev} = $self->{column};
7965          $self->{column}++;
7966          $self->{nc}
7967              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7968        } else {
7969          $self->{set_nc}->($self);
7970        }
7971      
7972            return  ($self->{ct}); # ENTITY
7973            redo A;
7974          } else {
7975            $self->{ct}->{notation} = chr $self->{nc}; # ENTITY
7976            $self->{state} = NOTATION_NAME_STATE;
7977            
7978        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7979          $self->{line_prev} = $self->{line};
7980          $self->{column_prev} = $self->{column};
7981          $self->{column}++;
7982          $self->{nc}
7983              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7984        } else {
7985          $self->{set_nc}->($self);
7986        }
7987      
7988            redo A;
7989          }
7990        } elsif ($self->{state} == NOTATION_NAME_STATE) {
7991          if ($is_space->{$self->{nc}}) {
7992            $self->{state} = AFTER_MD_DEF_STATE;
7993            
7994        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7995          $self->{line_prev} = $self->{line};
7996          $self->{column_prev} = $self->{column};
7997          $self->{column}++;
7998          $self->{nc}
7999              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8000        } else {
8001          $self->{set_nc}->($self);
8002        }
8003      
8004            redo A;
8005          } elsif ($self->{nc} == 0x003E) { # >
8006            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8007            
8008        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8009          $self->{line_prev} = $self->{line};
8010          $self->{column_prev} = $self->{column};
8011          $self->{column}++;
8012          $self->{nc}
8013              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8014        } else {
8015          $self->{set_nc}->($self);
8016        }
8017      
8018            return  ($self->{ct}); # ENTITY
8019            redo A;
8020          } elsif ($self->{nc} == -1) {
8021            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8022            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8023            
8024        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8025          $self->{line_prev} = $self->{line};
8026          $self->{column_prev} = $self->{column};
8027          $self->{column}++;
8028          $self->{nc}
8029              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8030        } else {
8031          $self->{set_nc}->($self);
8032        }
8033      
8034            return  ($self->{ct}); # ENTITY
8035            redo A;
8036          } else {
8037            $self->{ct}->{notation} .= chr $self->{nc}; # ENTITY
8038            ## Stay in the state.
8039            
8040        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8041          $self->{line_prev} = $self->{line};
8042          $self->{column_prev} = $self->{column};
8043          $self->{column}++;
8044          $self->{nc}
8045              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8046        } else {
8047          $self->{set_nc}->($self);
8048        }
8049      
8050            redo A;
8051          }
8052        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE) {
8053          if ($self->{nc} == 0x0022) { # "
8054            $self->{state} = AFTER_MD_DEF_STATE;
8055            
8056        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8057          $self->{line_prev} = $self->{line};
8058          $self->{column_prev} = $self->{column};
8059          $self->{column}++;
8060          $self->{nc}
8061              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8062        } else {
8063          $self->{set_nc}->($self);
8064        }
8065      
8066            redo A;
8067          } elsif ($self->{nc} == 0x0026) { # &
8068            $self->{prev_state} = $self->{state};
8069            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
8070            $self->{entity_add} = 0x0022; # "
8071            
8072        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8073          $self->{line_prev} = $self->{line};
8074          $self->{column_prev} = $self->{column};
8075          $self->{column}++;
8076          $self->{nc}
8077              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8078        } else {
8079          $self->{set_nc}->($self);
8080        }
8081      
8082            redo A;
8083    ## TODO: %
8084          } elsif ($self->{nc} == -1) {
8085            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
8086            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8087            ## Reconsume.
8088            return  ($self->{ct}); # ENTITY
8089            redo A;
8090          } else {
8091            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
8092            
8093        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8094          $self->{line_prev} = $self->{line};
8095          $self->{column_prev} = $self->{column};
8096          $self->{column}++;
8097          $self->{nc}
8098              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8099        } else {
8100          $self->{set_nc}->($self);
8101        }
8102      
8103            redo A;
8104          }
8105        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE) {
8106          if ($self->{nc} == 0x0027) { # '
8107            $self->{state} = AFTER_MD_DEF_STATE;
8108            
8109        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8110          $self->{line_prev} = $self->{line};
8111          $self->{column_prev} = $self->{column};
8112          $self->{column}++;
8113          $self->{nc}
8114              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8115        } else {
8116          $self->{set_nc}->($self);
8117        }
8118      
8119            redo A;
8120          } elsif ($self->{nc} == 0x0026) { # &
8121            $self->{prev_state} = $self->{state};
8122            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
8123            $self->{entity_add} = 0x0027; # '
8124            
8125        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8126          $self->{line_prev} = $self->{line};
8127          $self->{column_prev} = $self->{column};
8128          $self->{column}++;
8129          $self->{nc}
8130              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8131        } else {
8132          $self->{set_nc}->($self);
8133        }
8134      
8135            redo A;
8136    ## TODO: %
8137          } elsif ($self->{nc} == -1) {
8138            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
8139            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8140            ## Reconsume.
8141            return  ($self->{ct}); # ENTITY
8142            redo A;
8143          } else {
8144            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
8145            
8146        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8147          $self->{line_prev} = $self->{line};
8148          $self->{column_prev} = $self->{column};
8149          $self->{column}++;
8150          $self->{nc}
8151              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8152        } else {
8153          $self->{set_nc}->($self);
8154        }
8155      
8156            redo A;
8157          }
8158        } elsif ($self->{state} == ENTITY_VALUE_ENTITY_STATE) {
8159          if ($is_space->{$self->{nc}} or
8160              {
8161                0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
8162                $self->{entity_add} => 1,
8163              }->{$self->{nc}}) {
8164            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
8165                            line => $self->{line_prev},
8166                            column => $self->{column_prev}
8167                                + ($self->{nc} == -1 ? 1 : 0));
8168            ## Don't consume
8169            ## Return nothing.
8170            #
8171          } elsif ($self->{nc} == 0x0023) { # #
8172            $self->{ca} = $self->{ct};
8173            $self->{state} = ENTITY_HASH_STATE;
8174            $self->{kwd} = '#';
8175            
8176        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8177          $self->{line_prev} = $self->{line};
8178          $self->{column_prev} = $self->{column};
8179          $self->{column}++;
8180          $self->{nc}
8181              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8182        } else {
8183          $self->{set_nc}->($self);
8184        }
8185      
8186            redo A;
8187          } else {
8188            #
8189          }
8190    
8191          $self->{ct}->{value} .= '&';
8192          $self->{state} = $self->{prev_state};
8193          ## Reconsume.
8194          redo A;
8195        } elsif ($self->{state} == AFTER_ELEMENT_NAME_STATE) {
8196          if ($is_space->{$self->{nc}}) {
8197            $self->{state} = BEFORE_ELEMENT_CONTENT_STATE;
8198            
8199        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8200          $self->{line_prev} = $self->{line};
8201          $self->{column_prev} = $self->{column};
8202          $self->{column}++;
8203          $self->{nc}
8204              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8205        } else {
8206          $self->{set_nc}->($self);
8207        }
8208      
8209            redo A;
8210          } elsif ($self->{nc} == 0x0028) { # (
8211            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8212            $self->{ct}->{content} = ['('];
8213            $self->{group_depth} = 1;
8214            
8215        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8216          $self->{line_prev} = $self->{line};
8217          $self->{column_prev} = $self->{column};
8218          $self->{column}++;
8219          $self->{nc}
8220              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8221        } else {
8222          $self->{set_nc}->($self);
8223        }
8224      
8225            redo A;
8226          } elsif ($self->{nc} == 0x003E) { # >
8227            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
8228            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8229            
8230        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8231          $self->{line_prev} = $self->{line};
8232          $self->{column_prev} = $self->{column};
8233          $self->{column}++;
8234          $self->{nc}
8235              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8236        } else {
8237          $self->{set_nc}->($self);
8238        }
8239      
8240            return  ($self->{ct}); # ELEMENT
8241            redo A;
8242          } elsif ($self->{nc} == -1) {
8243            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8244            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8245            
8246        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8247          $self->{line_prev} = $self->{line};
8248          $self->{column_prev} = $self->{column};
8249          $self->{column}++;
8250          $self->{nc}
8251              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8252        } else {
8253          $self->{set_nc}->($self);
8254        }
8255      
8256            return  ($self->{ct}); # ELEMENT
8257            redo A;
8258          } else {
8259            $self->{ct}->{content} = [chr $self->{nc}];
8260            $self->{state} = CONTENT_KEYWORD_STATE;
8261            
8262        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8263          $self->{line_prev} = $self->{line};
8264          $self->{column_prev} = $self->{column};
8265          $self->{column}++;
8266          $self->{nc}
8267              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8268        } else {
8269          $self->{set_nc}->($self);
8270        }
8271      
8272            redo A;
8273          }
8274        } elsif ($self->{state} == CONTENT_KEYWORD_STATE) {
8275          if ($is_space->{$self->{nc}}) {
8276            $self->{state} = AFTER_MD_DEF_STATE;
8277            
8278        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8279          $self->{line_prev} = $self->{line};
8280          $self->{column_prev} = $self->{column};
8281          $self->{column}++;
8282          $self->{nc}
8283              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8284        } else {
8285          $self->{set_nc}->($self);
8286        }
8287      
8288            redo A;
8289          } elsif ($self->{nc} == 0x003E) { # >
8290            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8291            
8292        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8293          $self->{line_prev} = $self->{line};
8294          $self->{column_prev} = $self->{column};
8295          $self->{column}++;
8296          $self->{nc}
8297              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8298        } else {
8299          $self->{set_nc}->($self);
8300        }
8301      
8302            return  ($self->{ct}); # ELEMENT
8303            redo A;
8304          } elsif ($self->{nc} == -1) {
8305            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8306            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8307            
8308        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8309          $self->{line_prev} = $self->{line};
8310          $self->{column_prev} = $self->{column};
8311          $self->{column}++;
8312          $self->{nc}
8313              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8314        } else {
8315          $self->{set_nc}->($self);
8316        }
8317      
8318            return  ($self->{ct}); # ELEMENT
8319            redo A;
8320          } else {
8321            $self->{ct}->{content}->[-1] .= chr $self->{nc}; # ELEMENT
8322            ## Stay in the state.
8323            
8324        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8325          $self->{line_prev} = $self->{line};
8326          $self->{column_prev} = $self->{column};
8327          $self->{column}++;
8328          $self->{nc}
8329              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8330        } else {
8331          $self->{set_nc}->($self);
8332        }
8333      
8334            redo A;
8335          }
8336        } elsif ($self->{state} == AFTER_CM_GROUP_OPEN_STATE) {
8337          if ($is_space->{$self->{nc}}) {
8338            ## Stay in the state.
8339            
8340        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8341          $self->{line_prev} = $self->{line};
8342          $self->{column_prev} = $self->{column};
8343          $self->{column}++;
8344          $self->{nc}
8345              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8346        } else {
8347          $self->{set_nc}->($self);
8348        }
8349      
8350            redo A;
8351          } elsif ($self->{nc} == 0x0028) { # (
8352            $self->{group_depth}++;
8353            push @{$self->{ct}->{content}}, chr $self->{nc};
8354            ## Stay in the state.
8355            
8356        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8357          $self->{line_prev} = $self->{line};
8358          $self->{column_prev} = $self->{column};
8359          $self->{column}++;
8360          $self->{nc}
8361              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8362        } else {
8363          $self->{set_nc}->($self);
8364        }
8365      
8366            redo A;
8367          } elsif ($self->{nc} == 0x007C or # |
8368                   $self->{nc} == 0x002C) { # ,
8369            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8370            ## Stay in the state.
8371            
8372        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8373          $self->{line_prev} = $self->{line};
8374          $self->{column_prev} = $self->{column};
8375          $self->{column}++;
8376          $self->{nc}
8377              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8378        } else {
8379          $self->{set_nc}->($self);
8380        }
8381      
8382            redo A;
8383          } elsif ($self->{nc} == 0x0029) { # )
8384            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8385            push @{$self->{ct}->{content}}, chr $self->{nc};
8386            $self->{group_depth}--;
8387            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8388            
8389        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8390          $self->{line_prev} = $self->{line};
8391          $self->{column_prev} = $self->{column};
8392          $self->{column}++;
8393          $self->{nc}
8394              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8395        } else {
8396          $self->{set_nc}->($self);
8397        }
8398      
8399            redo A;
8400          } elsif ($self->{nc} == 0x003E) { # >
8401            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8402            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8403            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8404            
8405        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8406          $self->{line_prev} = $self->{line};
8407          $self->{column_prev} = $self->{column};
8408          $self->{column}++;
8409          $self->{nc}
8410              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8411        } else {
8412          $self->{set_nc}->($self);
8413        }
8414      
8415            return  ($self->{ct}); # ELEMENT
8416            redo A;
8417          } elsif ($self->{nc} == -1) {
8418            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8419            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8420            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8421            
8422        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8423          $self->{line_prev} = $self->{line};
8424          $self->{column_prev} = $self->{column};
8425          $self->{column}++;
8426          $self->{nc}
8427              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8428        } else {
8429          $self->{set_nc}->($self);
8430        }
8431      
8432            return  ($self->{ct}); # ELEMENT
8433            redo A;
8434          } else {
8435            push @{$self->{ct}->{content}}, chr $self->{nc};
8436            $self->{state} = CM_ELEMENT_NAME_STATE;
8437            
8438        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8439          $self->{line_prev} = $self->{line};
8440          $self->{column_prev} = $self->{column};
8441          $self->{column}++;
8442          $self->{nc}
8443              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8444        } else {
8445          $self->{set_nc}->($self);
8446        }
8447      
8448            redo A;
8449          }
8450        } elsif ($self->{state} == CM_ELEMENT_NAME_STATE) {
8451          if ($is_space->{$self->{nc}}) {
8452            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8453            
8454        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8455          $self->{line_prev} = $self->{line};
8456          $self->{column_prev} = $self->{column};
8457          $self->{column}++;
8458          $self->{nc}
8459              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8460        } else {
8461          $self->{set_nc}->($self);
8462        }
8463      
8464            redo A;
8465          } elsif ($self->{nc} == 0x002A or # *
8466                   $self->{nc} == 0x002B or # +
8467                   $self->{nc} == 0x003F) { # ?
8468            push @{$self->{ct}->{content}}, chr $self->{nc};
8469            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8470            
8471        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8472          $self->{line_prev} = $self->{line};
8473          $self->{column_prev} = $self->{column};
8474          $self->{column}++;
8475          $self->{nc}
8476              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8477        } else {
8478          $self->{set_nc}->($self);
8479        }
8480      
8481            redo A;
8482          } elsif ($self->{nc} == 0x007C or # |
8483                   $self->{nc} == 0x002C) { # ,
8484            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8485            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8486            
8487        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8488          $self->{line_prev} = $self->{line};
8489          $self->{column_prev} = $self->{column};
8490          $self->{column}++;
8491          $self->{nc}
8492              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8493        } else {
8494          $self->{set_nc}->($self);
8495        }
8496      
8497            redo A;
8498          } elsif ($self->{nc} == 0x0029) { # )
8499            $self->{group_depth}--;
8500            push @{$self->{ct}->{content}}, chr $self->{nc};
8501            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8502            
8503        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8504          $self->{line_prev} = $self->{line};
8505          $self->{column_prev} = $self->{column};
8506          $self->{column}++;
8507          $self->{nc}
8508              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8509        } else {
8510          $self->{set_nc}->($self);
8511        }
8512      
8513            redo A;
8514          } elsif ($self->{nc} == 0x003E) { # >
8515            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8516            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8517            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8518            
8519        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8520          $self->{line_prev} = $self->{line};
8521          $self->{column_prev} = $self->{column};
8522          $self->{column}++;
8523          $self->{nc}
8524              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8525        } else {
8526          $self->{set_nc}->($self);
8527        }
8528      
8529            return  ($self->{ct}); # ELEMENT
8530            redo A;
8531          } elsif ($self->{nc} == -1) {
8532            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8533            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8534            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8535            
8536        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8537          $self->{line_prev} = $self->{line};
8538          $self->{column_prev} = $self->{column};
8539          $self->{column}++;
8540          $self->{nc}
8541              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8542        } else {
8543          $self->{set_nc}->($self);
8544        }
8545      
8546            return  ($self->{ct}); # ELEMENT
8547            redo A;
8548          } else {
8549            $self->{ct}->{content}->[-1] .= chr $self->{nc};
8550            ## Stay in the state.
8551            
8552        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8553          $self->{line_prev} = $self->{line};
8554          $self->{column_prev} = $self->{column};
8555          $self->{column}++;
8556          $self->{nc}
8557              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8558        } else {
8559          $self->{set_nc}->($self);
8560        }
8561      
8562            redo A;
8563          }
8564        } elsif ($self->{state} == AFTER_CM_ELEMENT_NAME_STATE) {
8565          if ($is_space->{$self->{nc}}) {
8566            ## Stay in the state.
8567            
8568        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8569          $self->{line_prev} = $self->{line};
8570          $self->{column_prev} = $self->{column};
8571          $self->{column}++;
8572          $self->{nc}
8573              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8574        } else {
8575          $self->{set_nc}->($self);
8576        }
8577      
8578            redo A;
8579          } elsif ($self->{nc} == 0x007C or # |
8580                   $self->{nc} == 0x002C) { # ,
8581            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8582            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8583            
8584        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8585          $self->{line_prev} = $self->{line};
8586          $self->{column_prev} = $self->{column};
8587          $self->{column}++;
8588          $self->{nc}
8589              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8590        } else {
8591          $self->{set_nc}->($self);
8592        }
8593      
8594            redo A;
8595          } elsif ($self->{nc} == 0x0029) { # )
8596            $self->{group_depth}--;
8597            push @{$self->{ct}->{content}}, chr $self->{nc};
8598            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8599            
8600        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8601          $self->{line_prev} = $self->{line};
8602          $self->{column_prev} = $self->{column};
8603          $self->{column}++;
8604          $self->{nc}
8605              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8606        } else {
8607          $self->{set_nc}->($self);
8608        }
8609      
8610            redo A;
8611          } elsif ($self->{nc} == 0x003E) { # >
8612            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8613            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8614            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8615            
8616        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8617          $self->{line_prev} = $self->{line};
8618          $self->{column_prev} = $self->{column};
8619          $self->{column}++;
8620          $self->{nc}
8621              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8622        } else {
8623          $self->{set_nc}->($self);
8624        }
8625      
8626            return  ($self->{ct}); # ELEMENT
8627            redo A;
8628          } elsif ($self->{nc} == -1) {
8629            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8630            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8631            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8632            
8633        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8634          $self->{line_prev} = $self->{line};
8635          $self->{column_prev} = $self->{column};
8636          $self->{column}++;
8637          $self->{nc}
8638              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8639        } else {
8640          $self->{set_nc}->($self);
8641        }
8642      
8643            return  ($self->{ct}); # ELEMENT
8644            redo A;
8645          } else {
8646            $self->{parse_error}->(level => $self->{level}->{must}, type => 'after element name'); ## TODO: type
8647            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8648            $self->{state} = BOGUS_MD_STATE;
8649            
8650        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8651          $self->{line_prev} = $self->{line};
8652          $self->{column_prev} = $self->{column};
8653          $self->{column}++;
8654          $self->{nc}
8655              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8656        } else {
8657          $self->{set_nc}->($self);
8658        }
8659      
8660            redo A;
8661          }
8662        } elsif ($self->{state} == AFTER_CM_GROUP_CLOSE_STATE) {
8663          if ($is_space->{$self->{nc}}) {
8664            if ($self->{group_depth}) {
8665              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8666            } else {
8667              $self->{state} = AFTER_MD_DEF_STATE;
8668            }
8669            
8670        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8671          $self->{line_prev} = $self->{line};
8672          $self->{column_prev} = $self->{column};
8673          $self->{column}++;
8674          $self->{nc}
8675              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8676        } else {
8677          $self->{set_nc}->($self);
8678        }
8679      
8680            redo A;
8681          } elsif ($self->{nc} == 0x002A or # *
8682                   $self->{nc} == 0x002B or # +
8683                   $self->{nc} == 0x003F) { # ?
8684            push @{$self->{ct}->{content}}, chr $self->{nc};
8685            if ($self->{group_depth}) {
8686              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8687            } else {
8688              $self->{state} = AFTER_MD_DEF_STATE;
8689            }
8690            
8691        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8692          $self->{line_prev} = $self->{line};
8693          $self->{column_prev} = $self->{column};
8694          $self->{column}++;
8695          $self->{nc}
8696              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8697        } else {
8698          $self->{set_nc}->($self);
8699        }
8700      
8701            redo A;
8702          } elsif ($self->{nc} == 0x0029) { # )
8703            if ($self->{group_depth}) {
8704              $self->{group_depth}--;
8705              push @{$self->{ct}->{content}}, chr $self->{nc};
8706              ## Stay in the state.
8707              
8708        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8709          $self->{line_prev} = $self->{line};
8710          $self->{column_prev} = $self->{column};
8711          $self->{column}++;
8712          $self->{nc}
8713              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8714        } else {
8715          $self->{set_nc}->($self);
8716        }
8717      
8718              redo A;
8719            } else {
8720              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8721              $self->{state} = BOGUS_MD_STATE;
8722              ## Reconsume.
8723              redo A;
8724            }
8725          } elsif ($self->{nc} == 0x003E) { # >
8726            if ($self->{group_depth}) {
8727              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8728              push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8729            }
8730            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8731            
8732        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8733          $self->{line_prev} = $self->{line};
8734          $self->{column_prev} = $self->{column};
8735          $self->{column}++;
8736          $self->{nc}
8737              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8738        } else {
8739          $self->{set_nc}->($self);
8740        }
8741      
8742            return  ($self->{ct}); # ELEMENT
8743            redo A;
8744          } elsif ($self->{nc} == -1) {
8745            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8746            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8747            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8748            
8749        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8750          $self->{line_prev} = $self->{line};
8751          $self->{column_prev} = $self->{column};
8752          $self->{column}++;
8753          $self->{nc}
8754              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8755        } else {
8756          $self->{set_nc}->($self);
8757        }
8758      
8759            return  ($self->{ct}); # ELEMENT
8760            redo A;
8761          } else {
8762            if ($self->{group_depth}) {
8763              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8764            } else {
8765              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8766              $self->{state} = BOGUS_MD_STATE;
8767            }
8768            ## Reconsume.
8769            redo A;
8770          }
8771        } elsif ($self->{state} == AFTER_MD_DEF_STATE) {
8772          if ($is_space->{$self->{nc}}) {
8773            ## Stay in the state.
8774            
8775        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8776          $self->{line_prev} = $self->{line};
8777          $self->{column_prev} = $self->{column};
8778          $self->{column}++;
8779          $self->{nc}
8780              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8781        } else {
8782          $self->{set_nc}->($self);
8783        }
8784      
8785            redo A;
8786          } elsif ($self->{nc} == 0x003E) { # >
8787            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8788            
8789        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8790          $self->{line_prev} = $self->{line};
8791          $self->{column_prev} = $self->{column};
8792          $self->{column}++;
8793          $self->{nc}
8794              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8795        } else {
8796          $self->{set_nc}->($self);
8797        }
8798      
8799            return  ($self->{ct}); # ENTITY/ELEMENT
8800            redo A;
8801          } elsif ($self->{nc} == -1) {
8802            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8803            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8804            
8805        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8806          $self->{line_prev} = $self->{line};
8807          $self->{column_prev} = $self->{column};
8808          $self->{column}++;
8809          $self->{nc}
8810              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8811        } else {
8812          $self->{set_nc}->($self);
8813        }
8814      
8815            return  ($self->{ct}); # ENTITY/ELEMENT
8816            redo A;
8817          } else {
8818            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8819            $self->{state} = BOGUS_MD_STATE;
8820            ## Reconsume.
8821            redo A;
8822          }
8823        } elsif ($self->{state} == BOGUS_MD_STATE) {
8824          if ($self->{nc} == 0x003E) { # >
8825            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8826            
8827        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8828          $self->{line_prev} = $self->{line};
8829          $self->{column_prev} = $self->{column};
8830          $self->{column}++;
8831          $self->{nc}
8832              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8833        } else {
8834          $self->{set_nc}->($self);
8835        }
8836      
8837            return  ($self->{ct}); # ATTLIST/ENTITY/NOTATION
8838            redo A;
8839          } elsif ($self->{nc} == -1) {
8840            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8841            ## Reconsume.
8842            return  ($self->{ct}); # ATTLIST/ENTITY/NOTATION
8843            redo A;
8844          } else {
8845            ## Stay in the state.
8846            
8847        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8848          $self->{line_prev} = $self->{line};
8849          $self->{column_prev} = $self->{column};
8850          $self->{column}++;
8851          $self->{nc}
8852              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8853        } else {
8854          $self->{set_nc}->($self);
8855        }
8856      
8857            redo A;
8858          }
8859      } else {      } else {
8860        die "$0: $self->{state}: Unknown state";        die "$0: $self->{state}: Unknown state";
8861      }      }

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24