/[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.16 by wakaba, Sat Oct 18 11:34:49 2008 UTC revision 1.29 by wakaba, Sun Aug 16 04:06:34 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 BOGUS_MD_STATE () { 85 }  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 1724  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 1800  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 1847  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 1914  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 1961  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 2133  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 2142  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 2948  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 2983  sub _get_next_token ($) { Line 3030  sub _get_next_token ($) {
3030      }      }
3031        
3032          redo A;          redo A;
3033          } elsif ($self->{nc} == -1) {
3034            
3035            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3036            $self->{ct}->{quirks} = 1;
3037    
3038            $self->{state} = DATA_STATE;
3039            ## Reconsume.
3040            return  ($self->{ct}); # DOCTYPE (quirks)
3041    
3042            redo A;
3043        } else {        } else {
3044                    
3045          ## XML5: Unless EOF, swith to the bogus comment state.          ## XML5: Swith to the bogus comment state.
3046          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before DOCTYPE name');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before DOCTYPE name');
3047          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
3048          ## reconsume          ## reconsume
# Line 3030  sub _get_next_token ($) { Line 3087  sub _get_next_token ($) {
3087          return  ($self->{ct}); # DOCTYPE (quirks)          return  ($self->{ct}); # DOCTYPE (quirks)
3088    
3089          redo A;          redo A;
3090          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
3091            
3092            $self->{ct}->{name} # DOCTYPE
3093                = chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
3094            delete $self->{ct}->{quirks};
3095            $self->{state} = DOCTYPE_NAME_STATE;
3096            
3097        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3098          $self->{line_prev} = $self->{line};
3099          $self->{column_prev} = $self->{column};
3100          $self->{column}++;
3101          $self->{nc}
3102              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3103        } else {
3104          $self->{set_nc}->($self);
3105        }
3106      
3107            redo A;
3108        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3109                    
3110          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no DOCTYPE name');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'no DOCTYPE name');
# Line 3116  sub _get_next_token ($) { Line 3191  sub _get_next_token ($) {
3191          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3192    
3193          redo A;          redo A;
3194          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
3195            
3196            $self->{ct}->{name} # DOCTYPE
3197                .= chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
3198            delete $self->{ct}->{quirks};
3199            ## Stay in the state.
3200            
3201        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3202          $self->{line_prev} = $self->{line};
3203          $self->{column_prev} = $self->{column};
3204          $self->{column}++;
3205          $self->{nc}
3206              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3207        } else {
3208          $self->{set_nc}->($self);
3209        }
3210      
3211            redo A;
3212        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3213                    
3214          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
# Line 3147  sub _get_next_token ($) { Line 3240  sub _get_next_token ($) {
3240          redo A;          redo A;
3241        } else {        } else {
3242                    
3243          $self->{ct}->{name}          $self->{ct}->{name} .= chr ($self->{nc}); # DOCTYPE
3244            .= chr ($self->{nc}); # DOCTYPE          ## Stay in the state.
         ## Stay in the state  
3245                    
3246      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3247        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3256  sub _get_next_token ($) { Line 3348  sub _get_next_token ($) {
3348      }      }
3349        
3350          redo A;          redo A;
3351  ## TODO: " and ' for ENTITY        } elsif ($self->{nc} == 0x0022 and # "
3352                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3353                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3354            
3355            $self->{state} = DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE;
3356            $self->{ct}->{value} = ''; # ENTITY
3357            
3358        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3359          $self->{line_prev} = $self->{line};
3360          $self->{column_prev} = $self->{column};
3361          $self->{column}++;
3362          $self->{nc}
3363              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3364        } else {
3365          $self->{set_nc}->($self);
3366        }
3367      
3368            redo A;
3369          } elsif ($self->{nc} == 0x0027 and # '
3370                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3371                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3372            
3373            $self->{state} = DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE;
3374            $self->{ct}->{value} = ''; # ENTITY
3375            
3376        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3377          $self->{line_prev} = $self->{line};
3378          $self->{column_prev} = $self->{column};
3379          $self->{column}++;
3380          $self->{nc}
3381              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3382        } else {
3383          $self->{set_nc}->($self);
3384        }
3385      
3386            redo A;
3387        } elsif ($self->{is_xml} and        } elsif ($self->{is_xml} and
3388                 $self->{ct}->{type} == DOCTYPE_TOKEN and                 $self->{ct}->{type} == DOCTYPE_TOKEN and
3389                 $self->{nc} == 0x005B) { # [                 $self->{nc} == 0x005B) { # [
# Line 4172  sub _get_next_token ($) { Line 4299  sub _get_next_token ($) {
4299        }        }
4300      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
4301        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
4302                    if ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN) {
4303          ## Stay in the state            
4304              $self->{state} = BEFORE_NDATA_STATE;
4305            } else {
4306              
4307              ## Stay in the state
4308            }
4309                    
4310      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4311        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4209  sub _get_next_token ($) { Line 4341  sub _get_next_token ($) {
4341        
4342          return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION          return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4343          redo A;          redo A;
4344  ## TODO: "NDATA"        } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
4345                   ($self->{nc} == 0x004E or # N
4346                    $self->{nc} == 0x006E)) { # n
4347            
4348            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before NDATA'); ## TODO: type
4349            $self->{state} = NDATA_STATE;
4350            $self->{kwd} = chr $self->{nc};
4351            
4352        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4353          $self->{line_prev} = $self->{line};
4354          $self->{column_prev} = $self->{column};
4355          $self->{column}++;
4356          $self->{nc}
4357              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4358        } else {
4359          $self->{set_nc}->($self);
4360        }
4361      
4362            redo A;
4363        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4364          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4365                        
# Line 4271  sub _get_next_token ($) { Line 4421  sub _get_next_token ($) {
4421        
4422          redo A;          redo A;
4423        }        }
4424        } elsif ($self->{state} == BEFORE_NDATA_STATE) {
4425          if ($is_space->{$self->{nc}}) {
4426            
4427            ## Stay in the state.
4428            
4429        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4430          $self->{line_prev} = $self->{line};
4431          $self->{column_prev} = $self->{column};
4432          $self->{column}++;
4433          $self->{nc}
4434              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4435        } else {
4436          $self->{set_nc}->($self);
4437        }
4438      
4439            redo A;
4440          } elsif ($self->{nc} == 0x003E) { # >
4441            
4442            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4443            
4444        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4445          $self->{line_prev} = $self->{line};
4446          $self->{column_prev} = $self->{column};
4447          $self->{column}++;
4448          $self->{nc}
4449              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4450        } else {
4451          $self->{set_nc}->($self);
4452        }
4453      
4454            return  ($self->{ct}); # ENTITY
4455            redo A;
4456          } elsif ($self->{nc} == 0x004E or # N
4457                   $self->{nc} == 0x006E) { # n
4458            
4459            $self->{state} = NDATA_STATE;
4460            $self->{kwd} = chr $self->{nc};
4461            
4462        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4463          $self->{line_prev} = $self->{line};
4464          $self->{column_prev} = $self->{column};
4465          $self->{column}++;
4466          $self->{nc}
4467              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4468        } else {
4469          $self->{set_nc}->($self);
4470        }
4471      
4472            redo A;
4473          } elsif ($self->{nc} == -1) {
4474            
4475            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4476            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4477            ## reconsume
4478            return  ($self->{ct}); # ENTITY
4479            redo A;
4480          } else {
4481            
4482            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM literal');
4483            $self->{state} = BOGUS_MD_STATE;
4484            
4485        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4486          $self->{line_prev} = $self->{line};
4487          $self->{column_prev} = $self->{column};
4488          $self->{column}++;
4489          $self->{nc}
4490              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4491        } else {
4492          $self->{set_nc}->($self);
4493        }
4494      
4495            redo A;
4496          }
4497      } elsif ($self->{state} == BOGUS_DOCTYPE_STATE) {      } elsif ($self->{state} == BOGUS_DOCTYPE_STATE) {
4498        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
4499                    
# Line 4481  sub _get_next_token ($) { Line 4704  sub _get_next_token ($) {
4704              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
4705              $self->{entity_add} => 1,              $self->{entity_add} => 1,
4706            }->{$self->{nc}}) {            }->{$self->{nc}}) {
4707                    if ($self->{is_xml}) {
4708              
4709              $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
4710                              line => $self->{line_prev},
4711                              column => $self->{column_prev}
4712                                  + ($self->{nc} == -1 ? 1 : 0));
4713            } else {
4714              
4715              ## No error
4716            }
4717          ## Don't consume          ## Don't consume
         ## No error  
