/[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.27 by wakaba, Thu Jul 2 22:24:28 2009 UTC
# Line 177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO Line 177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO
177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }
178  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }
179  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }
180    sub BEFORE_NDATA_STATE () { 85 }
181    sub NDATA_STATE () { 86 }
182    sub AFTER_NDATA_STATE () { 87 }
183    sub BEFORE_NOTATION_NAME_STATE () { 88 }
184    sub NOTATION_NAME_STATE () { 89 }
185    sub DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE () { 90 }
186    sub DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE () { 91 }
187    sub ENTITY_VALUE_ENTITY_STATE () { 92 }
188    sub AFTER_ELEMENT_NAME_STATE () { 93 }
189    sub BEFORE_ELEMENT_CONTENT_STATE () { 94 }
190    sub CONTENT_KEYWORD_STATE () { 95 }
191    sub AFTER_CM_GROUP_OPEN_STATE () { 96 }
192    sub CM_ELEMENT_NAME_STATE () { 97 }
193    sub AFTER_CM_ELEMENT_NAME_STATE () { 98 }
194    sub AFTER_CM_GROUP_CLOSE_STATE () { 99 }
195    sub AFTER_MD_DEF_STATE () { 100 }
196    sub BOGUS_MD_STATE () { 101 }
197    
198  ## Tree constructor state constants (see Whatpm::HTML for the full  ## Tree constructor state constants (see Whatpm::HTML for the full
199  ## list and descriptions)  ## list and descriptions)
# Line 1723  sub _get_next_token ($) { Line 1740  sub _get_next_token ($) {
1740    
1741          redo A;          redo A;
1742        } else {        } else {
1743          if ($self->{nc} == 0x003D) { # =          if ($self->{nc} == 0x003D or $self->{nc} == 0x003C) { # =, <
1744                        
1745            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1746            $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 1816  sub _get_next_token ($) {
1816      }      }
1817        
1818          redo A;          redo A;
1819          } elsif ($self->{is_xml} and
1820                   $is_space->{$self->{nc}}) {
1821            
1822            $self->{ca}->{value} .= ' ';
1823            ## Stay in the state.
1824            
1825        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1826          $self->{line_prev} = $self->{line};
1827          $self->{column_prev} = $self->{column};
1828          $self->{column}++;
1829          $self->{nc}
1830              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1831        } else {
1832          $self->{set_nc}->($self);
1833        }
1834      
1835            redo A;
1836        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1837          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1838          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1846  sub _get_next_token ($) { Line 1880  sub _get_next_token ($) {
1880          }          }
1881          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1882          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1883                                q["&<],                                qq["&<\x09\x0C\x20],
1884                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1885    
1886          ## Stay in the state          ## Stay in the state
# Line 1913  sub _get_next_token ($) { Line 1947  sub _get_next_token ($) {
1947      }      }
1948        
1949          redo A;          redo A;
1950          } elsif ($self->{is_xml} and
1951                   $is_space->{$self->{nc}}) {
1952            
1953            $self->{ca}->{value} .= ' ';
1954            ## Stay in the state.
1955            
1956        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1957          $self->{line_prev} = $self->{line};
1958          $self->{column_prev} = $self->{column};
1959          $self->{column}++;
1960          $self->{nc}
1961              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1962        } else {
1963          $self->{set_nc}->($self);
1964        }
1965      
1966            redo A;
1967        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1968          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1969          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1960  sub _get_next_token ($) { Line 2011  sub _get_next_token ($) {
2011          }          }
2012          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2013          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2014                                q['&<],                                qq['&<\x09\x0C\x20],
2015                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2016    
2017          ## Stay in the state          ## Stay in the state
# Line 2132  sub _get_next_token ($) { Line 2183  sub _get_next_token ($) {
2183               0x0022 => 1, # "               0x0022 => 1, # "
2184               0x0027 => 1, # '               0x0027 => 1, # '
2185               0x003D => 1, # =               0x003D => 1, # =
2186                 0x003C => 1, # <
2187              }->{$self->{nc}}) {              }->{$self->{nc}}) {
2188                        
2189            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 2141  sub _get_next_token ($) { Line 2193  sub _get_next_token ($) {
2193          }          }
2194          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2195          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2196                                q["'=& >],                                qq["'=& \x09\x0C>],
2197                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2198    
2199          ## Stay in the state          ## Stay in the state
# Line 2947  sub _get_next_token ($) { Line 2999  sub _get_next_token ($) {
2999          redo A;          redo A;
3000        } else {        } else {
3001                    
         ## XML5: Not a parse error.  
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',  
                         line => $self->{line_prev},  
                         column => $self->{column_prev});  
3002          $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment          $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
3003          $self->{state} = COMMENT_STATE;          $self->{state} = COMMENT_STATE;
3004                    
# Line 3182  sub _get_next_token ($) { Line 3230  sub _get_next_token ($) {
3230        
3231          redo A;          redo A;
3232        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
3233            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3234              
3235              $self->{state} = DATA_STATE;
3236              $self->{s_kwd} = '';
3237            } else {
3238              
3239              $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
3240              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3241            }
3242                    
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3243                    
3244      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3245        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3196  sub _get_next_token ($) { Line 3251  sub _get_next_token ($) {
3251        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3252      }      }
3253        
3254            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
3255          redo A;          redo A;
3256        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3257            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3258              
3259              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3260              $self->{state} = DATA_STATE;
3261              $self->{s_kwd} = '';
3262              $self->{ct}->{quirks} = 1;
3263            } else {
3264              
3265              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3266              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3267            }
3268                    
3269          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');          ## Reconsume.
3270          $self->{state} = DATA_STATE;          return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{s_kwd} = '';  
         ## reconsume  
   
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3271          redo A;          redo A;
3272        } elsif ($self->{nc} == 0x0050 or # P        } elsif ($self->{nc} == 0x0050 or # P
3273                 $self->{nc} == 0x0070) { # p                 $self->{nc} == 0x0070) { # p
# Line 3245  sub _get_next_token ($) { Line 3303  sub _get_next_token ($) {
3303      }      }
3304        
3305          redo A;          redo A;
3306        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{nc} == 0x0022 and # "
3307                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3308                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3309            
3310            $self->{state} = DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE;
3311            $self->{ct}->{value} = ''; # ENTITY
3312            
3313        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3314          $self->{line_prev} = $self->{line};
3315          $self->{column_prev} = $self->{column};
3316          $self->{column}++;
3317          $self->{nc}
3318              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3319        } else {
3320          $self->{set_nc}->($self);
3321        }
3322      
3323            redo A;
3324          } elsif ($self->{nc} == 0x0027 and # '
3325                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3326                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3327            
3328            $self->{state} = DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE;
3329            $self->{ct}->{value} = ''; # ENTITY
3330            
3331        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3332          $self->{line_prev} = $self->{line};
3333          $self->{column_prev} = $self->{column};
3334          $self->{column}++;
3335          $self->{nc}
3336              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3337        } else {
3338          $self->{set_nc}->($self);
3339        }
3340      
3341            redo A;
3342          } elsif ($self->{is_xml} and
3343                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3344                   $self->{nc} == 0x005B) { # [
3345                    
3346          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3347          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 3264  sub _get_next_token ($) { Line 3360  sub _get_next_token ($) {
3360          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3361          redo A;          redo A;
3362        } else {        } else {
3363                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name'); ## TODO: type
3364          $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after DOCTYPE name');  
3365          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3366              
3367              $self->{ct}->{quirks} = 1;
3368              $self->{state} = BOGUS_DOCTYPE_STATE;
3369            } else {
3370              
3371              $self->{state} = BOGUS_MD_STATE;
3372            }
3373    
         $self->{state} = BOGUS_DOCTYPE_STATE;  
3374                    
3375      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3376        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3340  sub _get_next_token ($) { Line 3442  sub _get_next_token ($) {
3442        
3443          redo A;          redo A;
3444        } else {        } else {
3445                    $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',  
3446                          line => $self->{line_prev},                          line => $self->{line_prev},
3447                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3448          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3449              
3450          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3451              $self->{state} = BOGUS_DOCTYPE_STATE;
3452            } else {
3453              
3454              $self->{state} = BOGUS_MD_STATE;
3455            }
3456          ## Reconsume.          ## Reconsume.
3457          redo A;          redo A;
3458        }        }
# Line 3408  sub _get_next_token ($) { Line 3514  sub _get_next_token ($) {
3514        
3515          redo A;          redo A;
3516        } else {        } else {
3517                    $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',  
3518                          line => $self->{line_prev},                          line => $self->{line_prev},
3519                          column => $self->{column_prev} + 1 - length $self->{kwd});                          column => $self->{column_prev} + 1 - length $self->{kwd});
3520          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3521              
3522          $self->{state} = BOGUS_DOCTYPE_STATE;            $self->{ct}->{quirks} = 1;
3523              $self->{state} = BOGUS_DOCTYPE_STATE;
3524            } else {
3525              
3526              $self->{state} = BOGUS_MD_STATE;
3527            }
3528          ## Reconsume.          ## Reconsume.
3529          redo A;          redo A;
3530        }        }
# Line 3467  sub _get_next_token ($) { Line 3577  sub _get_next_token ($) {
3577        
3578          redo A;          redo A;
3579        } elsif ($self->{nc} eq 0x003E) { # >        } elsif ($self->{nc} eq 0x003E) { # >
           
3580          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3581            
3582          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3583          $self->{s_kwd} = '';            
3584              $self->{state} = DATA_STATE;
3585              $self->{s_kwd} = '';
3586              $self->{ct}->{quirks} = 1;
3587            } else {
3588              
3589              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3590            }
3591            
3592                    
3593      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3594        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3483  sub _get_next_token ($) { Line 3600  sub _get_next_token ($) {
3600        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3601      }      }
3602        
3603            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3604          redo A;          redo A;
3605        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3606            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3607              
3608              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3609              $self->{state} = DATA_STATE;
3610              $self->{s_kwd} = '';
3611              $self->{ct}->{quirks} = 1;
3612            } else {
3613              
3614              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3615              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3616            }
3617                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3618          ## reconsume          ## reconsume
   
         $self->{ct}->{quirks} = 1;  
