/[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.18 by wakaba, Sun Oct 19 06:14:57 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 182  sub NDATA_STATE () { 86 } Line 184  sub NDATA_STATE () { 86 }
184  sub AFTER_NDATA_STATE () { 87 }  sub AFTER_NDATA_STATE () { 87 }
185  sub BEFORE_NOTATION_NAME_STATE () { 88 }  sub BEFORE_NOTATION_NAME_STATE () { 88 }
186  sub NOTATION_NAME_STATE () { 89 }  sub NOTATION_NAME_STATE () { 89 }
187  sub AFTER_NOTATION_NAME_STATE () { 90 }  sub DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE () { 90 }
188  sub BOGUS_MD_STATE () { 91 }  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 1090  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 1231  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 1416  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 1580  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 1592  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 1726  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 1806  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 1830  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 1853  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 1920  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 1929  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 1944  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 1967  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 2106  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 2122  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 2139  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 2148  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 2248  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 2315  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 2890  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 2918  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 2947  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 2973  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 2989  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 3036  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 3122  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 3153  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 3262  sub _get_next_token ($) { Line 3514  sub _get_next_token ($) {
3514      }      }
3515        
3516          redo A;          redo A;
3517  ## TODO: " and ' for ENTITY        } 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        } elsif ($self->{is_xml} and
3554                 $self->{ct}->{type} == DOCTYPE_TOKEN and                 $self->{ct}->{type} == DOCTYPE_TOKEN and
3555                 $self->{nc} == 0x005B) { # [                 $self->{nc} == 0x005B) { # [
# Line 4583  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 4604  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 4658  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 4765  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 4918  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 4952  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 5362  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 5796  sub _get_next_token ($) { Line 6157  sub _get_next_token ($) {
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 5864  sub _get_next_token ($) { Line 6225  sub _get_next_token ($) {
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 5933  sub _get_next_token ($) { Line 6294  sub _get_next_token ($) {
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 6145  sub _get_next_token ($) { Line 6506  sub _get_next_token ($) {
6506          if ($self->{ct}->{type} == ATTLIST_TOKEN) {          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) {          } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
6509            ## TODO: ...            $self->{state} = AFTER_ELEMENT_NAME_STATE;
           $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;  
6510          } else { # ENTITY/NOTATION          } else { # ENTITY/NOTATION
6511            $self->{state} = AFTER_DOCTYPE_NAME_STATE;            $self->{state} = AFTER_DOCTYPE_NAME_STATE;
6512          }          }
# Line 7629  sub _get_next_token ($) { Line 7989  sub _get_next_token ($) {
7989        }        }
7990      } elsif ($self->{state} == NOTATION_NAME_STATE) {      } elsif ($self->{state} == NOTATION_NAME_STATE) {
7991        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
7992          $self->{state} = AFTER_NOTATION_NAME_STATE;          $self->{state} = AFTER_MD_DEF_STATE;
7993                    
7994      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7995        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 7689  sub _get_next_token ($) { Line 8049  sub _get_next_token ($) {
8049        
8050          redo A;          redo A;
8051        }        }
8052      } elsif ($self->{state} == AFTER_NOTATION_NAME_STATE) {      } 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}}) {        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.          ## Stay in the state.
8371                    
8372      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 7704  sub _get_next_token ($) { Line 8380  sub _get_next_token ($) {
8380      }      }
8381        
8382          redo A;          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) { # >        } 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;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8404                    
8405      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 7717  sub _get_next_token ($) { Line 8412  sub _get_next_token ($) {
8412        $self->{set_nc}->($self);        $self->{set_nc}->($self);
8413      }      }
8414        
8415          return  ($self->{ct}); # ENTITY          return  ($self->{ct}); # ELEMENT
8416          redo A;          redo A;
8417        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
8418          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type          $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;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8421                    
8422      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 7733  sub _get_next_token ($) { Line 8429  sub _get_next_token ($) {
8429        $self->{set_nc}->($self);        $self->{set_nc}->($self);
8430      }      }
8431        
8432          return  ($self->{ct}); # ENTITY          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;          redo A;
8548        } else {        } else {
8549          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after notation name'); ## TODO: type          $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;          $self->{state} = BOGUS_MD_STATE;
8820          ## Reconsume.          ## Reconsume.
8821          redo A;          redo A;
8822        }        }
   
   
8823      } elsif ($self->{state} == BOGUS_MD_STATE) {      } elsif ($self->{state} == BOGUS_MD_STATE) {
8824        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
8825          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24