4718          ## Return nothing.          ## Return nothing.
4719          #          #
4720        } elsif ($self->{nc} == 0x0023) { # #        } elsif ($self->{nc} == 0x0023) { # #
# Line 4502  sub _get_next_token ($) { Line 4733  sub _get_next_token ($) {
4733      }      }
4734        
4735          redo A;          redo A;
4736        } elsif ((0x0041 <= $self->{nc} and        } elsif ($self->{is_xml} or
4737                   (0x0041 <= $self->{nc} and
4738                  $self->{nc} <= 0x005A) or # A..Z                  $self->{nc} <= 0x005A) or # A..Z
4739                 (0x0061 <= $self->{nc} and                 (0x0061 <= $self->{nc} and
4740                  $self->{nc} <= 0x007A)) { # a..z                  $self->{nc} <= 0x007A)) { # a..z
# Line 4556  sub _get_next_token ($) { Line 4788  sub _get_next_token ($) {
4788          redo A;          redo A;
4789        }        }
4790      } elsif ($self->{state} == ENTITY_HASH_STATE) {      } elsif ($self->{state} == ENTITY_HASH_STATE) {
4791        if ($self->{nc} == 0x0078 or # x        if ($self->{nc} == 0x0078) { # x
4792            $self->{nc} == 0x0058) { # X          
4793            $self->{state} = HEXREF_X_STATE;
4794            $self->{kwd} .= chr $self->{nc};
4795            
4796        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4797          $self->{line_prev} = $self->{line};
4798          $self->{column_prev} = $self->{column};
4799          $self->{column}++;
4800          $self->{nc}
4801              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4802        } else {
4803          $self->{set_nc}->($self);
4804        }
4805      
4806            redo A;
4807          } elsif ($self->{nc} == 0x0058) { # X
4808                    
4809            if ($self->{is_xml}) {
4810              $self->{parse_error}->(level => $self->{level}->{must}, type => 'uppercase hcro'); ## TODO: type
4811            }
4812          $self->{state} = HEXREF_X_STATE;          $self->{state} = HEXREF_X_STATE;
4813          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
4814                    
# Line 4663  sub _get_next_token ($) { Line 4913  sub _get_next_token ($) {
4913        my $code = $self->{kwd};        my $code = $self->{kwd};
4914        my $l = $self->{line_prev};        my $l = $self->{line_prev};
4915        my $c = $self->{column_prev};        my $c = $self->{column_prev};
4916        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
4917              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
4918              ($self->{is_xml} and $code == 0x0000)) {
4919                    
4920          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
4921                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4816  sub _get_next_token ($) { Line 5068  sub _get_next_token ($) {
5068        my $code = $self->{kwd};        my $code = $self->{kwd};
5069        my $l = $self->{line_prev};        my $l = $self->{line_prev};
5070        my $c = $self->{column_prev};        my $c = $self->{column_prev};
5071        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
5072              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
5073              ($self->{is_xml} and $code == 0x0000)) {
5074                    
5075          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
5076                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4850  sub _get_next_token ($) { Line 5104  sub _get_next_token ($) {
5104          redo A;          redo A;
5105        }        }
5106      } elsif ($self->{state} == ENTITY_NAME_STATE) {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
5107        if (length $self->{kwd} < 30 and        if ((0x0041 <= $self->{nc} and # a
5108            ## NOTE: Some number greater than the maximum length of entity name             $self->{nc} <= 0x005A) or # x
5109            ((0x0041 <= $self->{nc} and # a            (0x0061 <= $self->{nc} and # a
5110              $self->{nc} <= 0x005A) or # x             $self->{nc} <= 0x007A) or # z
5111             (0x0061 <= $self->{nc} and # a            (0x0030 <= $self->{nc} and # 0
5112              $self->{nc} <= 0x007A) or # z             $self->{nc} <= 0x0039) or # 9
5113             (0x0030 <= $self->{nc} and # 0            $self->{nc} == 0x003B or # ;
5114              $self->{nc} <= 0x0039) or # 9            ($self->{is_xml} and
5115             $self->{nc} == 0x003B)) { # ;             not ($is_space->{$self->{nc}} or
5116                    {
5117                      0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
5118                      $self->{entity_add} => 1,
5119                    }->{$self->{nc}}))) {
5120          our $EntityChar;          our $EntityChar;
5121          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5122          if (defined $EntityChar->{$self->{kwd}}) {          if (defined $EntityChar->{$self->{kwd}} or
5123                $self->{ge}->{$self->{kwd}}) {
5124            if ($self->{nc} == 0x003B) { # ;            if ($self->{nc} == 0x003B) { # ;
5125                            if (defined $self->{ge}->{$self->{kwd}}) {
5126              $self->{entity__value} = $EntityChar->{$self->{kwd}};                if ($self->{ge}->{$self->{kwd}}->{only_text}) {
5127                    
5128                    $self->{entity__value} = $self->{ge}->{$self->{kwd}}->{value};
5129                  } else {
5130                    if (defined $self->{ge}->{$self->{kwd}}->{notation}) {
5131                      
5132                      $self->{parse_error}->(level => $self->{level}->{must}, type => 'unparsed entity', ## TODO: type
5133                                      value => $self->{kwd});
5134                    } else {
5135                      
5136                    }
5137                    $self->{entity__value} = '&' . $self->{kwd}; ## TODO: expand
5138                  }
5139                } else {
5140                  if ($self->{is_xml}) {
5141                    
5142                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'entity not declared', ## TODO: type
5143                                    value => $self->{kwd},
5144                                    level => {
5145                                              'amp;' => $self->{level}->{warn},
5146                                              'quot;' => $self->{level}->{warn},
5147                                              'lt;' => $self->{level}->{warn},
5148                                              'gt;' => $self->{level}->{warn},
5149                                              'apos;' => $self->{level}->{warn},
5150                                             }->{$self->{kwd}} ||
5151                                             $self->{level}->{must});
5152                  } else {
5153                    
5154                  }
5155                  $self->{entity__value} = $EntityChar->{$self->{kwd}};
5156                }
5157              $self->{entity__match} = 1;              $self->{entity__match} = 1;
5158                            
5159      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5260  sub _get_next_token ($) { Line 5549  sub _get_next_token ($) {
5549          ## XML5: Not defined yet.          ## XML5: Not defined yet.
5550    
5551          ## TODO:          ## TODO:
5552    
5553            if (not $self->{stop_processing} and
5554                not $self->{document}->xml_standalone) {
5555              $self->{parse_error}->(level => $self->{level}->{must}, type => 'stop processing', ## TODO: type
5556                              level => $self->{level}->{info});
5557              $self->{stop_processing} = 1;
5558            }
5559    
5560                    
5561      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
5562        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5482  sub _get_next_token ($) { Line 5779  sub _get_next_token ($) {
5779      }      }
5780        
5781          redo A;          redo A;
5782        } elsif ($self->{nc} == 0x0045) { # E        } elsif ($self->{nc} == 0x0045 or # E
5783                   $self->{nc} == 0x0065) { # e
5784          $self->{state} = MD_E_STATE;          $self->{state} = MD_E_STATE;
5785          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5786                    
# Line 5497  sub _get_next_token ($) { Line 5795  sub _get_next_token ($) {
5795      }      }
5796        
5797          redo A;          redo A;
5798        } elsif ($self->{nc} == 0x0041) { # A        } elsif ($self->{nc} == 0x0041 or # A
5799                   $self->{nc} == 0x0061) { # a
5800          $self->{state} = MD_ATTLIST_STATE;          $self->{state} = MD_ATTLIST_STATE;
5801          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5802                    
# Line 5512  sub _get_next_token ($) { Line 5811  sub _get_next_token ($) {
5811      }      }
5812        
5813          redo A;          redo A;
5814        } elsif ($self->{nc} == 0x004E) { # N        } elsif ($self->{nc} == 0x004E or # N
5815                   $self->{nc} == 0x006E) { # n
5816          $self->{state} = MD_NOTATION_STATE;          $self->{state} = MD_NOTATION_STATE;
5817          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
5818                    
# Line 5540  sub _get_next_token ($) { Line 5840  sub _get_next_token ($) {
5840        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.
5841        redo A;        redo A;
5842      } elsif ($self->{state} == MD_E_STATE) {      } elsif ($self->{state} == MD_E_STATE) {
5843        if ($self->{nc} == 0x004E) { # N        if ($self->{nc} == 0x004E or # N
5844              $self->{nc} == 0x006E) { # n
5845          $self->{state} = MD_ENTITY_STATE;          $self->{state} = MD_ENTITY_STATE;
5846          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5847                    
# Line 5555  sub _get_next_token ($) { Line 5856  sub _get_next_token ($) {
5856      }      }
5857        
5858          redo A;          redo A;
5859        } elsif ($self->{nc} == 0x004C) { # L        } elsif ($self->{nc} == 0x004C or # L
5860                   $self->{nc} == 0x006C) { # l
5861          ## XML5: <!ELEMENT> not supported.          ## XML5: <!ELEMENT> not supported.
5862          $self->{state} = MD_ELEMENT_STATE;          $self->{state} = MD_ELEMENT_STATE;
5863          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
# Line 5583  sub _get_next_token ($) { Line 5885  sub _get_next_token ($) {
5885          redo A;          redo A;
5886        }        }
5887      } elsif ($self->{state} == MD_ENTITY_STATE) {      } elsif ($self->{state} == MD_ENTITY_STATE) {
5888        if ($self->{nc} == {        if ($self->{nc} == [
5889              'EN' => 0x0054, # T              undef,
5890              'ENT' => 0x0049, # I              undef,
5891              'ENTI' => 0x0054, # T              0x0054, # T
5892            }->{$self->{kwd}}) {              0x0049, # I
5893                0x0054, # T
5894              ]->[length $self->{kwd}] or
5895              $self->{nc} == [
5896                undef,
5897                undef,
5898                0x0074, # t
5899                0x0069, # i
5900                0x0074, # t
5901              ]->[length $self->{kwd}]) {
5902          ## Stay in the state.          ## Stay in the state.
5903          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5904                    
# Line 5602  sub _get_next_token ($) { Line 5913  sub _get_next_token ($) {
5913      }      }
5914        
5915          redo A;          redo A;
5916        } elsif ($self->{kwd} eq 'ENTIT' and        } elsif ((length $self->{kwd}) == 5 and
5917                 $self->{nc} == 0x0059) { # Y                 ($self->{nc} == 0x0059 or # Y
5918          $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '', text => '',                  $self->{nc} == 0x0079)) { # y
5919            if ($self->{kwd} ne 'ENTIT' or $self->{nc} == 0x0079) {
5920              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
5921                              text => 'ENTITY',
5922                              line => $self->{line_prev},
5923                              column => $self->{column_prev} - 4);
5924            }
5925            $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '',
5926                         line => $self->{line_prev},                         line => $self->{line_prev},
5927                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 6};
5928          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
# Line 5632  sub _get_next_token ($) { Line 5950  sub _get_next_token ($) {
5950          redo A;          redo A;
5951        }        }
5952      } elsif ($self->{state} == MD_ELEMENT_STATE) {      } elsif ($self->{state} == MD_ELEMENT_STATE) {
5953        if ($self->{nc} == {        if ($self->{nc} == [
5954              'EL' => 0x0045, # E             undef,
5955              'ELE' => 0x004D, # M             undef,
5956              'ELEM' => 0x0045, # E             0x0045, # E
5957              'ELEME' => 0x004E, # N             0x004D, # M
5958            }->{$self->{kwd}}) {             0x0045, # E
5959               0x004E, # N
5960              ]->[length $self->{kwd}] or
5961              $self->{nc} == [
5962               undef,
5963               undef,
5964               0x0065, # e
5965               0x006D, # m
5966               0x0065, # e
5967               0x006E, # n
5968              ]->[length $self->{kwd}]) {
5969          ## Stay in the state.          ## Stay in the state.
5970          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5971                    
# Line 5652  sub _get_next_token ($) { Line 5980  sub _get_next_token ($) {
5980      }      }
5981        
5982          redo A;          redo A;
5983        } elsif ($self->{kwd} eq 'ELEMEN' and        } elsif ((length $self->{kwd}) == 6 and
5984                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
5985                    $self->{nc} == 0x0074)) { # t
5986            if ($self->{kwd} ne 'ELEMEN' or $self->{nc} == 0x0074) {
5987              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
5988                              text => 'ELEMENT',
5989                              line => $self->{line_prev},
5990                              column => $self->{column_prev} - 5);
5991            }
5992          $self->{ct} = {type => ELEMENT_TOKEN, name => '',          $self->{ct} = {type => ELEMENT_TOKEN, name => '',
5993                         line => $self->{line_prev},                         line => $self->{line_prev},
5994                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
5995          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
5996                    
5997      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5682  sub _get_next_token ($) { Line 6017  sub _get_next_token ($) {
6017          redo A;          redo A;
6018        }        }
6019      } elsif ($self->{state} == MD_ATTLIST_STATE) {      } elsif ($self->{state} == MD_ATTLIST_STATE) {
6020        if ($self->{nc} == {        if ($self->{nc} == [
6021              'A' => 0x0054, # T             undef,
6022              'AT' => 0x0054, # T             0x0054, # T
6023              'ATT' => 0x004C, # L             0x0054, # T
6024              'ATTL' => 0x0049, # I             0x004C, # L
6025              'ATTLI' => 0x0053, # S             0x0049, # I
6026            }->{$self->{kwd}}) {             0x0053, # S
6027              ]->[length $self->{kwd}] or
6028              $self->{nc} == [
6029               undef,
6030               0x0074, # t
6031               0x0074, # t
6032               0x006C, # l
6033               0x0069, # i
6034               0x0073, # s
6035              ]->[length $self->{kwd}]) {
6036          ## Stay in the state.          ## Stay in the state.
6037          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6038                    
# Line 5703  sub _get_next_token ($) { Line 6047  sub _get_next_token ($) {
6047      }      }
6048        
6049          redo A;          redo A;
6050        } elsif ($self->{kwd} eq 'ATTLIS' and        } elsif ((length $self->{kwd}) == 6 and
6051                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
6052                    $self->{nc} == 0x0074)) { # t
6053            if ($self->{kwd} ne 'ATTLIS' or $self->{nc} == 0x0074) {
6054              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6055                              text => 'ATTLIST',
6056                              line => $self->{line_prev},
6057                              column => $self->{column_prev} - 5);
6058            }
6059          $self->{ct} = {type => ATTLIST_TOKEN, name => '',          $self->{ct} = {type => ATTLIST_TOKEN, name => '',
6060                         attrdefs => [],                         attrdefs => [],
6061                         line => $self->{line_prev},                         line => $self->{line_prev},
6062                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
6063          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6064                    
6065      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5734  sub _get_next_token ($) { Line 6085  sub _get_next_token ($) {
6085          redo A;          redo A;
6086        }        }
6087      } elsif ($self->{state} == MD_NOTATION_STATE) {      } elsif ($self->{state} == MD_NOTATION_STATE) {
6088        if ($self->{nc} == {        if ($self->{nc} == [
6089              'N' => 0x004F, # O             undef,
6090              'NO' => 0x0054, # T             0x004F, # O
6091              'NOT' => 0x0041, # A             0x0054, # T
6092              'NOTA' => 0x0054, # T             0x0041, # A
6093              'NOTAT' => 0x0049, # I             0x0054, # T
6094              'NOTATI' => 0x004F, # O             0x0049, # I
6095            }->{$self->{kwd}}) {             0x004F, # O
6096              ]->[length $self->{kwd}] or
6097              $self->{nc} == [
6098               undef,
6099               0x006F, # o
6100               0x0074, # t
6101               0x0061, # a
6102               0x0074, # t
6103               0x0069, # i
6104               0x006F, # o
6105              ]->[length $self->{kwd}]) {
6106          ## Stay in the state.          ## Stay in the state.
6107          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
6108                    
# Line 5756  sub _get_next_token ($) { Line 6117  sub _get_next_token ($) {
6117      }      }
6118        
6119          redo A;          redo A;
6120        } elsif ($self->{kwd} eq 'NOTATIO' and        } elsif ((length $self->{kwd}) == 7 and
6121                 $self->{nc} == 0x004E) { # N                 ($self->{nc} == 0x004E or # N
6122                    $self->{nc} == 0x006E)) { # n
6123            if ($self->{kwd} ne 'NOTATIO' or $self->{nc} == 0x006E) {
6124              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
6125                              text => 'NOTATION',
6126                              line => $self->{line_prev},
6127                              column => $self->{column_prev} - 6);
6128            }
6129          $self->{ct} = {type => NOTATION_TOKEN, name => '',          $self->{ct} = {type => NOTATION_TOKEN, name => '',
6130                         line => $self->{line_prev},                         line => $self->{line_prev},
6131                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 8};
6132          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6133                    
6134      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5972  sub _get_next_token ($) { Line 6340  sub _get_next_token ($) {
6340          if ($self->{ct}->{type} == ATTLIST_TOKEN) {          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6341            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
6342          } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {          } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
6343            ## TODO: ...            $self->{state} = AFTER_ELEMENT_NAME_STATE;
           $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;  
6344          } else { # ENTITY/NOTATION          } else { # ENTITY/NOTATION
6345            $self->{state} = AFTER_DOCTYPE_NAME_STATE;            $self->{state} = AFTER_DOCTYPE_NAME_STATE;
6346          }          }
# Line 7271  sub _get_next_token ($) { Line 7638  sub _get_next_token ($) {
7638          ## Reconsume.          ## Reconsume.
7639          redo A;          redo A;
7640        }        }
7641        } elsif ($self->{state} == NDATA_STATE) {
7642          ## ASCII case-insensitive
7643          if ($self->{nc} == [
7644                undef,
7645                0x0044, # D
7646                0x0041, # A
7647                0x0054, # T
7648              ]->[length $self->{kwd}] or
7649              $self->{nc} == [
7650                undef,
7651                0x0064, # d
7652                0x0061, # a
7653                0x0074, # t
7654              ]->[length $self->{kwd}]) {
7655            
7656            ## Stay in the state.
7657            $self->{kwd} .= chr $self->{nc};
7658            
7659        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7660          $self->{line_prev} = $self->{line};
7661          $self->{column_prev} = $self->{column};
7662          $self->{column}++;
7663          $self->{nc}
7664              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7665        } else {
7666          $self->{set_nc}->($self);
7667        }
7668      
7669            redo A;
7670          } elsif ((length $self->{kwd}) == 4 and
7671                   ($self->{nc} == 0x0041 or # A
7672                    $self->{nc} == 0x0061)) { # a
7673            if ($self->{kwd} ne 'NDAT' or $self->{nc} == 0x0061) { # a
7674              
7675              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
7676                              text => 'NDATA',
7677                              line => $self->{line_prev},
7678                              column => $self->{column_prev} - 4);
7679            } else {
7680              
7681            }
7682            $self->{state} = AFTER_NDATA_STATE;
7683            
7684        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7685          $self->{line_prev} = $self->{line};
7686          $self->{column_prev} = $self->{column};
7687          $self->{column}++;
7688          $self->{nc}
7689              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7690        } else {
7691          $self->{set_nc}->($self);
7692        }
7693      
7694            redo A;
7695          } else {
7696            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7697                            line => $self->{line_prev},
7698                            column => $self->{column_prev} + 1
7699                                - length $self->{kwd});
7700            
7701            $self->{state} = BOGUS_MD_STATE;
7702            ## Reconsume.
7703            redo A;
7704          }
7705        } elsif ($self->{state} == AFTER_NDATA_STATE) {
7706          if ($is_space->{$self->{nc}}) {
7707            $self->{state} = BEFORE_NOTATION_NAME_STATE;
7708            
7709        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7710          $self->{line_prev} = $self->{line};
7711          $self->{column_prev} = $self->{column};
7712          $self->{column}++;
7713          $self->{nc}
7714              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7715        } else {
7716          $self->{set_nc}->($self);
7717        }
7718      
7719            redo A;
7720          } elsif ($self->{nc} == 0x003E) { # >
7721            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7722            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7723            
7724        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7725          $self->{line_prev} = $self->{line};
7726          $self->{column_prev} = $self->{column};
7727          $self->{column}++;
7728          $self->{nc}
7729              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7730        } else {
7731          $self->{set_nc}->($self);
7732        }
7733      
7734            return  ($self->{ct}); # ENTITY
7735            redo A;
7736          } elsif ($self->{nc} == -1) {
7737            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7738            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7739            
7740        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7741          $self->{line_prev} = $self->{line};
7742          $self->{column_prev} = $self->{column};
7743          $self->{column}++;
7744          $self->{nc}
7745              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7746        } else {
7747          $self->{set_nc}->($self);
7748        }
7749      
7750            return  ($self->{ct}); # ENTITY
7751            redo A;
7752          } else {
7753            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7754                            line => $self->{line_prev},
7755                            column => $self->{column_prev} + 1
7756                                - length $self->{kwd});
7757            $self->{state} = BOGUS_MD_STATE;
7758            ## Reconsume.
7759            redo A;
7760          }
7761        } elsif ($self->{state} == BEFORE_NOTATION_NAME_STATE) {
7762          if ($is_space->{$self->{nc}}) {
7763            ## Stay in the state.
7764            
7765        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7766          $self->{line_prev} = $self->{line};
7767          $self->{column_prev} = $self->{column};
7768          $self->{column}++;
7769          $self->{nc}
7770              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7771        } else {
7772          $self->{set_nc}->($self);
7773        }
7774      
7775            redo A;
7776          } elsif ($self->{nc} == 0x003E) { # >
7777            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7778            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7779            
7780        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7781          $self->{line_prev} = $self->{line};
7782          $self->{column_prev} = $self->{column};
7783          $self->{column}++;
7784          $self->{nc}
7785              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7786        } else {
7787          $self->{set_nc}->($self);
7788        }
7789      
7790            return  ($self->{ct}); # ENTITY
7791            redo A;
7792          } elsif ($self->{nc} == -1) {
7793            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7794            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7795            
7796        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7797          $self->{line_prev} = $self->{line};
7798          $self->{column_prev} = $self->{column};
7799          $self->{column}++;
7800          $self->{nc}
7801              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7802        } else {
7803          $self->{set_nc}->($self);
7804        }
7805      
7806            return  ($self->{ct}); # ENTITY
7807            redo A;
7808          } else {
7809            $self->{ct}->{notation} = chr $self->{nc}; # ENTITY
7810            $self->{state} = NOTATION_NAME_STATE;
7811            
7812        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7813          $self->{line_prev} = $self->{line};
7814          $self->{column_prev} = $self->{column};
7815          $self->{column}++;
7816          $self->{nc}
7817              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7818        } else {
7819          $self->{set_nc}->($self);
7820        }
7821      
7822            redo A;
7823          }
7824        } elsif ($self->{state} == NOTATION_NAME_STATE) {
7825          if ($is_space->{$self->{nc}}) {
7826            $self->{state} = AFTER_MD_DEF_STATE;
7827            
7828        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7829          $self->{line_prev} = $self->{line};
7830          $self->{column_prev} = $self->{column};
7831          $self->{column}++;
7832          $self->{nc}
7833              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7834        } else {
7835          $self->{set_nc}->($self);
7836        }
7837      
7838            redo A;
7839          } elsif ($self->{nc} == 0x003E) { # >
7840            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7841            
7842        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7843          $self->{line_prev} = $self->{line};
7844          $self->{column_prev} = $self->{column};
7845          $self->{column}++;
7846          $self->{nc}
7847              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7848        } else {
7849          $self->{set_nc}->($self);
7850        }
7851      
7852            return  ($self->{ct}); # ENTITY
7853            redo A;
7854          } elsif ($self->{nc} == -1) {
7855            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7856            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7857            
7858        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7859          $self->{line_prev} = $self->{line};
7860          $self->{column_prev} = $self->{column};
7861          $self->{column}++;
7862          $self->{nc}
7863              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7864        } else {
7865          $self->{set_nc}->($self);
7866        }
7867      
7868            return  ($self->{ct}); # ENTITY
7869            redo A;
7870          } else {
7871            $self->{ct}->{notation} .= chr $self->{nc}; # ENTITY
7872            ## Stay in the state.
7873            
7874        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7875          $self->{line_prev} = $self->{line};
7876          $self->{column_prev} = $self->{column};
7877          $self->{column}++;
7878          $self->{nc}
7879              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7880        } else {
7881          $self->{set_nc}->($self);
7882        }
7883      
7884            redo A;
7885          }
7886        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE) {
7887          if ($self->{nc} == 0x0022) { # "
7888            $self->{state} = AFTER_MD_DEF_STATE;
7889            
7890        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7891          $self->{line_prev} = $self->{line};
7892          $self->{column_prev} = $self->{column};
7893          $self->{column}++;
7894          $self->{nc}
7895              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7896        } else {
7897          $self->{set_nc}->($self);
7898        }
7899      
7900            redo A;
7901          } elsif ($self->{nc} == 0x0026) { # &
7902            $self->{prev_state} = $self->{state};
7903            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
7904            $self->{entity_add} = 0x0022; # "
7905            
7906        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7907          $self->{line_prev} = $self->{line};
7908          $self->{column_prev} = $self->{column};
7909          $self->{column}++;
7910          $self->{nc}
7911              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7912        } else {
7913          $self->{set_nc}->($self);
7914        }
7915      
7916            redo A;
7917    ## TODO: %
7918          } elsif ($self->{nc} == -1) {
7919            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
7920            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7921            ## Reconsume.
7922            return  ($self->{ct}); # ENTITY
7923            redo A;
7924          } else {
7925            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
7926            
7927        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7928          $self->{line_prev} = $self->{line};
7929          $self->{column_prev} = $self->{column};
7930          $self->{column}++;
7931          $self->{nc}
7932              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7933        } else {
7934          $self->{set_nc}->($self);
7935        }
7936      
7937            redo A;
7938          }
7939        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE) {
7940          if ($self->{nc} == 0x0027) { # '
7941            $self->{state} = AFTER_MD_DEF_STATE;
7942            
7943        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7944          $self->{line_prev} = $self->{line};
7945          $self->{column_prev} = $self->{column};
7946          $self->{column}++;
7947          $self->{nc}
7948              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7949        } else {
7950          $self->{set_nc}->($self);
7951        }
7952      
7953            redo A;
7954          } elsif ($self->{nc} == 0x0026) { # &
7955            $self->{prev_state} = $self->{state};
7956            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
7957            $self->{entity_add} = 0x0027; # '
7958            
7959        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7960          $self->{line_prev} = $self->{line};
7961          $self->{column_prev} = $self->{column};
7962          $self->{column}++;
7963          $self->{nc}
7964              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7965        } else {
7966          $self->{set_nc}->($self);
7967        }
7968      
7969            redo A;
7970    ## TODO: %
7971          } elsif ($self->{nc} == -1) {
7972            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
7973            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7974            ## Reconsume.
7975            return  ($self->{ct}); # ENTITY
7976            redo A;
7977          } else {
7978            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
7979            
7980        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7981          $self->{line_prev} = $self->{line};
7982          $self->{column_prev} = $self->{column};
7983          $self->{column}++;
7984          $self->{nc}
7985              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7986        } else {
7987          $self->{set_nc}->($self);
7988        }
7989      
7990            redo A;
7991          }
7992        } elsif ($self->{state} == ENTITY_VALUE_ENTITY_STATE) {
7993          if ($is_space->{$self->{nc}} or
7994              {
7995                0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
7996                $self->{entity_add} => 1,
7997              }->{$self->{nc}}) {
7998            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
7999                            line => $self->{line_prev},
8000                            column => $self->{column_prev}
8001                                + ($self->{nc} == -1 ? 1 : 0));
8002            ## Don't consume
8003            ## Return nothing.
8004            #
8005          } elsif ($self->{nc} == 0x0023) { # #
8006            $self->{ca} = $self->{ct};
8007            $self->{state} = ENTITY_HASH_STATE;
8008            $self->{kwd} = '#';
8009            
8010        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8011          $self->{line_prev} = $self->{line};
8012          $self->{column_prev} = $self->{column};
8013          $self->{column}++;
8014          $self->{nc}
8015              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8016        } else {
8017          $self->{set_nc}->($self);
8018        }
8019      
8020            redo A;
8021          } else {
8022            #
8023          }
8024    
8025          $self->{ct}->{value} .= '&';
8026          $self->{state} = $self->{prev_state};
8027          ## Reconsume.
8028          redo A;
8029        } elsif ($self->{state} == AFTER_ELEMENT_NAME_STATE) {
8030          if ($is_space->{$self->{nc}}) {
8031            $self->{state} = BEFORE_ELEMENT_CONTENT_STATE;
8032            
8033        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8034          $self->{line_prev} = $self->{line};
8035          $self->{column_prev} = $self->{column};
8036          $self->{column}++;
8037          $self->{nc}
8038              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8039        } else {
8040          $self->{set_nc}->($self);
8041        }
8042      
8043            redo A;
8044          } elsif ($self->{nc} == 0x0028) { # (
8045            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8046            $self->{ct}->{content} = ['('];
8047            $self->{group_depth} = 1;
8048            
8049        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8050          $self->{line_prev} = $self->{line};
8051          $self->{column_prev} = $self->{column};
8052          $self->{column}++;
8053          $self->{nc}
8054              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8055        } else {
8056          $self->{set_nc}->($self);
8057        }
8058      
8059            redo A;
8060          } elsif ($self->{nc} == 0x003E) { # >
8061            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
8062            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8063            
8064        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8065          $self->{line_prev} = $self->{line};
8066          $self->{column_prev} = $self->{column};
8067          $self->{column}++;
8068          $self->{nc}
8069              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8070        } else {
8071          $self->{set_nc}->($self);
8072        }
8073      
8074            return  ($self->{ct}); # ELEMENT
8075            redo A;
8076          } elsif ($self->{nc} == -1) {
8077            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8078            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8079            
8080        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8081          $self->{line_prev} = $self->{line};
8082          $self->{column_prev} = $self->{column};
8083          $self->{column}++;
8084          $self->{nc}
8085              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8086        } else {
8087          $self->{set_nc}->($self);
8088        }
8089      
8090            return  ($self->{ct}); # ELEMENT
8091            redo A;
8092          } else {
8093            $self->{ct}->{content} = [chr $self->{nc}];
8094            $self->{state} = CONTENT_KEYWORD_STATE;
8095            
8096        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8097          $self->{line_prev} = $self->{line};
8098          $self->{column_prev} = $self->{column};
8099          $self->{column}++;
8100          $self->{nc}
8101              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8102        } else {
8103          $self->{set_nc}->($self);
8104        }
8105      
8106            redo A;
8107          }
8108        } elsif ($self->{state} == CONTENT_KEYWORD_STATE) {
8109          if ($is_space->{$self->{nc}}) {
8110            $self->{state} = AFTER_MD_DEF_STATE;
8111            
8112        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8113          $self->{line_prev} = $self->{line};
8114          $self->{column_prev} = $self->{column};
8115          $self->{column}++;
8116          $self->{nc}
8117              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8118        } else {
8119          $self->{set_nc}->($self);
8120        }
8121      
8122            redo A;
8123          } elsif ($self->{nc} == 0x003E) { # >
8124            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8125            
8126        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8127          $self->{line_prev} = $self->{line};
8128          $self->{column_prev} = $self->{column};
8129          $self->{column}++;
8130          $self->{nc}
8131              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8132        } else {
8133          $self->{set_nc}->($self);
8134        }
8135      
8136            return  ($self->{ct}); # ELEMENT
8137            redo A;
8138          } elsif ($self->{nc} == -1) {
8139            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8140            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8141            
8142        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8143          $self->{line_prev} = $self->{line};
8144          $self->{column_prev} = $self->{column};
8145          $self->{column}++;
8146          $self->{nc}
8147              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8148        } else {
8149          $self->{set_nc}->($self);
8150        }
8151      
8152            return  ($self->{ct}); # ELEMENT
8153            redo A;
8154          } else {
8155            $self->{ct}->{content}->[-1] .= chr $self->{nc}; # ELEMENT
8156            ## Stay in the state.
8157            
8158        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8159          $self->{line_prev} = $self->{line};
8160          $self->{column_prev} = $self->{column};
8161          $self->{column}++;
8162          $self->{nc}
8163              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8164        } else {
8165          $self->{set_nc}->($self);
8166        }
8167      
8168            redo A;
8169          }
8170        } elsif ($self->{state} == AFTER_CM_GROUP_OPEN_STATE) {
8171          if ($is_space->{$self->{nc}}) {
8172            ## Stay in the state.
8173            
8174        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8175          $self->{line_prev} = $self->{line};
8176          $self->{column_prev} = $self->{column};
8177          $self->{column}++;
8178          $self->{nc}
8179              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8180        } else {
8181          $self->{set_nc}->($self);
8182        }
8183      
8184            redo A;
8185          } elsif ($self->{nc} == 0x0028) { # (
8186            $self->{group_depth}++;
8187            push @{$self->{ct}->{content}}, chr $self->{nc};
8188            ## Stay in the state.
8189            
8190        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8191          $self->{line_prev} = $self->{line};
8192          $self->{column_prev} = $self->{column};
8193          $self->{column}++;
8194          $self->{nc}
8195              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8196        } else {
8197          $self->{set_nc}->($self);
8198        }
8199      
8200            redo A;
8201          } elsif ($self->{nc} == 0x007C or # |
8202                   $self->{nc} == 0x002C) { # ,
8203            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8204            ## Stay in the state.
8205            
8206        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8207          $self->{line_prev} = $self->{line};
8208          $self->{column_prev} = $self->{column};
8209          $self->{column}++;
8210          $self->{nc}
8211              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8212        } else {
8213          $self->{set_nc}->($self);
8214        }
8215      
8216            redo A;
8217          } elsif ($self->{nc} == 0x0029) { # )
8218            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8219            push @{$self->{ct}->{content}}, chr $self->{nc};
8220            $self->{group_depth}--;
8221            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8222            
8223        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8224          $self->{line_prev} = $self->{line};
8225          $self->{column_prev} = $self->{column};
8226          $self->{column}++;
8227          $self->{nc}
8228              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8229        } else {
8230          $self->{set_nc}->($self);
8231        }
8232      
8233            redo A;
8234          } elsif ($self->{nc} == 0x003E) { # >
8235            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8236            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8237            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8238            
8239        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8240          $self->{line_prev} = $self->{line};
8241          $self->{column_prev} = $self->{column};
8242          $self->{column}++;
8243          $self->{nc}
8244              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8245        } else {
8246          $self->{set_nc}->($self);
8247        }
8248      
8249            return  ($self->{ct}); # ELEMENT
8250            redo A;
8251          } elsif ($self->{nc} == -1) {
8252            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8253            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8254            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8255            
8256        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8257          $self->{line_prev} = $self->{line};
8258          $self->{column_prev} = $self->{column};
8259          $self->{column}++;
8260          $self->{nc}
8261              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8262        } else {
8263          $self->{set_nc}->($self);
8264        }
8265      
8266            return  ($self->{ct}); # ELEMENT
8267            redo A;
8268          } else {
8269            push @{$self->{ct}->{content}}, chr $self->{nc};
8270            $self->{state} = CM_ELEMENT_NAME_STATE;
8271            
8272        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8273          $self->{line_prev} = $self->{line};
8274          $self->{column_prev} = $self->{column};
8275          $self->{column}++;
8276          $self->{nc}
8277              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8278        } else {
8279          $self->{set_nc}->($self);
8280        }
8281      
8282            redo A;
8283          }
8284        } elsif ($self->{state} == CM_ELEMENT_NAME_STATE) {
8285          if ($is_space->{$self->{nc}}) {
8286            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8287            
8288        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8289          $self->{line_prev} = $self->{line};
8290          $self->{column_prev} = $self->{column};
8291          $self->{column}++;
8292          $self->{nc}
8293              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8294        } else {
8295          $self->{set_nc}->($self);
8296        }
8297      
8298            redo A;
8299          } elsif ($self->{nc} == 0x002A or # *
8300                   $self->{nc} == 0x002B or # +
8301                   $self->{nc} == 0x003F) { # ?
8302            push @{$self->{ct}->{content}}, chr $self->{nc};
8303            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8304            
8305        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8306          $self->{line_prev} = $self->{line};
8307          $self->{column_prev} = $self->{column};
8308          $self->{column}++;
8309          $self->{nc}
8310              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8311        } else {
8312          $self->{set_nc}->($self);
8313        }
8314      
8315            redo A;
8316          } elsif ($self->{nc} == 0x007C or # |
8317                   $self->{nc} == 0x002C) { # ,
8318            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8319            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8320            
8321        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8322          $self->{line_prev} = $self->{line};
8323          $self->{column_prev} = $self->{column};
8324          $self->{column}++;
8325          $self->{nc}
8326              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8327        } else {
8328          $self->{set_nc}->($self);
8329        }
8330      
8331            redo A;
8332          } elsif ($self->{nc} == 0x0029) { # )
8333            $self->{group_depth}--;
8334            push @{$self->{ct}->{content}}, chr $self->{nc};
8335            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8336            
8337        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8338          $self->{line_prev} = $self->{line};
8339          $self->{column_prev} = $self->{column};
8340          $self->{column}++;
8341          $self->{nc}
8342              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8343        } else {
8344          $self->{set_nc}->($self);
8345        }
8346      
8347            redo A;
8348          } elsif ($self->{nc} == 0x003E) { # >
8349            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8350            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8351            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8352            
8353        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8354          $self->{line_prev} = $self->{line};
8355          $self->{column_prev} = $self->{column};
8356          $self->{column}++;
8357          $self->{nc}
8358              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8359        } else {
8360          $self->{set_nc}->($self);
8361        }
8362      
8363            return  ($self->{ct}); # ELEMENT
8364            redo A;
8365          } elsif ($self->{nc} == -1) {
8366            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8367            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8368            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8369            
8370        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8371          $self->{line_prev} = $self->{line};
8372          $self->{column_prev} = $self->{column};
8373          $self->{column}++;
8374          $self->{nc}
8375              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8376        } else {
8377          $self->{set_nc}->($self);
8378        }
8379      
8380            return  ($self->{ct}); # ELEMENT
8381            redo A;
8382          } else {
8383            $self->{ct}->{content}->[-1] .= chr $self->{nc};
8384            ## Stay in the state.
8385            
8386        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8387          $self->{line_prev} = $self->{line};
8388          $self->{column_prev} = $self->{column};
8389          $self->{column}++;
8390          $self->{nc}
8391              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8392        } else {
8393          $self->{set_nc}->($self);
8394        }
8395      
8396            redo A;
8397          }
8398        } elsif ($self->{state} == AFTER_CM_ELEMENT_NAME_STATE) {
8399          if ($is_space->{$self->{nc}}) {
8400            ## Stay in the state.
8401            
8402        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8403          $self->{line_prev} = $self->{line};
8404          $self->{column_prev} = $self->{column};
8405          $self->{column}++;
8406          $self->{nc}
8407              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8408        } else {
8409          $self->{set_nc}->($self);
8410        }
8411      
8412            redo A;
8413          } elsif ($self->{nc} == 0x007C or # |
8414                   $self->{nc} == 0x002C) { # ,
8415            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8416            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8417            
8418        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8419          $self->{line_prev} = $self->{line};
8420          $self->{column_prev} = $self->{column};
8421          $self->{column}++;
8422          $self->{nc}
8423              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8424        } else {
8425          $self->{set_nc}->($self);
8426        }
8427      
8428            redo A;
8429          } elsif ($self->{nc} == 0x0029) { # )
8430            $self->{group_depth}--;
8431            push @{$self->{ct}->{content}}, chr $self->{nc};
8432            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8433            
8434        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8435          $self->{line_prev} = $self->{line};
8436          $self->{column_prev} = $self->{column};
8437          $self->{column}++;
8438          $self->{nc}
8439              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8440        } else {
8441          $self->{set_nc}->($self);
8442        }
8443      
8444            redo A;
8445          } elsif ($self->{nc} == 0x003E) { # >
8446            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8447            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8448            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8449            
8450        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8451          $self->{line_prev} = $self->{line};
8452          $self->{column_prev} = $self->{column};
8453          $self->{column}++;
8454          $self->{nc}
8455              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8456        } else {
8457          $self->{set_nc}->($self);
8458        }
8459      
8460            return  ($self->{ct}); # ELEMENT
8461            redo A;
8462          } elsif ($self->{nc} == -1) {
8463            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8464            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8465            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8466            
8467        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8468          $self->{line_prev} = $self->{line};
8469          $self->{column_prev} = $self->{column};
8470          $self->{column}++;
8471          $self->{nc}
8472              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8473        } else {
8474          $self->{set_nc}->($self);
8475        }
8476      
8477            return  ($self->{ct}); # ELEMENT
8478            redo A;
8479          } else {
8480            $self->{parse_error}->(level => $self->{level}->{must}, type => 'after element name'); ## TODO: type
8481            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8482            $self->{state} = BOGUS_MD_STATE;
8483            
8484        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8485          $self->{line_prev} = $self->{line};
8486          $self->{column_prev} = $self->{column};
8487          $self->{column}++;
8488          $self->{nc}
8489              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8490        } else {
8491          $self->{set_nc}->($self);
8492        }
8493      
8494            redo A;
8495          }
8496        } elsif ($self->{state} == AFTER_CM_GROUP_CLOSE_STATE) {
8497          if ($is_space->{$self->{nc}}) {
8498            if ($self->{group_depth}) {
8499              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8500            } else {
8501              $self->{state} = AFTER_MD_DEF_STATE;
8502            }
8503            
8504        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8505          $self->{line_prev} = $self->{line};
8506          $self->{column_prev} = $self->{column};
8507          $self->{column}++;
8508          $self->{nc}
8509              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8510        } else {
8511          $self->{set_nc}->($self);
8512        }
8513      
8514            redo A;
8515          } elsif ($self->{nc} == 0x002A or # *
8516                   $self->{nc} == 0x002B or # +
8517                   $self->{nc} == 0x003F) { # ?
8518            push @{$self->{ct}->{content}}, chr $self->{nc};
8519            if ($self->{group_depth}) {
8520              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8521            } else {
8522              $self->{state} = AFTER_MD_DEF_STATE;
8523            }
8524            
8525        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8526          $self->{line_prev} = $self->{line};
8527          $self->{column_prev} = $self->{column};
8528          $self->{column}++;
8529          $self->{nc}
8530              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8531        } else {
8532          $self->{set_nc}->($self);
8533        }
8534      
8535            redo A;
8536          } elsif ($self->{nc} == 0x0029) { # )
8537            if ($self->{group_depth}) {
8538              $self->{group_depth}--;
8539              push @{$self->{ct}->{content}}, chr $self->{nc};
8540              ## Stay in the state.
8541              
8542        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8543          $self->{line_prev} = $self->{line};
8544          $self->{column_prev} = $self->{column};
8545          $self->{column}++;
8546          $self->{nc}
8547              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8548        } else {
8549          $self->{set_nc}->($self);
8550        }
8551      
8552              redo A;
8553            } else {
8554              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8555              $self->{state} = BOGUS_MD_STATE;
8556              ## Reconsume.
8557              redo A;
8558            }
8559          } elsif ($self->{nc} == 0x003E) { # >
8560            if ($self->{group_depth}) {
8561              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8562              push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8563            }
8564            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8565            
8566        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8567          $self->{line_prev} = $self->{line};
8568          $self->{column_prev} = $self->{column};
8569          $self->{column}++;
8570          $self->{nc}
8571              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8572        } else {
8573          $self->{set_nc}->($self);
8574        }
8575      
8576            return  ($self->{ct}); # ELEMENT
8577            redo A;
8578          } elsif ($self->{nc} == -1) {
8579            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8580            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8581            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8582            
8583        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8584          $self->{line_prev} = $self->{line};
8585          $self->{column_prev} = $self->{column};
8586          $self->{column}++;
8587          $self->{nc}
8588              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8589        } else {
8590          $self->{set_nc}->($self);
8591        }
8592      
8593            return  ($self->{ct}); # ELEMENT
8594            redo A;
8595          } else {
8596            if ($self->{group_depth}) {
8597              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8598            } else {
8599              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8600              $self->{state} = BOGUS_MD_STATE;
8601            }
8602            ## Reconsume.
8603            redo A;
8604          }
8605        } elsif ($self->{state} == AFTER_MD_DEF_STATE) {
8606          if ($is_space->{$self->{nc}}) {
8607            ## Stay in the state.
8608            
8609        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8610          $self->{line_prev} = $self->{line};
8611          $self->{column_prev} = $self->{column};
8612          $self->{column}++;
8613          $self->{nc}
8614              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8615        } else {
8616          $self->{set_nc}->($self);
8617        }
8618      
8619            redo A;
8620          } elsif ($self->{nc} == 0x003E) { # >
8621            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8622            
8623        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8624          $self->{line_prev} = $self->{line};
8625          $self->{column_prev} = $self->{column};
8626          $self->{column}++;
8627          $self->{nc}
8628              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8629        } else {
8630          $self->{set_nc}->($self);
8631        }
8632      
8633            return  ($self->{ct}); # ENTITY/ELEMENT
8634            redo A;
8635          } elsif ($self->{nc} == -1) {
8636            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8637            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8638            
8639        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8640          $self->{line_prev} = $self->{line};
8641          $self->{column_prev} = $self->{column};
8642          $self->{column}++;
8643          $self->{nc}
8644              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8645        } else {
8646          $self->{set_nc}->($self);
8647        }
8648      
8649            return  ($self->{ct}); # ENTITY/ELEMENT
8650            redo A;
8651          } else {
8652            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8653            $self->{state} = BOGUS_MD_STATE;
8654            ## Reconsume.
8655            redo A;
8656          }
8657      } elsif ($self->{state} == BOGUS_MD_STATE) {      } elsif ($self->{state} == BOGUS_MD_STATE) {
8658        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
8659          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;

Legend:
Removed from v.1.16  
changed lines
  Added in v.1.29

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24