3619          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3620          redo A;          redo A;
3621        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
3622                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3623                   $self->{nc} == 0x005B) { # [
3624                    
3625          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no PUBLIC literal');
3626          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3520  sub _get_next_token ($) { Line 3640  sub _get_next_token ($) {
3640          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3641          redo A;          redo A;
3642        } else {        } else {
           
3643          $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;  
3644    
3645          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3646              
3647              $self->{ct}->{quirks} = 1;
3648              $self->{state} = BOGUS_DOCTYPE_STATE;
3649            } else {
3650              
3651              $self->{state} = BOGUS_MD_STATE;
3652            }
3653    
3654                    
3655      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3656        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3555  sub _get_next_token ($) { Line 3681  sub _get_next_token ($) {
3681        
3682          redo A;          redo A;
3683        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3684          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3685    
3686          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3687          $self->{s_kwd} = '';            
3688              $self->{state} = DATA_STATE;
3689              $self->{s_kwd} = '';
3690              $self->{ct}->{quirks} = 1;
3691            } else {
3692              
3693              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3694            }
3695    
3696                    
3697      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3698        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3571  sub _get_next_token ($) { Line 3704  sub _get_next_token ($) {
3704        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3705      }      }
3706        
3707            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3708          redo A;          redo A;
3709        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
3710          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3711    
3712          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3713          $self->{s_kwd} = '';            
3714          ## reconsume            $self->{state} = DATA_STATE;
3715              $self->{s_kwd} = '';
3716          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
3717            } else {
3718              
3719              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3720            }
3721            
3722            ## Reconsume.
3723          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
   
3724          redo A;          redo A;
3725        } else {        } else {
3726                    
3727          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
3728          $self->{read_until}->($self->{ct}->{pubid}, q[">],          $self->{read_until}->($self->{ct}->{pubid}, q[">],
3729                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
3730    
# Line 3626  sub _get_next_token ($) { Line 3759  sub _get_next_token ($) {
3759        
3760          redo A;          redo A;
3761        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
3762          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3763    
3764          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3765          $self->{s_kwd} = '';            
3766              $self->{state} = DATA_STATE;
3767              $self->{s_kwd} = '';
3768              $self->{ct}->{quirks} = 1;
3769            } else {
3770              
3771              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3772            }
3773    
3774                    
3775      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3776        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3642  sub _get_next_token ($) { Line 3782  sub _get_next_token ($) {
3782        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3783      }      }
3784        
3785            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3786          redo A;          redo A;
3787        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
3788          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed PUBLIC literal');
3789    
3790          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3791          $self->{s_kwd} = '';            
3792              $self->{state} = DATA_STATE;
3793              $self->{s_kwd} = '';
3794              $self->{ct}->{quirks} = 1;
3795            } else {
3796              
3797              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3798            }
3799          
3800          ## reconsume          ## reconsume
3801            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3802          redo A;          redo A;
3803        } else {        } else {
3804                    
3805          $self->{ct}->{pubid} # DOCTYPE          $self->{ct}->{pubid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
3806          $self->{read_until}->($self->{ct}->{pubid}, q['>],          $self->{read_until}->($self->{ct}->{pubid}, q['>],
3807                                length $self->{ct}->{pubid});                                length $self->{ct}->{pubid});
3808    
# Line 3698  sub _get_next_token ($) { Line 3838  sub _get_next_token ($) {
3838          redo A;          redo A;
3839        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
3840                    
3841          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
3842          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;
3843                    
3844      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 3854  sub _get_next_token ($) {
3854          redo A;          redo A;
3855        } elsif ($self->{nc} == 0x0027) { # '        } elsif ($self->{nc} == 0x0027) { # '
3856                    
3857          $self->{ct}->{sysid} = ''; # DOCTYPE          $self->{ct}->{sysid} = ''; # DOCTYPE/ENTITY/NOTATION
3858          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;          $self->{state} = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;
3859                    
3860      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 3869  sub _get_next_token ($) {
3869        
3870          redo A;          redo A;
3871        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
3872          if ($self->{is_xml}) {          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3873                        if ($self->{is_xml}) {
3874            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');              
3875                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
3876              } else {
3877                
3878              }
3879              $self->{state} = DATA_STATE;
3880              $self->{s_kwd} = '';
3881          } else {          } else {
3882                        if ($self->{ct}->{type} == NOTATION_TOKEN) {
3883                
3884              } else {
3885                
3886                $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');            
3887              }
3888              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3889          }          }
3890          $self->{state} = DATA_STATE;          
         $self->{s_kwd} = '';  
3891                    
3892      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3893        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3748  sub _get_next_token ($) { Line 3899  sub _get_next_token ($) {
3899        $self->{set_nc}->($self);        $self->{set_nc}->($self);
3900      }      }
3901        
3902            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         return  ($self->{ct}); # DOCTYPE  
   
3903          redo A;          redo A;
3904        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3905            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3906              
3907              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3908              
3909              $self->{state} = DATA_STATE;
3910              $self->{s_kwd} = '';
3911              $self->{ct}->{quirks} = 1;
3912            } else {
3913              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
3914              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3915            }
3916                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
3917          ## reconsume          ## reconsume
3918            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
3919          redo A;          redo A;
3920        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
3921                   $self->{ct}->{type} == DOCTYPE_TOKEN and
3922                   $self->{nc} == 0x005B) { # [
3923                    
3924          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
3925          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
# Line 3784  sub _get_next_token ($) { Line 3939  sub _get_next_token ($) {
3939          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3940          redo A;          redo A;
3941        } else {        } else {
           
3942          $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;  
3943    
3944          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
3945              
3946              $self->{ct}->{quirks} = 1;
3947              $self->{state} = BOGUS_DOCTYPE_STATE;
3948            } else {
3949              
3950              $self->{state} = BOGUS_MD_STATE;
3951            }
3952    
3953                    
3954      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3955        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3851  sub _get_next_token ($) { Line 4012  sub _get_next_token ($) {
4012        
4013          redo A;          redo A;
4014        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
           
4015          $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} = '';  
4016                    
4017      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4018        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3867  sub _get_next_token ($) { Line 4025  sub _get_next_token ($) {
4025      }      }
4026        
4027    
4028          $self->{ct}->{quirks} = 1;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4029          return  ($self->{ct}); # DOCTYPE            
4030              $self->{state} = DATA_STATE;
4031              $self->{s_kwd} = '';
4032              $self->{ct}->{quirks} = 1;
4033            } else {
4034              
4035              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4036            }
4037    
4038            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4039          redo A;          redo A;
4040        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4041            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4042              
4043              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4044              $self->{state} = DATA_STATE;
4045              $self->{s_kwd} = '';
4046              $self->{ct}->{quirks} = 1;
4047            } else {
4048              
4049              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4050              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4051            }
4052                    
         $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');  
   
         $self->{state} = DATA_STATE;  
         $self->{s_kwd} = '';  
4053          ## reconsume          ## reconsume
4054            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4055          redo A;          redo A;
4056        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4057                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4058                   $self->{nc} == 0x005B) { # [
4059                    
4060          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no SYSTEM literal');
4061    
# Line 3904  sub _get_next_token ($) { Line 4076  sub _get_next_token ($) {
4076          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4077          redo A;          redo A;
4078        } else {        } else {
           
4079          $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;  
4080    
4081          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4082                        
4083              $self->{ct}->{quirks} = 1;
4084              $self->{state} = BOGUS_DOCTYPE_STATE;
4085            } else {
4086              
4087              $self->{state} = BOGUS_MD_STATE;
4088            }
4089    
4090                    
4091      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4092        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3939  sub _get_next_token ($) { Line 4117  sub _get_next_token ($) {
4117        
4118          redo A;          redo A;
4119        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >        } elsif (not $self->{is_xml} and $self->{nc} == 0x003E) { # >
           
4120          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4121    
4122          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4123          $self->{s_kwd} = '';            
4124              $self->{state} = DATA_STATE;
4125              $self->{s_kwd} = '';
4126              $self->{ct}->{quirks} = 1;
4127            } else {
4128              
4129              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4130            }
4131            
4132                    
4133      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4134        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3955  sub _get_next_token ($) { Line 4140  sub _get_next_token ($) {
4140        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4141      }      }
4142        
4143            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4144          redo A;          redo A;
4145        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4146          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4147    
4148          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4149          $self->{s_kwd} = '';            
4150              $self->{state} = DATA_STATE;
4151              $self->{s_kwd} = '';
4152              $self->{ct}->{quirks} = 1;
4153            } else {
4154              
4155              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4156            }
4157            
4158          ## reconsume          ## reconsume
4159            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
         $self->{ct}->{quirks} = 1;  
         return  ($self->{ct}); # DOCTYPE  
   
4160          redo A;          redo A;
4161        } else {        } else {
4162                    
4163          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4164          $self->{read_until}->($self->{ct}->{sysid}, q[">],          $self->{read_until}->($self->{ct}->{sysid}, q[">],
4165                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4166    
# Line 4032  sub _get_next_token ($) { Line 4217  sub _get_next_token ($) {
4217    
4218          redo A;          redo A;
4219        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
           
4220          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed SYSTEM literal');
4221    
4222          $self->{state} = DATA_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4223          $self->{s_kwd} = '';            
4224          ## reconsume            $self->{state} = DATA_STATE;
4225              $self->{s_kwd} = '';
4226          $self->{ct}->{quirks} = 1;            $self->{ct}->{quirks} = 1;
4227          return  ($self->{ct}); # DOCTYPE          } else {
4228              
4229              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4230            }
4231    
4232            ## reconsume
4233            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4234          redo A;          redo A;
4235        } else {        } else {
4236                    
4237          $self->{ct}->{sysid} # DOCTYPE          $self->{ct}->{sysid} .= chr $self->{nc}; # DOCTYPE/ENTITY/NOTATION
             .= chr $self->{nc};  
4238          $self->{read_until}->($self->{ct}->{sysid}, q['>],          $self->{read_until}->($self->{ct}->{sysid}, q['>],
4239                                length $self->{ct}->{sysid});                                length $self->{ct}->{sysid});
4240    
# Line 4066  sub _get_next_token ($) { Line 4254  sub _get_next_token ($) {
4254        }        }
4255      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
4256        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
4257                    if ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN) {
4258          ## Stay in the state            
4259              $self->{state} = BEFORE_NDATA_STATE;
4260            } else {
4261              
4262              ## Stay in the state
4263            }
4264                    
4265      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4266        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4081  sub _get_next_token ($) { Line 4274  sub _get_next_token ($) {
4274        
4275          redo A;          redo A;
4276        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
4277            if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4278              
4279              $self->{state} = DATA_STATE;
4280              $self->{s_kwd} = '';
4281            } else {
4282              
4283              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4284            }
4285    
4286                    
4287          $self->{state} = DATA_STATE;      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4288          $self->{s_kwd} = '';        $self->{line_prev} = $self->{line};
4289          $self->{column_prev} = $self->{column};
4290          $self->{column}++;
4291          $self->{nc}
4292              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4293        } else {
4294          $self->{set_nc}->($self);
4295        }
4296      
4297            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4298            redo A;
4299          } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
4300                   ($self->{nc} == 0x004E or # N
4301                    $self->{nc} == 0x006E)) { # n
4302            
4303            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before NDATA'); ## TODO: type
4304            $self->{state} = NDATA_STATE;
4305            $self->{kwd} = chr $self->{nc};
4306                    
4307      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4308        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4095  sub _get_next_token ($) { Line 4314  sub _get_next_token ($) {
4314        $self->{set_nc}->($self);        $self->{set_nc}->($self);
4315      }      }
4316        
   
         return  ($self->{ct}); # DOCTYPE  
   
4317          redo A;          redo A;
4318        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4319                    if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4320          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');            
4321          $self->{state} = DATA_STATE;            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
4322          $self->{s_kwd} = '';            $self->{state} = DATA_STATE;
4323          ## reconsume            $self->{s_kwd} = '';
4324              $self->{ct}->{quirks} = 1;
4325          $self->{ct}->{quirks} = 1;          } else {
4326          return  ($self->{ct}); # DOCTYPE            
4327              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4328              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4329            }
4330    
4331            ## reconsume
4332            return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4333          redo A;          redo A;
4334        } elsif ($self->{is_xml} and $self->{nc} == 0x005B) { # [        } elsif ($self->{is_xml} and
4335                   $self->{ct}->{type} == DOCTYPE_TOKEN and
4336                   $self->{nc} == 0x005B) { # [
4337                    
4338          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4339          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE          $self->{ct}->{has_internal_subset} = 1; # DOCTYPE
# Line 4129  sub _get_next_token ($) { Line 4352  sub _get_next_token ($) {
4352          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
4353          redo A;          redo A;
4354        } else {        } else {
           
4355          $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;  
4356    
4357          $self->{state} = BOGUS_DOCTYPE_STATE;          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4358              
4359              #$self->{ct}->{quirks} = 1;
4360              $self->{state} = BOGUS_DOCTYPE_STATE;
4361            } else {
4362              
4363              $self->{state} = BOGUS_MD_STATE;
4364            }
4365    
4366            
4367        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4368          $self->{line_prev} = $self->{line};
4369          $self->{column_prev} = $self->{column};
4370          $self->{column}++;
4371          $self->{nc}
4372              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4373        } else {
4374          $self->{set_nc}->($self);
4375        }
4376      
4377            redo A;
4378          }
4379        } elsif ($self->{state} == BEFORE_NDATA_STATE) {
4380          if ($is_space->{$self->{nc}}) {
4381            
4382            ## Stay in the state.
4383            
4384        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4385          $self->{line_prev} = $self->{line};
4386          $self->{column_prev} = $self->{column};
4387          $self->{column}++;
4388          $self->{nc}
4389              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4390        } else {
4391          $self->{set_nc}->($self);
4392        }
4393      
4394            redo A;
4395          } elsif ($self->{nc} == 0x003E) { # >
4396            
4397            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4398            
4399        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4400          $self->{line_prev} = $self->{line};
4401          $self->{column_prev} = $self->{column};
4402          $self->{column}++;
4403          $self->{nc}
4404              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4405        } else {
4406          $self->{set_nc}->($self);
4407        }
4408      
4409            return  ($self->{ct}); # ENTITY
4410            redo A;
4411          } elsif ($self->{nc} == 0x004E or # N
4412                   $self->{nc} == 0x006E) { # n
4413            
4414            $self->{state} = NDATA_STATE;
4415            $self->{kwd} = chr $self->{nc};
4416            
4417        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4418          $self->{line_prev} = $self->{line};
4419          $self->{column_prev} = $self->{column};
4420          $self->{column}++;
4421          $self->{nc}
4422              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4423        } else {
4424          $self->{set_nc}->($self);
4425        }
4426      
4427            redo A;
4428          } elsif ($self->{nc} == -1) {
4429            
4430            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4431            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4432            ## reconsume
4433            return  ($self->{ct}); # ENTITY
4434            redo A;
4435          } else {
4436            
4437            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM literal');
4438            $self->{state} = BOGUS_MD_STATE;
4439                    
4440      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4441        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4357  sub _get_next_token ($) { Line 4659  sub _get_next_token ($) {
4659              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
4660              $self->{entity_add} => 1,              $self->{entity_add} => 1,
4661            }->{$self->{nc}}) {            }->{$self->{nc}}) {
4662                    if ($self->{is_xml}) {
4663              
4664              $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
4665                              line => $self->{line_prev},
4666                              column => $self->{column_prev}
4667                                  + ($self->{nc} == -1 ? 1 : 0));
4668            } else {
4669              
4670              ## No error
4671            }
4672          ## Don't consume          ## Don't consume
         ## No error  
4673          ## Return nothing.          ## Return nothing.
4674          #          #
4675        } elsif ($self->{nc} == 0x0023) { # #        } elsif ($self->{nc} == 0x0023) { # #
# Line 4378  sub _get_next_token ($) { Line 4688  sub _get_next_token ($) {
4688      }      }
4689        
4690          redo A;          redo A;
4691        } elsif ((0x0041 <= $self->{nc} and        } elsif ($self->{is_xml} or
4692                   (0x0041 <= $self->{nc} and
4693                  $self->{nc} <= 0x005A) or # A..Z                  $self->{nc} <= 0x005A) or # A..Z
4694                 (0x0061 <= $self->{nc} and                 (0x0061 <= $self->{nc} and
4695                  $self->{nc} <= 0x007A)) { # a..z                  $self->{nc} <= 0x007A)) { # a..z
# Line 4432  sub _get_next_token ($) { Line 4743  sub _get_next_token ($) {
4743          redo A;          redo A;
4744        }        }
4745      } elsif ($self->{state} == ENTITY_HASH_STATE) {      } elsif ($self->{state} == ENTITY_HASH_STATE) {
4746        if ($self->{nc} == 0x0078 or # x        if ($self->{nc} == 0x0078) { # x
4747            $self->{nc} == 0x0058) { # X          
4748            $self->{state} = HEXREF_X_STATE;
4749            $self->{kwd} .= chr $self->{nc};
4750            
4751        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4752          $self->{line_prev} = $self->{line};
4753          $self->{column_prev} = $self->{column};
4754          $self->{column}++;
4755          $self->{nc}
4756              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4757        } else {
4758          $self->{set_nc}->($self);
4759        }
4760      
4761            redo A;
4762          } elsif ($self->{nc} == 0x0058) { # X
4763                    
4764            if ($self->{is_xml}) {
4765              $self->{parse_error}->(level => $self->{level}->{must}, type => 'uppercase hcro'); ## TODO: type
4766            }
4767          $self->{state} = HEXREF_X_STATE;          $self->{state} = HEXREF_X_STATE;
4768          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
4769                    
# Line 4539  sub _get_next_token ($) { Line 4868  sub _get_next_token ($) {
4868        my $code = $self->{kwd};        my $code = $self->{kwd};
4869        my $l = $self->{line_prev};        my $l = $self->{line_prev};
4870        my $c = $self->{column_prev};        my $c = $self->{column_prev};
4871        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
4872              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
4873              ($self->{is_xml} and $code == 0x0000)) {
4874                    
4875          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
4876                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4692  sub _get_next_token ($) { Line 5023  sub _get_next_token ($) {
5023        my $code = $self->{kwd};        my $code = $self->{kwd};
5024        my $l = $self->{line_prev};        my $l = $self->{line_prev};
5025        my $c = $self->{column_prev};        my $c = $self->{column_prev};
5026        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
5027              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
5028              ($self->{is_xml} and $code == 0x0000)) {
5029                    
5030          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
5031                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4726  sub _get_next_token ($) { Line 5059  sub _get_next_token ($) {
5059          redo A;          redo A;
5060        }        }
5061      } elsif ($self->{state} == ENTITY_NAME_STATE) {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
5062        if (length $self->{kwd} < 30 and        if ((0x0041 <= $self->{nc} and # a
5063            ## NOTE: Some number greater than the maximum length of entity name             $self->{nc} <= 0x005A) or # x
5064            ((0x0041 <= $self->{nc} and # a            (0x0061 <= $self->{nc} and # a
5065              $self->{nc} <= 0x005A) or # x             $self->{nc} <= 0x007A) or # z
5066             (0x0061 <= $self->{nc} and # a            (0x0030 <= $self->{nc} and # 0
5067              $self->{nc} <= 0x007A) or # z             $self->{nc} <= 0x0039) or # 9
5068             (0x0030 <= $self->{nc} and # 0            $self->{nc} == 0x003B or # ;
5069              $self->{nc} <= 0x0039) or # 9            ($self->{is_xml} and
5070             $self->{nc} == 0x003B)) { # ;             not ($is_space->{$self->{nc}} or
5071                    {
5072                      0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
5073                      $self->{entity_add} => 1,
5074                    }->{$self->{nc}}))) {
5075          our $EntityChar;          our $EntityChar;
5076          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5077          if (defined $EntityChar->{$self->{kwd}}) {          if (defined $EntityChar->{$self->{kwd}} or
5078                $self->{ge}->{$self->{kwd}}) {
5079            if ($self->{nc} == 0x003B) { # ;            if ($self->{nc} == 0x003B) { # ;
5080                            if (defined $self->{ge}->{$self->{kwd}}) {
5081              $self->{entity__value} = $EntityChar->{$self->{kwd}};                if ($self->{ge}->{$self->{kwd}}->{only_text}) {
5082                    
5083                    $self->{entity__value} = $self->{ge}->{$self->{kwd}}->{value};
5084                  } else {
5085                    if (defined $self->{ge}->{$self->{kwd}}->{notation}) {
5086                      
5087                      $self->{parse_error}->(level => $self->{level}->{must}, type => 'unparsed entity', ## TODO: type
5088                                      value => $self->{kwd});
5089                    } else {
5090                      
5091                    }
5092                    $self->{entity__value} = '&' . $self->{kwd}; ## TODO: expand
5093                  }
5094                } else {
5095                  if ($self->{is_xml}) {
5096                    
5097                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'entity not declared', ## TODO: type
5098                                    value => $self->{kwd},
5099                                    level => {
5100                                              'amp;' => $self->{level}->{warn},
5101                                              'quot;' => $self->{level}->{warn},
5102                                              'lt;' => $self->{level}->{warn},
5103                                              'gt;' => $self->{level}->{warn},
5104                                              'apos;' => $self->{level}->{warn},
5105                                             }->{$self->{kwd}} ||
5106                                             $self->{level}->{must});
5107                  } else {
5108                    
5109                  }
5110                  $self->{entity__value} = $EntityChar->{$self->{kwd}};
5111                }
5112              $self->{entity__match} = 1;              $self->{entity__match} = 1;
5113                            
5114      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 5504  sub _get_next_token ($) {
5504          ## XML5: Not defined yet.          ## XML5: Not defined yet.
5505    
5506          ## TODO:          ## TODO:
5507    
5508            if (not $self->{stop_processing} and
5509                not $self->{document}->xml_standalone) {
5510              $self->{parse_error}->(level => $self->{level}->{must}, type => 'stop processing', ## TODO: type
5511                              level => $self->{level}->{info});
5512              $self->{stop_processing} = 1;
5513            }
5514    
5515                    
5516      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
5517        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5358  sub _get_next_token ($) { Line 5734  sub _get_next_token ($) {
5734      }      }
5735        
5736          redo A;          redo A;
5737        } elsif ($self->{nc} == 0x0045) { # E        } elsif ($self->{nc} == 0x0045 or # E
5738                   $self->{nc} == 0x0065) { # e
5739          $self->{state} = MD_E_STATE;          $self->{state} = MD_E_STATE;
5740          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5741                    
# Line 5373  sub _get_next_token ($) { Line 5750  sub _get_next_token ($) {
5750      }      }
5751        
5752          redo A;          redo A;
5753        } elsif ($self->{nc} == 0x0041) { # A        } elsif ($self->{nc} == 0x0041 or # A
5754                   $self->{nc} == 0x0061) { # a
5755          $self->{state} = MD_ATTLIST_STATE;          $self->{state} = MD_ATTLIST_STATE;
5756          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5757                    
# Line 5388  sub _get_next_token ($) { Line 5766  sub _get_next_token ($) {
5766      }      }
5767        
5768          redo A;          redo A;
5769        } elsif ($self->{nc} == 0x004E) { # N        } elsif ($self->{nc} == 0x004E or # N
5770                   $self->{nc} == 0x006E) { # n
5771          $self->{state} = MD_NOTATION_STATE;          $self->{state} = MD_NOTATION_STATE;
5772          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5773                    
# Line 5416  sub _get_next_token ($) { Line 5795  sub _get_next_token ($) {
5795        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.
5796        redo A;        redo A;
5797      } elsif ($self->{state} == MD_E_STATE) {      } elsif ($self->{state} == MD_E_STATE) {
5798        if ($self->{nc} == 0x004E) { # N        if ($self->{nc} == 0x004E or # N
5799              $self->{nc} == 0x006E) { # n
5800          $self->{state} = MD_ENTITY_STATE;          $self->{state} = MD_ENTITY_STATE;
5801          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5802                    
# Line 5431  sub _get_next_token ($) { Line 5811  sub _get_next_token ($) {
5811      }      }
5812        
5813          redo A;          redo A;
5814        } elsif ($self->{nc} == 0x004C) { # L        } elsif ($self->{nc} == 0x004C or # L
5815                   $self->{nc} == 0x006C) { # l
5816          ## XML5: <!ELEMENT> not supported.          ## XML5: <!ELEMENT> not supported.
5817          $self->{state} = MD_ELEMENT_STATE;          $self->{state} = MD_ELEMENT_STATE;
5818          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
# Line 5459  sub _get_next_token ($) { Line 5840  sub _get_next_token ($) {
5840          redo A;          redo A;
5841        }        }
5842      } elsif ($self->{state} == MD_ENTITY_STATE) {      } elsif ($self->{state} == MD_ENTITY_STATE) {
5843        if ($self->{nc} == {        if ($self->{nc} == [
5844              'EN' => 0x0054, # T              undef,
5845              'ENT' => 0x0049, # I              undef,
5846              'ENTI' => 0x0054, # T              0x0054, # T
5847            }->{$self->{kwd}}) {              0x0049, # I
5848                0x0054, # T
5849              ]->[length $self->{kwd}] or
5850              $self->{nc} == [
5851                undef,
5852                undef,
5853                0x0074, # t
5854                0x0069, # i
5855                0x0074, # t
5856              ]->[length $self->{kwd}]) {
5857          ## Stay in the state.          ## Stay in the state.
5858          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5859                    
# Line 5478  sub _get_next_token ($) { Line 5868  sub _get_next_token ($) {
5868      }      }
5869        
5870          redo A;          redo A;
5871        } elsif ($self->{kwd} eq 'ENTIT' and        } elsif ((length $self->{kwd}) == 5 and
5872                 $self->{nc} == 0x0059) { # Y                 ($self->{nc} == 0x0059 or # Y
5873          $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '', text => '',                  $self->{nc} == 0x0079)) { # y
5874            if ($self->{kwd} ne 'ENTIT' or $self->{nc} == 0x0079) {
5875              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
5876                              text => 'ENTITY',
5877                              line => $self->{line_prev},
5878                              column => $self->{column_prev} - 4);
5879            }
5880            $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '',
5881                         line => $self->{line_prev},                         line => $self->{line_prev},
5882                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 6};
5883          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
# Line 5508  sub _get_next_token ($) { Line 5905  sub _get_next_token ($) {
5905          redo A;          redo A;
5906        }        }
5907      } elsif ($self->{state} == MD_ELEMENT_STATE) {      } elsif ($self->{state} == MD_ELEMENT_STATE) {
5908        if ($self->{nc} == {        if ($self->{nc} == [
5909              'EL' => 0x0045, # E             undef,
5910              'ELE' => 0x004D, # M             undef,
5911              'ELEM' => 0x0045, # E             0x0045, # E
5912              'ELEME' => 0x004E, # N             0x004D, # M
5913            }->{$self->{kwd}}) {             0x0045, # E
5914               0x004E, # N
5915              ]->[length $self->{kwd}] or
5916              $self->{nc} == [
5917               undef,
5918               undef,
5919               0x0065, # e
5920               0x006D, # m
5921               0x0065, # e
5922               0x006E, # n
5923              ]->[length $self->{kwd}]) {
5924          ## Stay in the state.          ## Stay in the state.
5925          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5926                    
# Line 5528  sub _get_next_token ($) { Line 5935  sub _get_next_token ($) {
5935      }      }
5936        
5937          redo A;          redo A;
5938        } elsif ($self->{kwd} eq 'ELEMEN' and        } elsif ((length $self->{kwd}) == 6 and
5939                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
5940                    $self->{nc} == 0x0074)) { # t
5941            if ($self->{kwd} ne 'ELEMEN' or $self->{nc} == 0x0074) {
5942              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
5943                              text => 'ELEMENT',
5944                              line => $self->{line_prev},
5945                              column => $self->{column_prev} - 5);
5946            }
5947          $self->{ct} = {type => ELEMENT_TOKEN, name => '',          $self->{ct} = {type => ELEMENT_TOKEN, name => '',
5948                         line => $self->{line_prev},                         line => $self->{line_prev},
5949                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
5950          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
5951                    
5952      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 5972  sub _get_next_token ($) {
5972          redo A;          redo A;
5973        }        }
5974      } elsif ($self->{state} == MD_ATTLIST_STATE) {      } elsif ($self->{state} == MD_ATTLIST_STATE) {
5975        if ($self->{nc} == {        if ($self->{nc} == [
5976              'A' => 0x0054, # T             undef,
5977              'AT' => 0x0054, # T             0x0054, # T
5978              'ATT' => 0x004C, # L             0x0054, # T
5979              'ATTL' => 0x0049, # I             0x004C, # L
5980              'ATTLI' => 0x0053, # S             0x0049, # I
5981            }->{$self->{kwd}}) {             0x0053, # S
5982              ]->[length $self->{kwd}] or
5983              $self->{nc} == [
5984               undef,
5985               0x0074, # t
5986               0x0074, # t
5987               0x006C, # l
5988               0x0069, # i
5989               0x0073, # s
5990              ]->[length $self->{kwd}]) {
5991          ## Stay in the state.          ## Stay in the state.
5992          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5993                    
# Line 5579  sub _get_next_token ($) { Line 6002  sub _get_next_token ($) {
6002      }      }
6003        
6004          redo A;          redo A;
6005        } elsif ($self->{kwd} eq 'ATTLIS' and        } elsif ((length $self->{kwd}) == 6 and
6006                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
6007                    $self->{nc} == 0x0074)) { # t
6008            if ($self->{kwd} ne 'ATTLIS' or $self->{nc} == 0x0074) {
6009              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6010                              text => 'ATTLIST',
6011                              line => $self->{line_prev},
6012                              column => $self->{column_prev} - 5);
6013            }
6014          $self->{ct} = {type => ATTLIST_TOKEN, name => '',          $self->{ct} = {type => ATTLIST_TOKEN, name => '',
6015                         attrdefs => [],                         attrdefs => [],
6016                         line => $self->{line_prev},                         line => $self->{line_prev},
6017                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
6018          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6019                    
6020      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 6040  sub _get_next_token ($) {
6040          redo A;          redo A;
6041        }        }
6042      } elsif ($self->{state} == MD_NOTATION_STATE) {      } elsif ($self->{state} == MD_NOTATION_STATE) {
6043        if ($self->{nc} == {        if ($self->{nc} == [
6044              'N' => 0x004F, # O             undef,
6045              'NO' => 0x0054, # T             0x004F, # O
6046              'NOT' => 0x0041, # A             0x0054, # T
6047              'NOTA' => 0x0054, # T             0x0041, # A
6048              'NOTAT' => 0x0049, # I             0x0054, # T
6049              'NOTATI' => 0x004F, # O             0x0049, # I
6050            }->{$self->{kwd}}) {             0x004F, # O
6051              ]->[length $self->{kwd}] or
6052              $self->{nc} == [
6053               undef,
6054               0x006F, # o
6055               0x0074, # t
6056               0x0061, # a
6057               0x0074, # t
6058               0x0069, # i
6059               0x006F, # o
6060              ]->[length $self->{kwd}]) {
6061          ## Stay in the state.          ## Stay in the state.
6062          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6063                    
# Line 5632  sub _get_next_token ($) { Line 6072  sub _get_next_token ($) {
6072      }      }
6073        
6074          redo A;          redo A;
6075        } elsif ($self->{kwd} eq 'NOTATIO' and        } elsif ((length $self->{kwd}) == 7 and
6076                 $self->{nc} == 0x004E) { # N                 ($self->{nc} == 0x004E or # N
6077                    $self->{nc} == 0x006E)) { # n
6078            if ($self->{kwd} ne 'NOTATIO' or $self->{nc} == 0x006E) {
6079              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6080                              text => 'NOTATION',
6081                              line => $self->{line_prev},
6082                              column => $self->{column_prev} - 6);
6083            }
6084          $self->{ct} = {type => NOTATION_TOKEN, name => '',          $self->{ct} = {type => NOTATION_TOKEN, name => '',
6085                         line => $self->{line_prev},                         line => $self->{line_prev},
6086                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 8};
6087          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6088                    
6089      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 6292  sub _get_next_token ($) {
6292        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".        ## XML5: "DOCTYPE ENTITY name state" and "DOCTYPE ATTLIST name state".
6293                
6294        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
6295          ## TODO:          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6296          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
6297            } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
6298              $self->{state} = AFTER_ELEMENT_NAME_STATE;
6299            } else { # ENTITY/NOTATION
6300              $self->{state} = AFTER_DOCTYPE_NAME_STATE;
6301            }
6302                    
6303      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
6304        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5863  sub _get_next_token ($) { Line 6315  sub _get_next_token ($) {
6315          if ($self->{ct}->{type} == ATTLIST_TOKEN) {          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6316            #            #
6317          } else {          } else {
6318            $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
6319          }          }
6320          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
6321                    
# Line 6853  sub _get_next_token ($) { Line 7305  sub _get_next_token ($) {
7305        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
7306          ## XML5: No parse error.          ## XML5: No parse error.
7307          $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
7308          $self->{state} = BOGUS_COMMENT_STATE;          $self->{state} = BOGUS_MD_STATE;
         $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded  
7309          ## Reconsume.          ## Reconsume.
7310          redo A;          redo A;
7311        } elsif ($self->{nc} == 0x0022) { # "        } elsif ($self->{nc} == 0x0022) { # "
# Line 7141  sub _get_next_token ($) { Line 7592  sub _get_next_token ($) {
7592          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;          $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
7593          ## Reconsume.          ## Reconsume.
7594          redo A;          redo A;
7595        }              }
7596        } elsif ($self->{state} == NDATA_STATE) {
7597          ## ASCII case-insensitive
7598          if ($self->{nc} == [
7599                undef,
7600                0x0044, # D
7601                0x0041, # A
7602                0x0054, # T
7603              ]->[length $self->{kwd}] or
7604              $self->{nc} == [
7605                undef,
7606                0x0064, # d
7607                0x0061, # a
7608                0x0074, # t
7609              ]->[length $self->{kwd}]) {
7610            
7611            ## Stay in the state.
7612            $self->{kwd} .= chr $self->{nc};
7613            
7614        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7615          $self->{line_prev} = $self->{line};
7616          $self->{column_prev} = $self->{column};
7617          $self->{column}++;
7618          $self->{nc}
7619              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7620        } else {
7621          $self->{set_nc}->($self);
7622        }
7623      
7624            redo A;
7625          } elsif ((length $self->{kwd}) == 4 and
7626                   ($self->{nc} == 0x0041 or # A
7627                    $self->{nc} == 0x0061)) { # a
7628            if ($self->{kwd} ne 'NDAT' or $self->{nc} == 0x0061) { # a
7629              
7630              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
7631                              text => 'NDATA',
7632                              line => $self->{line_prev},
7633                              column => $self->{column_prev} - 4);
7634            } else {
7635              
7636            }
7637            $self->{state} = AFTER_NDATA_STATE;
7638            
7639        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7640          $self->{line_prev} = $self->{line};
7641          $self->{column_prev} = $self->{column};
7642          $self->{column}++;
7643          $self->{nc}
7644              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7645        } else {
7646          $self->{set_nc}->($self);
7647        }
7648      
7649            redo A;
7650          } else {
7651            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7652                            line => $self->{line_prev},
7653                            column => $self->{column_prev} + 1
7654                                - length $self->{kwd});
7655            
7656            $self->{state} = BOGUS_MD_STATE;
7657            ## Reconsume.
7658            redo A;
7659          }
7660        } elsif ($self->{state} == AFTER_NDATA_STATE) {
7661          if ($is_space->{$self->{nc}}) {
7662            $self->{state} = BEFORE_NOTATION_NAME_STATE;
7663            
7664        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7665          $self->{line_prev} = $self->{line};
7666          $self->{column_prev} = $self->{column};
7667          $self->{column}++;
7668          $self->{nc}
7669              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7670        } else {
7671          $self->{set_nc}->($self);
7672        }
7673      
7674            redo A;
7675          } elsif ($self->{nc} == 0x003E) { # >
7676            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7677            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7678            
7679        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7680          $self->{line_prev} = $self->{line};
7681          $self->{column_prev} = $self->{column};
7682          $self->{column}++;
7683          $self->{nc}
7684              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7685        } else {
7686          $self->{set_nc}->($self);
7687        }
7688      
7689            return  ($self->{ct}); # ENTITY
7690            redo A;
7691          } elsif ($self->{nc} == -1) {
7692            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7693            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7694            
7695        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7696          $self->{line_prev} = $self->{line};
7697          $self->{column_prev} = $self->{column};
7698          $self->{column}++;
7699          $self->{nc}
7700              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7701        } else {
7702          $self->{set_nc}->($self);
7703        }
7704      
7705            return  ($self->{ct}); # ENTITY
7706            redo A;
7707          } else {
7708            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7709                            line => $self->{line_prev},
7710                            column => $self->{column_prev} + 1
7711                                - length $self->{kwd});
7712            $self->{state} = BOGUS_MD_STATE;
7713            ## Reconsume.
7714            redo A;
7715          }
7716        } elsif ($self->{state} == BEFORE_NOTATION_NAME_STATE) {
7717          if ($is_space->{$self->{nc}}) {
7718            ## Stay in the state.
7719            
7720        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7721          $self->{line_prev} = $self->{line};
7722          $self->{column_prev} = $self->{column};
7723          $self->{column}++;
7724          $self->{nc}
7725              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7726        } else {
7727          $self->{set_nc}->($self);
7728        }
7729      
7730            redo A;
7731          } elsif ($self->{nc} == 0x003E) { # >
7732            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7733            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7734            
7735        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7736          $self->{line_prev} = $self->{line};
7737          $self->{column_prev} = $self->{column};
7738          $self->{column}++;
7739          $self->{nc}
7740              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7741        } else {
7742          $self->{set_nc}->($self);
7743        }
7744      
7745            return  ($self->{ct}); # ENTITY
7746            redo A;
7747          } elsif ($self->{nc} == -1) {
7748            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7749            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7750            
7751        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7752          $self->{line_prev} = $self->{line};
7753          $self->{column_prev} = $self->{column};
7754          $self->{column}++;
7755          $self->{nc}
7756              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7757        } else {
7758          $self->{set_nc}->($self);
7759        }
7760      
7761            return  ($self->{ct}); # ENTITY
7762            redo A;
7763          } else {
7764            $self->{ct}->{notation} = chr $self->{nc}; # ENTITY
7765            $self->{state} = NOTATION_NAME_STATE;
7766            
7767        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7768          $self->{line_prev} = $self->{line};
7769          $self->{column_prev} = $self->{column};
7770          $self->{column}++;
7771          $self->{nc}
7772              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7773        } else {
7774          $self->{set_nc}->($self);
7775        }
7776      
7777            redo A;
7778          }
7779        } elsif ($self->{state} == NOTATION_NAME_STATE) {
7780          if ($is_space->{$self->{nc}}) {
7781            $self->{state} = AFTER_MD_DEF_STATE;
7782            
7783        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7784          $self->{line_prev} = $self->{line};
7785          $self->{column_prev} = $self->{column};
7786          $self->{column}++;
7787          $self->{nc}
7788              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7789        } else {
7790          $self->{set_nc}->($self);
7791        }
7792      
7793            redo A;
7794          } elsif ($self->{nc} == 0x003E) { # >
7795            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7796            
7797        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7798          $self->{line_prev} = $self->{line};
7799          $self->{column_prev} = $self->{column};
7800          $self->{column}++;
7801          $self->{nc}
7802              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7803        } else {
7804          $self->{set_nc}->($self);
7805        }
7806      
7807            return  ($self->{ct}); # ENTITY
7808            redo A;
7809          } elsif ($self->{nc} == -1) {
7810            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7811            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7812            
7813        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7814          $self->{line_prev} = $self->{line};
7815          $self->{column_prev} = $self->{column};
7816          $self->{column}++;
7817          $self->{nc}
7818              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7819        } else {
7820          $self->{set_nc}->($self);
7821        }
7822      
7823            return  ($self->{ct}); # ENTITY
7824            redo A;
7825          } else {
7826            $self->{ct}->{notation} .= chr $self->{nc}; # ENTITY
7827            ## Stay in the state.
7828            
7829        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7830          $self->{line_prev} = $self->{line};
7831          $self->{column_prev} = $self->{column};
7832          $self->{column}++;
7833          $self->{nc}
7834              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7835        } else {
7836          $self->{set_nc}->($self);
7837        }
7838      
7839            redo A;
7840          }
7841        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE) {
7842          if ($self->{nc} == 0x0022) { # "
7843            $self->{state} = AFTER_MD_DEF_STATE;
7844            
7845        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7846          $self->{line_prev} = $self->{line};
7847          $self->{column_prev} = $self->{column};
7848          $self->{column}++;
7849          $self->{nc}
7850              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7851        } else {
7852          $self->{set_nc}->($self);
7853        }
7854      
7855            redo A;
7856          } elsif ($self->{nc} == 0x0026) { # &
7857            $self->{prev_state} = $self->{state};
7858            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
7859            $self->{entity_add} = 0x0022; # "
7860            
7861        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7862          $self->{line_prev} = $self->{line};
7863          $self->{column_prev} = $self->{column};
7864          $self->{column}++;
7865          $self->{nc}
7866              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7867        } else {
7868          $self->{set_nc}->($self);
7869        }
7870      
7871            redo A;
7872    ## TODO: %
7873          } elsif ($self->{nc} == -1) {
7874            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
7875            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7876            ## Reconsume.
7877            return  ($self->{ct}); # ENTITY
7878            redo A;
7879          } else {
7880            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
7881            
7882        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7883          $self->{line_prev} = $self->{line};
7884          $self->{column_prev} = $self->{column};
7885          $self->{column}++;
7886          $self->{nc}
7887              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7888        } else {
7889          $self->{set_nc}->($self);
7890        }
7891      
7892            redo A;
7893          }
7894        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE) {
7895          if ($self->{nc} == 0x0027) { # '
7896            $self->{state} = AFTER_MD_DEF_STATE;
7897            
7898        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7899          $self->{line_prev} = $self->{line};
7900          $self->{column_prev} = $self->{column};
7901          $self->{column}++;
7902          $self->{nc}
7903              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7904        } else {
7905          $self->{set_nc}->($self);
7906        }
7907      
7908            redo A;
7909          } elsif ($self->{nc} == 0x0026) { # &
7910            $self->{prev_state} = $self->{state};
7911            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
7912            $self->{entity_add} = 0x0027; # '
7913            
7914        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7915          $self->{line_prev} = $self->{line};
7916          $self->{column_prev} = $self->{column};
7917          $self->{column}++;
7918          $self->{nc}
7919              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7920        } else {
7921          $self->{set_nc}->($self);
7922        }
7923      
7924            redo A;
7925    ## TODO: %
7926          } elsif ($self->{nc} == -1) {
7927            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
7928            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7929            ## Reconsume.
7930            return  ($self->{ct}); # ENTITY
7931            redo A;
7932          } else {
7933            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
7934            
7935        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7936          $self->{line_prev} = $self->{line};
7937          $self->{column_prev} = $self->{column};
7938          $self->{column}++;
7939          $self->{nc}
7940              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7941        } else {
7942          $self->{set_nc}->($self);
7943        }
7944      
7945            redo A;
7946          }
7947        } elsif ($self->{state} == ENTITY_VALUE_ENTITY_STATE) {
7948          if ($is_space->{$self->{nc}} or
7949              {
7950                0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
7951                $self->{entity_add} => 1,
7952              }->{$self->{nc}}) {
7953            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
7954                            line => $self->{line_prev},
7955                            column => $self->{column_prev}
7956                                + ($self->{nc} == -1 ? 1 : 0));
7957            ## Don't consume
7958            ## Return nothing.
7959            #
7960          } elsif ($self->{nc} == 0x0023) { # #
7961            $self->{ca} = $self->{ct};
7962            $self->{state} = ENTITY_HASH_STATE;
7963            $self->{kwd} = '#';
7964            
7965        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7966          $self->{line_prev} = $self->{line};
7967          $self->{column_prev} = $self->{column};
7968          $self->{column}++;
7969          $self->{nc}
7970              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7971        } else {
7972          $self->{set_nc}->($self);
7973        }
7974      
7975            redo A;
7976          } else {
7977            #
7978          }
7979    
7980          $self->{ct}->{value} .= '&';
7981          $self->{state} = $self->{prev_state};
7982          ## Reconsume.
7983          redo A;
7984        } elsif ($self->{state} == AFTER_ELEMENT_NAME_STATE) {
7985          if ($is_space->{$self->{nc}}) {
7986            $self->{state} = BEFORE_ELEMENT_CONTENT_STATE;
7987            
7988        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7989          $self->{line_prev} = $self->{line};
7990          $self->{column_prev} = $self->{column};
7991          $self->{column}++;
7992          $self->{nc}
7993              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7994        } else {
7995          $self->{set_nc}->($self);
7996        }
7997      
7998            redo A;
7999          } elsif ($self->{nc} == 0x0028) { # (
8000            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8001            $self->{ct}->{content} = ['('];
8002            $self->{group_depth} = 1;
8003            
8004        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8005          $self->{line_prev} = $self->{line};
8006          $self->{column_prev} = $self->{column};
8007          $self->{column}++;
8008          $self->{nc}
8009              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8010        } else {
8011          $self->{set_nc}->($self);
8012        }
8013      
8014            redo A;
8015          } elsif ($self->{nc} == 0x003E) { # >
8016            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
8017            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8018            
8019        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8020          $self->{line_prev} = $self->{line};
8021          $self->{column_prev} = $self->{column};
8022          $self->{column}++;
8023          $self->{nc}
8024              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8025        } else {
8026          $self->{set_nc}->($self);
8027        }
8028      
8029            return  ($self->{ct}); # ELEMENT
8030            redo A;
8031          } elsif ($self->{nc} == -1) {
8032            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8033            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8034            
8035        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8036          $self->{line_prev} = $self->{line};
8037          $self->{column_prev} = $self->{column};
8038          $self->{column}++;
8039          $self->{nc}
8040              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8041        } else {
8042          $self->{set_nc}->($self);
8043        }
8044      
8045            return  ($self->{ct}); # ELEMENT
8046            redo A;
8047          } else {
8048            $self->{ct}->{content} = [chr $self->{nc}];
8049            $self->{state} = CONTENT_KEYWORD_STATE;
8050            
8051        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8052          $self->{line_prev} = $self->{line};
8053          $self->{column_prev} = $self->{column};
8054          $self->{column}++;
8055          $self->{nc}
8056              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8057        } else {
8058          $self->{set_nc}->($self);
8059        }
8060      
8061            redo A;
8062          }
8063        } elsif ($self->{state} == CONTENT_KEYWORD_STATE) {
8064          if ($is_space->{$self->{nc}}) {
8065            $self->{state} = AFTER_MD_DEF_STATE;
8066            
8067        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8068          $self->{line_prev} = $self->{line};
8069          $self->{column_prev} = $self->{column};
8070          $self->{column}++;
8071          $self->{nc}
8072              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8073        } else {
8074          $self->{set_nc}->($self);
8075        }
8076      
8077            redo A;
8078          } elsif ($self->{nc} == 0x003E) { # >
8079            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8080            
8081        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8082          $self->{line_prev} = $self->{line};
8083          $self->{column_prev} = $self->{column};
8084          $self->{column}++;
8085          $self->{nc}
8086              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8087        } else {
8088          $self->{set_nc}->($self);
8089        }
8090      
8091            return  ($self->{ct}); # ELEMENT
8092            redo A;
8093          } elsif ($self->{nc} == -1) {
8094            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8095            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8096            
8097        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8098          $self->{line_prev} = $self->{line};
8099          $self->{column_prev} = $self->{column};
8100          $self->{column}++;
8101          $self->{nc}
8102              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8103        } else {
8104          $self->{set_nc}->($self);
8105        }
8106      
8107            return  ($self->{ct}); # ELEMENT
8108            redo A;
8109          } else {
8110            $self->{ct}->{content}->[-1] .= chr $self->{nc}; # ELEMENT
8111            ## Stay in the state.
8112            
8113        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8114          $self->{line_prev} = $self->{line};
8115          $self->{column_prev} = $self->{column};
8116          $self->{column}++;
8117          $self->{nc}
8118              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8119        } else {
8120          $self->{set_nc}->($self);
8121        }
8122      
8123            redo A;
8124          }
8125        } elsif ($self->{state} == AFTER_CM_GROUP_OPEN_STATE) {
8126          if ($is_space->{$self->{nc}}) {
8127            ## Stay in the state.
8128            
8129        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8130          $self->{line_prev} = $self->{line};
8131          $self->{column_prev} = $self->{column};
8132          $self->{column}++;
8133          $self->{nc}
8134              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8135        } else {
8136          $self->{set_nc}->($self);
8137        }
8138      
8139            redo A;
8140          } elsif ($self->{nc} == 0x0028) { # (
8141            $self->{group_depth}++;
8142            push @{$self->{ct}->{content}}, chr $self->{nc};
8143            ## Stay in the state.
8144            
8145        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8146          $self->{line_prev} = $self->{line};
8147          $self->{column_prev} = $self->{column};
8148          $self->{column}++;
8149          $self->{nc}
8150              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8151        } else {
8152          $self->{set_nc}->($self);
8153        }
8154      
8155            redo A;
8156          } elsif ($self->{nc} == 0x007C or # |
8157                   $self->{nc} == 0x002C) { # ,
8158            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8159            ## Stay in the state.
8160            
8161        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8162          $self->{line_prev} = $self->{line};
8163          $self->{column_prev} = $self->{column};
8164          $self->{column}++;
8165          $self->{nc}
8166              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8167        } else {
8168          $self->{set_nc}->($self);
8169        }
8170      
8171            redo A;
8172          } elsif ($self->{nc} == 0x0029) { # )
8173            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8174            push @{$self->{ct}->{content}}, chr $self->{nc};
8175            $self->{group_depth}--;
8176            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8177            
8178        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8179          $self->{line_prev} = $self->{line};
8180          $self->{column_prev} = $self->{column};
8181          $self->{column}++;
8182          $self->{nc}
8183              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8184        } else {
8185          $self->{set_nc}->($self);
8186        }
8187      
8188            redo A;
8189          } elsif ($self->{nc} == 0x003E) { # >
8190            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8191            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8192            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8193            
8194        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8195          $self->{line_prev} = $self->{line};
8196          $self->{column_prev} = $self->{column};
8197          $self->{column}++;
8198          $self->{nc}
8199              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8200        } else {
8201          $self->{set_nc}->($self);
8202        }
8203      
8204            return  ($self->{ct}); # ELEMENT
8205            redo A;
8206          } elsif ($self->{nc} == -1) {
8207            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8208            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8209            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8210            
8211        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8212          $self->{line_prev} = $self->{line};
8213          $self->{column_prev} = $self->{column};
8214          $self->{column}++;
8215          $self->{nc}
8216              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8217        } else {
8218          $self->{set_nc}->($self);
8219        }
8220      
8221            return  ($self->{ct}); # ELEMENT
8222            redo A;
8223          } else {
8224            push @{$self->{ct}->{content}}, chr $self->{nc};
8225            $self->{state} = CM_ELEMENT_NAME_STATE;
8226            
8227        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8228          $self->{line_prev} = $self->{line};
8229          $self->{column_prev} = $self->{column};
8230          $self->{column}++;
8231          $self->{nc}
8232              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8233        } else {
8234          $self->{set_nc}->($self);
8235        }
8236      
8237            redo A;
8238          }
8239        } elsif ($self->{state} == CM_ELEMENT_NAME_STATE) {
8240          if ($is_space->{$self->{nc}}) {
8241            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8242            
8243        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8244          $self->{line_prev} = $self->{line};
8245          $self->{column_prev} = $self->{column};
8246          $self->{column}++;
8247          $self->{nc}
8248              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8249        } else {
8250          $self->{set_nc}->($self);
8251        }
8252      
8253            redo A;
8254          } elsif ($self->{nc} == 0x002A or # *
8255                   $self->{nc} == 0x002B or # +
8256                   $self->{nc} == 0x003F) { # ?
8257            push @{$self->{ct}->{content}}, chr $self->{nc};
8258            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8259            
8260        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8261          $self->{line_prev} = $self->{line};
8262          $self->{column_prev} = $self->{column};
8263          $self->{column}++;
8264          $self->{nc}
8265              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8266        } else {
8267          $self->{set_nc}->($self);
8268        }
8269      
8270            redo A;
8271          } elsif ($self->{nc} == 0x007C or # |
8272                   $self->{nc} == 0x002C) { # ,
8273            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8274            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8275            
8276        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8277          $self->{line_prev} = $self->{line};
8278          $self->{column_prev} = $self->{column};
8279          $self->{column}++;
8280          $self->{nc}
8281              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8282        } else {
8283          $self->{set_nc}->($self);
8284        }
8285      
8286            redo A;
8287          } elsif ($self->{nc} == 0x0029) { # )
8288            $self->{group_depth}--;
8289            push @{$self->{ct}->{content}}, chr $self->{nc};
8290            $self->{state} = AFTER_CM_GROUP_CLOSE_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            redo A;
8303          } elsif ($self->{nc} == 0x003E) { # >
8304            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8305            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
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          } elsif ($self->{nc} == -1) {
8321            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8322            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8323            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8324            
8325        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8326          $self->{line_prev} = $self->{line};
8327          $self->{column_prev} = $self->{column};
8328          $self->{column}++;
8329          $self->{nc}
8330              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8331        } else {
8332          $self->{set_nc}->($self);
8333        }
8334      
8335            return  ($self->{ct}); # ELEMENT
8336            redo A;
8337          } else {
8338            $self->{ct}->{content}->[-1] .= chr $self->{nc};
8339            ## Stay in the state.
8340            
8341        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8342          $self->{line_prev} = $self->{line};
8343          $self->{column_prev} = $self->{column};
8344          $self->{column}++;
8345          $self->{nc}
8346              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8347        } else {
8348          $self->{set_nc}->($self);
8349        }
8350      
8351            redo A;
8352          }
8353        } elsif ($self->{state} == AFTER_CM_ELEMENT_NAME_STATE) {
8354          if ($is_space->{$self->{nc}}) {
8355            ## Stay in the state.
8356            
8357        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8358          $self->{line_prev} = $self->{line};
8359          $self->{column_prev} = $self->{column};
8360          $self->{column}++;
8361          $self->{nc}
8362              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8363        } else {
8364          $self->{set_nc}->($self);
8365        }
8366      
8367            redo A;
8368          } elsif ($self->{nc} == 0x007C or # |
8369                   $self->{nc} == 0x002C) { # ,
8370            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8371            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8372            
8373        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8374          $self->{line_prev} = $self->{line};
8375          $self->{column_prev} = $self->{column};
8376          $self->{column}++;
8377          $self->{nc}
8378              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8379        } else {
8380          $self->{set_nc}->($self);
8381        }
8382      
8383            redo A;
8384          } elsif ($self->{nc} == 0x0029) { # )
8385            $self->{group_depth}--;
8386            push @{$self->{ct}->{content}}, chr $self->{nc};
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            $self->{parse_error}->(level => $self->{level}->{must}, type => 'after element name'); ## TODO: type
8436            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8437            $self->{state} = BOGUS_MD_STATE;
8438            
8439        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8440          $self->{line_prev} = $self->{line};
8441          $self->{column_prev} = $self->{column};
8442          $self->{column}++;
8443          $self->{nc}
8444              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8445        } else {
8446          $self->{set_nc}->($self);
8447        }
8448      
8449            redo A;
8450          }
8451        } elsif ($self->{state} == AFTER_CM_GROUP_CLOSE_STATE) {
8452          if ($is_space->{$self->{nc}}) {
8453            if ($self->{group_depth}) {
8454              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8455            } else {
8456              $self->{state} = AFTER_MD_DEF_STATE;
8457            }
8458            
8459        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8460          $self->{line_prev} = $self->{line};
8461          $self->{column_prev} = $self->{column};
8462          $self->{column}++;
8463          $self->{nc}
8464              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8465        } else {
8466          $self->{set_nc}->($self);
8467        }
8468      
8469            redo A;
8470          } elsif ($self->{nc} == 0x002A or # *
8471                   $self->{nc} == 0x002B or # +
8472                   $self->{nc} == 0x003F) { # ?
8473            push @{$self->{ct}->{content}}, chr $self->{nc};
8474            if ($self->{group_depth}) {
8475              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8476            } else {
8477              $self->{state} = AFTER_MD_DEF_STATE;
8478            }
8479            
8480        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8481          $self->{line_prev} = $self->{line};
8482          $self->{column_prev} = $self->{column};
8483          $self->{column}++;
8484          $self->{nc}
8485              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8486        } else {
8487          $self->{set_nc}->($self);
8488        }
8489      
8490            redo A;
8491          } elsif ($self->{nc} == 0x0029) { # )
8492            if ($self->{group_depth}) {
8493              $self->{group_depth}--;
8494              push @{$self->{ct}->{content}}, chr $self->{nc};
8495              ## Stay in the state.
8496              
8497        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8498          $self->{line_prev} = $self->{line};
8499          $self->{column_prev} = $self->{column};
8500          $self->{column}++;
8501          $self->{nc}
8502              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8503        } else {
8504          $self->{set_nc}->($self);
8505        }
8506      
8507              redo A;
8508            } else {
8509              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8510              $self->{state} = BOGUS_MD_STATE;
8511              ## Reconsume.
8512              redo A;
8513            }
8514          } elsif ($self->{nc} == 0x003E) { # >
8515            if ($self->{group_depth}) {
8516              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8517              push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8518            }
8519            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8520            
8521        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8522          $self->{line_prev} = $self->{line};
8523          $self->{column_prev} = $self->{column};
8524          $self->{column}++;
8525          $self->{nc}
8526              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8527        } else {
8528          $self->{set_nc}->($self);
8529        }
8530      
8531            return  ($self->{ct}); # ELEMENT
8532            redo A;
8533          } elsif ($self->{nc} == -1) {
8534            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8535            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8536            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8537            
8538        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8539          $self->{line_prev} = $self->{line};
8540          $self->{column_prev} = $self->{column};
8541          $self->{column}++;
8542          $self->{nc}
8543              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8544        } else {
8545          $self->{set_nc}->($self);
8546        }
8547      
8548            return  ($self->{ct}); # ELEMENT
8549            redo A;
8550          } else {
8551            if ($self->{group_depth}) {
8552              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8553            } else {
8554              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8555              $self->{state} = BOGUS_MD_STATE;
8556            }
8557            ## Reconsume.
8558            redo A;
8559          }
8560        } elsif ($self->{state} == AFTER_MD_DEF_STATE) {
8561          if ($is_space->{$self->{nc}}) {
8562            ## Stay in the state.
8563            
8564        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8565          $self->{line_prev} = $self->{line};
8566          $self->{column_prev} = $self->{column};
8567          $self->{column}++;
8568          $self->{nc}
8569              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8570        } else {
8571          $self->{set_nc}->($self);
8572        }
8573      
8574            redo A;
8575          } elsif ($self->{nc} == 0x003E) { # >
8576            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8577            
8578        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8579          $self->{line_prev} = $self->{line};
8580          $self->{column_prev} = $self->{column};
8581          $self->{column}++;
8582          $self->{nc}
8583              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8584        } else {
8585          $self->{set_nc}->($self);
8586        }
8587      
8588            return  ($self->{ct}); # ENTITY/ELEMENT
8589            redo A;
8590          } elsif ($self->{nc} == -1) {
8591            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8592            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8593            
8594        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8595          $self->{line_prev} = $self->{line};
8596          $self->{column_prev} = $self->{column};
8597          $self->{column}++;
8598          $self->{nc}
8599              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8600        } else {
8601          $self->{set_nc}->($self);
8602        }
8603      
8604            return  ($self->{ct}); # ENTITY/ELEMENT
8605            redo A;
8606          } else {
8607            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8608            $self->{state} = BOGUS_MD_STATE;
8609            ## Reconsume.
8610            redo A;
8611          }
8612        } elsif ($self->{state} == BOGUS_MD_STATE) {
8613          if ($self->{nc} == 0x003E) { # >
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}); # ATTLIST/ENTITY/NOTATION
8627            redo A;
8628          } elsif ($self->{nc} == -1) {
8629            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8630            ## Reconsume.
8631            return  ($self->{ct}); # ATTLIST/ENTITY/NOTATION
8632            redo A;
8633          } else {
8634            ## Stay in the state.
8635            
8636        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8637          $self->{line_prev} = $self->{line};
8638          $self->{column_prev} = $self->{column};
8639          $self->{column}++;
8640          $self->{nc}
8641              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8642        } else {
8643          $self->{set_nc}->($self);
8644        }
8645      
8646            redo A;
8647          }
8648      } else {      } else {
8649        die "$0: $self->{state}: Unknown state";        die "$0: $self->{state}: Unknown state";
8650      }      }

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24