/[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.17 by wakaba, Sun Oct 19 04:39:25 2008 UTC revision 1.32 by wakaba, Sat Sep 5 09:57:55 2009 UTC
# Line 105  sub COMMENT_START_STATE () { 14 } Line 105  sub COMMENT_START_STATE () { 14 }
105  sub COMMENT_START_DASH_STATE () { 15 }  sub COMMENT_START_DASH_STATE () { 15 }
106  sub COMMENT_STATE () { 16 }  sub COMMENT_STATE () { 16 }
107  sub COMMENT_END_STATE () { 17 }  sub COMMENT_END_STATE () { 17 }
108    sub COMMENT_END_BANG_STATE () { 102 }
109    sub COMMENT_END_SPACE_STATE () { 103 } ## LAST
110  sub COMMENT_END_DASH_STATE () { 18 }  sub COMMENT_END_DASH_STATE () { 18 }
111  sub BOGUS_COMMENT_STATE () { 19 }  sub BOGUS_COMMENT_STATE () { 19 }
112  sub DOCTYPE_STATE () { 20 }  sub DOCTYPE_STATE () { 20 }
# Line 177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO Line 179  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO
179  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }
180  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }
181  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }
182  sub BOGUS_MD_STATE () { 85 }  sub BEFORE_NDATA_STATE () { 85 }
183    sub NDATA_STATE () { 86 }
184    sub AFTER_NDATA_STATE () { 87 }
185    sub BEFORE_NOTATION_NAME_STATE () { 88 }
186    sub NOTATION_NAME_STATE () { 89 }
187    sub DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE () { 90 }
188    sub DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE () { 91 }
189    sub ENTITY_VALUE_ENTITY_STATE () { 92 }
190    sub AFTER_ELEMENT_NAME_STATE () { 93 }
191    sub BEFORE_ELEMENT_CONTENT_STATE () { 94 }
192    sub CONTENT_KEYWORD_STATE () { 95 }
193    sub AFTER_CM_GROUP_OPEN_STATE () { 96 }
194    sub CM_ELEMENT_NAME_STATE () { 97 }
195    sub AFTER_CM_ELEMENT_NAME_STATE () { 98 }
196    sub AFTER_CM_GROUP_CLOSE_STATE () { 99 }
197    sub AFTER_MD_DEF_STATE () { 100 }
198    sub BOGUS_MD_STATE () { 101 }
199    
200  ## Tree constructor state constants (see Whatpm::HTML for the full  ## Tree constructor state constants (see Whatpm::HTML for the full
201  ## list and descriptions)  ## list and descriptions)
# Line 1232  sub _get_next_token ($) { Line 1250  sub _get_next_token ($) {
1250          if ({          if ({
1251               0x0022 => 1, # "               0x0022 => 1, # "
1252               0x0027 => 1, # '               0x0027 => 1, # '
1253                 0x003C => 1, # <
1254               0x003D => 1, # =               0x003D => 1, # =
1255              }->{$self->{nc}}) {              }->{$self->{nc}}) {
1256                        
# Line 1414  sub _get_next_token ($) { Line 1433  sub _get_next_token ($) {
1433    
1434          redo A;          redo A;
1435        } else {        } else {
1436          if ($self->{nc} == 0x0022 or # "          if ({
1437              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1438                 0x0027 => 1, # '
1439                 0x003C => 1, # <
1440                }->{$self->{nc}}) {
1441                        
1442            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1443            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');
# Line 1586  sub _get_next_token ($) { Line 1608  sub _get_next_token ($) {
1608                        
1609          }          }
1610    
1611          if ($self->{nc} == 0x0022 or # "          if ({
1612              $self->{nc} == 0x0027) { # '               0x0022 => 1, # "
1613                 0x0027 => 1, # '
1614                 0x003C => 1, # <
1615                }->{$self->{nc}}) {
1616                        
1617            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1618            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bad attribute name');
# Line 1724  sub _get_next_token ($) { Line 1749  sub _get_next_token ($) {
1749    
1750          redo A;          redo A;
1751        } else {        } else {
1752          if ($self->{nc} == 0x003D) { # =          if ($self->{nc} == 0x003D or $self->{nc} == 0x003C) { # =, <
1753                        
1754            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1755            $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 1825  sub _get_next_token ($) {
1825      }      }
1826        
1827          redo A;          redo A;
1828          } elsif ($self->{is_xml} and
1829                   $is_space->{$self->{nc}}) {
1830            
1831            $self->{ca}->{value} .= ' ';
1832            ## Stay in the state.
1833            
1834        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1835          $self->{line_prev} = $self->{line};
1836          $self->{column_prev} = $self->{column};
1837          $self->{column}++;
1838          $self->{nc}
1839              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1840        } else {
1841          $self->{set_nc}->($self);
1842        }
1843      
1844            redo A;
1845        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1846          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1847          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1847  sub _get_next_token ($) { Line 1889  sub _get_next_token ($) {
1889          }          }
1890          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1891          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1892                                q["&<],                                qq["&<\x09\x0C\x20],
1893                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1894    
1895          ## Stay in the state          ## Stay in the state
# Line 1914  sub _get_next_token ($) { Line 1956  sub _get_next_token ($) {
1956      }      }
1957        
1958          redo A;          redo A;
1959          } elsif ($self->{is_xml} and
1960                   $is_space->{$self->{nc}}) {
1961            
1962            $self->{ca}->{value} .= ' ';
1963            ## Stay in the state.
1964            
1965        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
1966          $self->{line_prev} = $self->{line};
1967          $self->{column_prev} = $self->{column};
1968          $self->{column}++;
1969          $self->{nc}
1970              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
1971        } else {
1972          $self->{set_nc}->($self);
1973        }
1974      
1975            redo A;
1976        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1977          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');          $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed attribute value');
1978          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1961  sub _get_next_token ($) { Line 2020  sub _get_next_token ($) {
2020          }          }
2021          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2022          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2023                                q['&<],                                qq['&<\x09\x0C\x20],
2024                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2025    
2026          ## Stay in the state          ## Stay in the state
# Line 2133  sub _get_next_token ($) { Line 2192  sub _get_next_token ($) {
2192               0x0022 => 1, # "               0x0022 => 1, # "
2193               0x0027 => 1, # '               0x0027 => 1, # '
2194               0x003D => 1, # =               0x003D => 1, # =
2195                 0x003C => 1, # <
2196              }->{$self->{nc}}) {              }->{$self->{nc}}) {
2197                        
2198            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 2142  sub _get_next_token ($) { Line 2202  sub _get_next_token ($) {
2202          }          }
2203          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
2204          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
2205                                q["'=& >],                                qq["'=& \x09\x0C>],
2206                                length $self->{ca}->{value});                                length $self->{ca}->{value});
2207    
2208          ## Stay in the state          ## Stay in the state
# Line 2884  sub _get_next_token ($) { Line 2944  sub _get_next_token ($) {
2944        
2945          redo A;          redo A;
2946        }        }
2947      } elsif ($self->{state} == COMMENT_END_STATE) {      } elsif ($self->{state} == COMMENT_END_STATE or
2948                 $self->{state} == COMMENT_END_BANG_STATE) {
2949        ## XML5: "Comment end state" and "DOCTYPE comment end state".        ## XML5: "Comment end state" and "DOCTYPE comment end state".
2950          ## (No comment end bang state.)
2951    
2952        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
2953          if ($self->{in_subset}) {          if ($self->{in_subset}) {
# Line 2912  sub _get_next_token ($) { Line 2974  sub _get_next_token ($) {
2974    
2975          redo A;          redo A;
2976        } elsif ($self->{nc} == 0x002D) { # -        } elsif ($self->{nc} == 0x002D) { # -
2977            if ($self->{state} == COMMENT_END_BANG_STATE) {
2978              
2979              $self->{ct}->{data} .= '--!'; # comment
2980              $self->{state} = COMMENT_END_DASH_STATE;
2981            } else {
2982              
2983              ## XML5: Not a parse error.
2984              $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',
2985                              line => $self->{line_prev},
2986                              column => $self->{column_prev});
2987              $self->{ct}->{data} .= '-'; # comment
2988              ## Stay in the state
2989            }
2990                    
2991          ## XML5: Not a parse error.      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
2992          $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',        $self->{line_prev} = $self->{line};
2993                          line => $self->{line_prev},        $self->{column_prev} = $self->{column};
2994                          column => $self->{column_prev});        $self->{column}++;
2995          $self->{ct}->{data} .= '-'; # comment        $self->{nc}
2996          ## Stay in the state            = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
2997        } else {
2998          $self->{set_nc}->($self);
2999        }
3000      
3001            redo A;
3002          } elsif ($self->{state} != COMMENT_END_BANG_STATE and
3003                   $is_space->{$self->{nc}}) {
3004            
3005            $self->{parse_error}->(level => $self->{level}->{must}, type => 'comment end space'); # XXX error type
3006            $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
3007            $self->{state} = COMMENT_END_SPACE_STATE;
3008            
3009        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3010          $self->{line_prev} = $self->{line};
3011          $self->{column_prev} = $self->{column};
3012          $self->{column}++;
3013          $self->{nc}
3014              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3015        } else {
3016          $self->{set_nc}->($self);
3017        }
3018      
3019            redo A;
3020          } elsif ($self->{state} != COMMENT_END_BANG_STATE and
3021                   $self->{nc} == 0x0021) { # !
3022            
3023            $self->{parse_error}->(level => $self->{level}->{must}, type => 'comment end bang'); # XXX error type
3024            $self->{state} = COMMENT_END_BANG_STATE;
3025                    
3026      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3027        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 2941  sub _get_next_token ($) { Line 3044  sub _get_next_token ($) {
3044            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
3045            $self->{s_kwd} = '';            $self->{s_kwd} = '';
3046          }          }
3047          ## reconsume          ## Reconsume.
3048    
3049          return  ($self->{ct}); # comment          return  ($self->{ct}); # comment
3050    
3051          redo A;          redo A;
3052        } else {        } else {
3053                    
3054          ## XML5: Not a parse error.          if ($self->{state} == COMMENT_END_BANG_STATE) {
3055          $self->{parse_error}->(level => $self->{level}->{must}, type => 'dash in comment',            $self->{ct}->{data} .= '--!' . chr ($self->{nc}); # comment
3056                          line => $self->{line_prev},          } else {
3057                          column => $self->{column_prev});            $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
3058          $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment          }
3059          $self->{state} = COMMENT_STATE;          $self->{state} = COMMENT_STATE;
3060                    
3061      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 2967  sub _get_next_token ($) { Line 3070  sub _get_next_token ($) {
3070        
3071          redo A;          redo A;
3072        }        }
3073        } elsif ($self->{state} == COMMENT_END_SPACE_STATE) {
3074          ## XML5: Not exist.
3075    
3076          if ($self->{nc} == 0x003E) { # >
3077            if ($self->{in_subset}) {
3078              
3079              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3080            } else {
3081              
3082              $self->{state} = DATA_STATE;
3083              $self->{s_kwd} = '';
3084            }
3085            
3086        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3087          $self->{line_prev} = $self->{line};
3088          $self->{column_prev} = $self->{column};
3089          $self->{column}++;
3090          $self->{nc}
3091              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3092        } else {
3093          $self->{set_nc}->($self);
3094        }
3095      
3096    
3097            return  ($self->{ct}); # comment
3098    
3099            redo A;
3100          } elsif ($is_space->{$self->{nc}}) {
3101            
3102            $self->{ct}->{data} .= chr ($self->{nc}); # comment
3103            ## Stay in the state.
3104            
3105        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3106          $self->{line_prev} = $self->{line};
3107          $self->{column_prev} = $self->{column};
3108          $self->{column}++;
3109          $self->{nc}
3110              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3111        } else {
3112          $self->{set_nc}->($self);
3113        }
3114      
3115            redo A;
3116          } elsif ($self->{nc} == -1) {
3117            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed comment');
3118            if ($self->{in_subset}) {
3119              
3120              $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
3121            } else {
3122              
3123              $self->{state} = DATA_STATE;
3124              $self->{s_kwd} = '';
3125            }
3126            ## Reconsume.
3127    
3128            return  ($self->{ct}); # comment
3129    
3130            redo A;
3131          } else {
3132            
3133            $self->{ct}->{data} .= chr ($self->{nc}); # comment
3134            $self->{state} = COMMENT_STATE;
3135            
3136        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3137          $self->{line_prev} = $self->{line};
3138          $self->{column_prev} = $self->{column};
3139          $self->{column}++;
3140          $self->{nc}
3141              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3142        } else {
3143          $self->{set_nc}->($self);
3144        }
3145      
3146            redo A;
3147          }
3148      } elsif ($self->{state} == DOCTYPE_STATE) {      } elsif ($self->{state} == DOCTYPE_STATE) {
3149        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
3150                    
# Line 2983  sub _get_next_token ($) { Line 3161  sub _get_next_token ($) {
3161      }      }
3162        
3163          redo A;          redo A;
3164          } elsif ($self->{nc} == -1) {
3165            
3166            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed DOCTYPE');
3167            $self->{ct}->{quirks} = 1;
3168    
3169            $self->{state} = DATA_STATE;
3170            ## Reconsume.
3171            return  ($self->{ct}); # DOCTYPE (quirks)
3172    
3173            redo A;
3174        } else {        } else {
3175                    
3176          ## XML5: Unless EOF, swith to the bogus comment state.          ## XML5: Swith to the bogus comment state.
3177          $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');
3178          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
3179          ## reconsume          ## reconsume
# Line 3030  sub _get_next_token ($) { Line 3218  sub _get_next_token ($) {
3218          return  ($self->{ct}); # DOCTYPE (quirks)          return  ($self->{ct}); # DOCTYPE (quirks)
3219    
3220          redo A;          redo A;
3221          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
3222            
3223            $self->{ct}->{name} # DOCTYPE
3224                = chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
3225            delete $self->{ct}->{quirks};
3226            $self->{state} = DOCTYPE_NAME_STATE;
3227            
3228        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3229          $self->{line_prev} = $self->{line};
3230          $self->{column_prev} = $self->{column};
3231          $self->{column}++;
3232          $self->{nc}
3233              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3234        } else {
3235          $self->{set_nc}->($self);
3236        }
3237      
3238            redo A;
3239        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3240                    
3241          $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 3322  sub _get_next_token ($) {
3322          return  ($self->{ct}); # DOCTYPE          return  ($self->{ct}); # DOCTYPE
3323    
3324          redo A;          redo A;
3325          } elsif (0x0041 <= $self->{nc} and $self->{nc} <= 0x005A) { # A..Z
3326            
3327            $self->{ct}->{name} # DOCTYPE
3328                .= chr ($self->{nc} + ($self->{is_xml} ? 0 : 0x0020));
3329            delete $self->{ct}->{quirks};
3330            ## Stay in the state.
3331            
3332        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3333          $self->{line_prev} = $self->{line};
3334          $self->{column_prev} = $self->{column};
3335          $self->{column}++;
3336          $self->{nc}
3337              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3338        } else {
3339          $self->{set_nc}->($self);
3340        }
3341      
3342            redo A;
3343        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3344                    
3345          $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 3371  sub _get_next_token ($) {
3371          redo A;          redo A;
3372        } else {        } else {
3373                    
3374          $self->{ct}->{name}          $self->{ct}->{name} .= chr ($self->{nc}); # DOCTYPE
3375            .= chr ($self->{nc}); # DOCTYPE          ## Stay in the state.
         ## Stay in the state  
3376                    
3377      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3378        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 3256  sub _get_next_token ($) { Line 3479  sub _get_next_token ($) {
3479      }      }
3480        
3481          redo A;          redo A;
3482  ## TODO: " and ' for ENTITY        } elsif ($self->{nc} == 0x0022 and # "
3483                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3484                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3485            
3486            $self->{state} = DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE;
3487            $self->{ct}->{value} = ''; # ENTITY
3488            
3489        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3490          $self->{line_prev} = $self->{line};
3491          $self->{column_prev} = $self->{column};
3492          $self->{column}++;
3493          $self->{nc}
3494              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3495        } else {
3496          $self->{set_nc}->($self);
3497        }
3498      
3499            redo A;
3500          } elsif ($self->{nc} == 0x0027 and # '
3501                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
3502                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
3503            
3504            $self->{state} = DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE;
3505            $self->{ct}->{value} = ''; # ENTITY
3506            
3507        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
3508          $self->{line_prev} = $self->{line};
3509          $self->{column_prev} = $self->{column};
3510          $self->{column}++;
3511          $self->{nc}
3512              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
3513        } else {
3514          $self->{set_nc}->($self);
3515        }
3516      
3517            redo A;
3518        } elsif ($self->{is_xml} and        } elsif ($self->{is_xml} and
3519                 $self->{ct}->{type} == DOCTYPE_TOKEN and                 $self->{ct}->{type} == DOCTYPE_TOKEN and
3520                 $self->{nc} == 0x005B) { # [                 $self->{nc} == 0x005B) { # [
# Line 4172  sub _get_next_token ($) { Line 4430  sub _get_next_token ($) {
4430        }        }
4431      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
4432        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
4433                    if ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN) {
4434          ## Stay in the state            
4435              $self->{state} = BEFORE_NDATA_STATE;
4436            } else {
4437              
4438              ## Stay in the state
4439            }
4440                    
4441      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4442        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 4209  sub _get_next_token ($) { Line 4472  sub _get_next_token ($) {
4472        
4473          return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION          return  ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
4474          redo A;          redo A;
4475  ## TODO: "NDATA"        } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
4476                   ($self->{nc} == 0x004E or # N
4477                    $self->{nc} == 0x006E)) { # n
4478            
4479            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no space before NDATA'); ## TODO: type
4480            $self->{state} = NDATA_STATE;
4481            $self->{kwd} = chr $self->{nc};
4482            
4483        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4484          $self->{line_prev} = $self->{line};
4485          $self->{column_prev} = $self->{column};
4486          $self->{column}++;
4487          $self->{nc}
4488              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4489        } else {
4490          $self->{set_nc}->($self);
4491        }
4492      
4493            redo A;
4494        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
4495          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
4496                        
# Line 4271  sub _get_next_token ($) { Line 4552  sub _get_next_token ($) {
4552        
4553          redo A;          redo A;
4554        }        }
4555        } elsif ($self->{state} == BEFORE_NDATA_STATE) {
4556          if ($is_space->{$self->{nc}}) {
4557            
4558            ## Stay in the state.
4559            
4560        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4561          $self->{line_prev} = $self->{line};
4562          $self->{column_prev} = $self->{column};
4563          $self->{column}++;
4564          $self->{nc}
4565              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4566        } else {
4567          $self->{set_nc}->($self);
4568        }
4569      
4570            redo A;
4571          } elsif ($self->{nc} == 0x003E) { # >
4572            
4573            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4574            
4575        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4576          $self->{line_prev} = $self->{line};
4577          $self->{column_prev} = $self->{column};
4578          $self->{column}++;
4579          $self->{nc}
4580              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4581        } else {
4582          $self->{set_nc}->($self);
4583        }
4584      
4585            return  ($self->{ct}); # ENTITY
4586            redo A;
4587          } elsif ($self->{nc} == 0x004E or # N
4588                   $self->{nc} == 0x006E) { # n
4589            
4590            $self->{state} = NDATA_STATE;
4591            $self->{kwd} = chr $self->{nc};
4592            
4593        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4594          $self->{line_prev} = $self->{line};
4595          $self->{column_prev} = $self->{column};
4596          $self->{column}++;
4597          $self->{nc}
4598              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4599        } else {
4600          $self->{set_nc}->($self);
4601        }
4602      
4603            redo A;
4604          } elsif ($self->{nc} == -1) {
4605            
4606            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
4607            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4608            ## reconsume
4609            return  ($self->{ct}); # ENTITY
4610            redo A;
4611          } else {
4612            
4613            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after SYSTEM literal');
4614            $self->{state} = BOGUS_MD_STATE;
4615            
4616        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4617          $self->{line_prev} = $self->{line};
4618          $self->{column_prev} = $self->{column};
4619          $self->{column}++;
4620          $self->{nc}
4621              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4622        } else {
4623          $self->{set_nc}->($self);
4624        }
4625      
4626            redo A;
4627          }
4628      } elsif ($self->{state} == BOGUS_DOCTYPE_STATE) {      } elsif ($self->{state} == BOGUS_DOCTYPE_STATE) {
4629        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
4630                    
# Line 4481  sub _get_next_token ($) { Line 4835  sub _get_next_token ($) {
4835              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
4836              $self->{entity_add} => 1,              $self->{entity_add} => 1,
4837            }->{$self->{nc}}) {            }->{$self->{nc}}) {
4838                    if ($self->{is_xml}) {
4839              
4840              $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
4841                              line => $self->{line_prev},
4842                              column => $self->{column_prev}
4843                                  + ($self->{nc} == -1 ? 1 : 0));
4844            } else {
4845              
4846              ## No error
4847            }
4848          ## Don't consume          ## Don't consume
         ## No error  
4849          ## Return nothing.          ## Return nothing.
4850          #          #
4851        } elsif ($self->{nc} == 0x0023) { # #        } elsif ($self->{nc} == 0x0023) { # #
# Line 4502  sub _get_next_token ($) { Line 4864  sub _get_next_token ($) {
4864      }      }
4865        
4866          redo A;          redo A;
4867        } elsif ((0x0041 <= $self->{nc} and        } elsif ($self->{is_xml} or
4868                   (0x0041 <= $self->{nc} and
4869                  $self->{nc} <= 0x005A) or # A..Z                  $self->{nc} <= 0x005A) or # A..Z
4870                 (0x0061 <= $self->{nc} and                 (0x0061 <= $self->{nc} and
4871                  $self->{nc} <= 0x007A)) { # a..z                  $self->{nc} <= 0x007A)) { # a..z
# Line 4556  sub _get_next_token ($) { Line 4919  sub _get_next_token ($) {
4919          redo A;          redo A;
4920        }        }
4921      } elsif ($self->{state} == ENTITY_HASH_STATE) {      } elsif ($self->{state} == ENTITY_HASH_STATE) {
4922        if ($self->{nc} == 0x0078 or # x        if ($self->{nc} == 0x0078) { # x
           $self->{nc} == 0x0058) { # X  
4923                    
4924          $self->{state} = HEXREF_X_STATE;          $self->{state} = HEXREF_X_STATE;
4925          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
# Line 4573  sub _get_next_token ($) { Line 4935  sub _get_next_token ($) {
4935      }      }
4936        
4937          redo A;          redo A;
4938          } elsif ($self->{nc} == 0x0058) { # X
4939            
4940            if ($self->{is_xml}) {
4941              $self->{parse_error}->(level => $self->{level}->{must}, type => 'uppercase hcro'); ## TODO: type
4942            }
4943            $self->{state} = HEXREF_X_STATE;
4944            $self->{kwd} .= chr $self->{nc};
4945            
4946        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
4947          $self->{line_prev} = $self->{line};
4948          $self->{column_prev} = $self->{column};
4949          $self->{column}++;
4950          $self->{nc}
4951              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
4952        } else {
4953          $self->{set_nc}->($self);
4954        }
4955      
4956            redo A;
4957        } elsif (0x0030 <= $self->{nc} and        } elsif (0x0030 <= $self->{nc} and
4958                 $self->{nc} <= 0x0039) { # 0..9                 $self->{nc} <= 0x0039) { # 0..9
4959                    
# Line 4663  sub _get_next_token ($) { Line 5044  sub _get_next_token ($) {
5044        my $code = $self->{kwd};        my $code = $self->{kwd};
5045        my $l = $self->{line_prev};        my $l = $self->{line_prev};
5046        my $c = $self->{column_prev};        my $c = $self->{column_prev};
5047        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
5048              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
5049              ($self->{is_xml} and $code == 0x0000)) {
5050                    
5051          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
5052                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4816  sub _get_next_token ($) { Line 5199  sub _get_next_token ($) {
5199        my $code = $self->{kwd};        my $code = $self->{kwd};
5200        my $l = $self->{line_prev};        my $l = $self->{line_prev};
5201        my $c = $self->{column_prev};        my $c = $self->{column_prev};
5202        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
5203              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
5204              ($self->{is_xml} and $code == 0x0000)) {
5205                    
5206          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',          $self->{parse_error}->(level => $self->{level}->{must}, type => 'invalid character reference',
5207                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 4850  sub _get_next_token ($) { Line 5235  sub _get_next_token ($) {
5235          redo A;          redo A;
5236        }        }
5237      } elsif ($self->{state} == ENTITY_NAME_STATE) {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
5238        if (length $self->{kwd} < 30 and        if ((0x0041 <= $self->{nc} and # a
5239            ## NOTE: Some number greater than the maximum length of entity name             $self->{nc} <= 0x005A) or # x
5240            ((0x0041 <= $self->{nc} and # a            (0x0061 <= $self->{nc} and # a
5241              $self->{nc} <= 0x005A) or # x             $self->{nc} <= 0x007A) or # z
5242             (0x0061 <= $self->{nc} and # a            (0x0030 <= $self->{nc} and # 0
5243              $self->{nc} <= 0x007A) or # z             $self->{nc} <= 0x0039) or # 9
5244             (0x0030 <= $self->{nc} and # 0            $self->{nc} == 0x003B or # ;
5245              $self->{nc} <= 0x0039) or # 9            ($self->{is_xml} and
5246             $self->{nc} == 0x003B)) { # ;             not ($is_space->{$self->{nc}} or
5247                    {
5248                      0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
5249                      $self->{entity_add} => 1,
5250                    }->{$self->{nc}}))) {
5251          our $EntityChar;          our $EntityChar;
5252          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
5253          if (defined $EntityChar->{$self->{kwd}}) {          if (defined $EntityChar->{$self->{kwd}} or
5254                $self->{ge}->{$self->{kwd}}) {
5255            if ($self->{nc} == 0x003B) { # ;            if ($self->{nc} == 0x003B) { # ;
5256                            if (defined $self->{ge}->{$self->{kwd}}) {
5257              $self->{entity__value} = $EntityChar->{$self->{kwd}};                if ($self->{ge}->{$self->{kwd}}->{only_text}) {
5258                    
5259                    $self->{entity__value} = $self->{ge}->{$self->{kwd}}->{value};
5260                  } else {
5261                    if (defined $self->{ge}->{$self->{kwd}}->{notation}) {
5262                      
5263                      $self->{parse_error}->(level => $self->{level}->{must}, type => 'unparsed entity', ## TODO: type
5264                                      value => $self->{kwd});
5265                    } else {
5266                      
5267                    }
5268                    $self->{entity__value} = '&' . $self->{kwd}; ## TODO: expand
5269                  }
5270                } else {
5271                  if ($self->{is_xml}) {
5272                    
5273                    $self->{parse_error}->(level => $self->{level}->{must}, type => 'entity not declared', ## TODO: type
5274                                    value => $self->{kwd},
5275                                    level => {
5276                                              'amp;' => $self->{level}->{warn},
5277                                              'quot;' => $self->{level}->{warn},
5278                                              'lt;' => $self->{level}->{warn},
5279                                              'gt;' => $self->{level}->{warn},
5280                                              'apos;' => $self->{level}->{warn},
5281                                             }->{$self->{kwd}} ||
5282                                             $self->{level}->{must});
5283                  } else {
5284                    
5285                  }
5286                  $self->{entity__value} = $EntityChar->{$self->{kwd}};
5287                }
5288              $self->{entity__match} = 1;              $self->{entity__match} = 1;
5289                            
5290      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 5680  sub _get_next_token ($) {
5680          ## XML5: Not defined yet.          ## XML5: Not defined yet.
5681    
5682          ## TODO:          ## TODO:
5683    
5684            if (not $self->{stop_processing} and
5685                not $self->{document}->xml_standalone) {
5686              $self->{parse_error}->(level => $self->{level}->{must}, type => 'stop processing', ## TODO: type
5687                              level => $self->{level}->{info});
5688              $self->{stop_processing} = 1;
5689            }
5690    
5691                    
5692      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
5693        $self->{line_prev} = $self->{line};        $self->{line_prev} = $self->{line};
# Line 5694  sub _get_next_token ($) { Line 6122  sub _get_next_token ($) {
6122          }          }
6123          $self->{ct} = {type => ELEMENT_TOKEN, name => '',          $self->{ct} = {type => ELEMENT_TOKEN, name => '',
6124                         line => $self->{line_prev},                         line => $self->{line_prev},
6125                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
6126          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6127                    
6128      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5762  sub _get_next_token ($) { Line 6190  sub _get_next_token ($) {
6190          $self->{ct} = {type => ATTLIST_TOKEN, name => '',          $self->{ct} = {type => ATTLIST_TOKEN, name => '',
6191                         attrdefs => [],                         attrdefs => [],
6192                         line => $self->{line_prev},                         line => $self->{line_prev},
6193                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
6194          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6195                    
6196      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 5831  sub _get_next_token ($) { Line 6259  sub _get_next_token ($) {
6259          }          }
6260          $self->{ct} = {type => NOTATION_TOKEN, name => '',          $self->{ct} = {type => NOTATION_TOKEN, name => '',
6261                         line => $self->{line_prev},                         line => $self->{line_prev},
6262                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 8};
6263          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
6264                    
6265      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {      if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
# Line 6043  sub _get_next_token ($) { Line 6471  sub _get_next_token ($) {
6471          if ($self->{ct}->{type} == ATTLIST_TOKEN) {          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
6472            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
6473          } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {          } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
6474            ## TODO: ...            $self->{state} = AFTER_ELEMENT_NAME_STATE;
           $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;  
6475          } else { # ENTITY/NOTATION          } else { # ENTITY/NOTATION
6476            $self->{state} = AFTER_DOCTYPE_NAME_STATE;            $self->{state} = AFTER_DOCTYPE_NAME_STATE;
6477          }          }
# Line 7342  sub _get_next_token ($) { Line 7769  sub _get_next_token ($) {
7769          ## Reconsume.          ## Reconsume.
7770          redo A;          redo A;
7771        }        }
7772        } elsif ($self->{state} == NDATA_STATE) {
7773          ## ASCII case-insensitive
7774          if ($self->{nc} == [
7775                undef,
7776                0x0044, # D
7777                0x0041, # A
7778                0x0054, # T
7779              ]->[length $self->{kwd}] or
7780              $self->{nc} == [
7781                undef,
7782                0x0064, # d
7783                0x0061, # a
7784                0x0074, # t
7785              ]->[length $self->{kwd}]) {
7786            
7787            ## Stay in the state.
7788            $self->{kwd} .= chr $self->{nc};
7789            
7790        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7791          $self->{line_prev} = $self->{line};
7792          $self->{column_prev} = $self->{column};
7793          $self->{column}++;
7794          $self->{nc}
7795              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7796        } else {
7797          $self->{set_nc}->($self);
7798        }
7799      
7800            redo A;
7801          } elsif ((length $self->{kwd}) == 4 and
7802                   ($self->{nc} == 0x0041 or # A
7803                    $self->{nc} == 0x0061)) { # a
7804            if ($self->{kwd} ne 'NDAT' or $self->{nc} == 0x0061) { # a
7805              
7806              $self->{parse_error}->(level => $self->{level}->{must}, type => 'lowercase keyword', ## TODO: type
7807                              text => 'NDATA',
7808                              line => $self->{line_prev},
7809                              column => $self->{column_prev} - 4);
7810            } else {
7811              
7812            }
7813            $self->{state} = AFTER_NDATA_STATE;
7814            
7815        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7816          $self->{line_prev} = $self->{line};
7817          $self->{column_prev} = $self->{column};
7818          $self->{column}++;
7819          $self->{nc}
7820              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7821        } else {
7822          $self->{set_nc}->($self);
7823        }
7824      
7825            redo A;
7826          } else {
7827            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7828                            line => $self->{line_prev},
7829                            column => $self->{column_prev} + 1
7830                                - length $self->{kwd});
7831            
7832            $self->{state} = BOGUS_MD_STATE;
7833            ## Reconsume.
7834            redo A;
7835          }
7836        } elsif ($self->{state} == AFTER_NDATA_STATE) {
7837          if ($is_space->{$self->{nc}}) {
7838            $self->{state} = BEFORE_NOTATION_NAME_STATE;
7839            
7840        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7841          $self->{line_prev} = $self->{line};
7842          $self->{column_prev} = $self->{column};
7843          $self->{column}++;
7844          $self->{nc}
7845              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7846        } else {
7847          $self->{set_nc}->($self);
7848        }
7849      
7850            redo A;
7851          } elsif ($self->{nc} == 0x003E) { # >
7852            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7853            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7854            
7855        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7856          $self->{line_prev} = $self->{line};
7857          $self->{column_prev} = $self->{column};
7858          $self->{column}++;
7859          $self->{nc}
7860              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7861        } else {
7862          $self->{set_nc}->($self);
7863        }
7864      
7865            return  ($self->{ct}); # ENTITY
7866            redo A;
7867          } elsif ($self->{nc} == -1) {
7868            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7869            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7870            
7871        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7872          $self->{line_prev} = $self->{line};
7873          $self->{column_prev} = $self->{column};
7874          $self->{column}++;
7875          $self->{nc}
7876              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7877        } else {
7878          $self->{set_nc}->($self);
7879        }
7880      
7881            return  ($self->{ct}); # ENTITY
7882            redo A;
7883          } else {
7884            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after literal', ## TODO: type
7885                            line => $self->{line_prev},
7886                            column => $self->{column_prev} + 1
7887                                - length $self->{kwd});
7888            $self->{state} = BOGUS_MD_STATE;
7889            ## Reconsume.
7890            redo A;
7891          }
7892        } elsif ($self->{state} == BEFORE_NOTATION_NAME_STATE) {
7893          if ($is_space->{$self->{nc}}) {
7894            ## Stay in the state.
7895            
7896        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7897          $self->{line_prev} = $self->{line};
7898          $self->{column_prev} = $self->{column};
7899          $self->{column}++;
7900          $self->{nc}
7901              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7902        } else {
7903          $self->{set_nc}->($self);
7904        }
7905      
7906            redo A;
7907          } elsif ($self->{nc} == 0x003E) { # >
7908            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no notation name'); ## TODO: type
7909            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7910            
7911        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7912          $self->{line_prev} = $self->{line};
7913          $self->{column_prev} = $self->{column};
7914          $self->{column}++;
7915          $self->{nc}
7916              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7917        } else {
7918          $self->{set_nc}->($self);
7919        }
7920      
7921            return  ($self->{ct}); # ENTITY
7922            redo A;
7923          } elsif ($self->{nc} == -1) {
7924            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7925            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
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            return  ($self->{ct}); # ENTITY
7938            redo A;
7939          } else {
7940            $self->{ct}->{notation} = chr $self->{nc}; # ENTITY
7941            $self->{state} = NOTATION_NAME_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          }
7955        } elsif ($self->{state} == NOTATION_NAME_STATE) {
7956          if ($is_space->{$self->{nc}}) {
7957            $self->{state} = AFTER_MD_DEF_STATE;
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          } elsif ($self->{nc} == 0x003E) { # >
7971            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7972            
7973        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7974          $self->{line_prev} = $self->{line};
7975          $self->{column_prev} = $self->{column};
7976          $self->{column}++;
7977          $self->{nc}
7978              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7979        } else {
7980          $self->{set_nc}->($self);
7981        }
7982      
7983            return  ($self->{ct}); # ENTITY
7984            redo A;
7985          } elsif ($self->{nc} == -1) {
7986            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
7987            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
7988            
7989        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
7990          $self->{line_prev} = $self->{line};
7991          $self->{column_prev} = $self->{column};
7992          $self->{column}++;
7993          $self->{nc}
7994              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
7995        } else {
7996          $self->{set_nc}->($self);
7997        }
7998      
7999            return  ($self->{ct}); # ENTITY
8000            redo A;
8001          } else {
8002            $self->{ct}->{notation} .= chr $self->{nc}; # ENTITY
8003            ## Stay in the state.
8004            
8005        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8006          $self->{line_prev} = $self->{line};
8007          $self->{column_prev} = $self->{column};
8008          $self->{column}++;
8009          $self->{nc}
8010              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8011        } else {
8012          $self->{set_nc}->($self);
8013        }
8014      
8015            redo A;
8016          }
8017        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE) {
8018          if ($self->{nc} == 0x0022) { # "
8019            $self->{state} = AFTER_MD_DEF_STATE;
8020            
8021        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8022          $self->{line_prev} = $self->{line};
8023          $self->{column_prev} = $self->{column};
8024          $self->{column}++;
8025          $self->{nc}
8026              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8027        } else {
8028          $self->{set_nc}->($self);
8029        }
8030      
8031            redo A;
8032          } elsif ($self->{nc} == 0x0026) { # &
8033            $self->{prev_state} = $self->{state};
8034            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
8035            $self->{entity_add} = 0x0022; # "
8036            
8037        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8038          $self->{line_prev} = $self->{line};
8039          $self->{column_prev} = $self->{column};
8040          $self->{column}++;
8041          $self->{nc}
8042              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8043        } else {
8044          $self->{set_nc}->($self);
8045        }
8046      
8047            redo A;
8048    ## TODO: %
8049          } elsif ($self->{nc} == -1) {
8050            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
8051            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8052            ## Reconsume.
8053            return  ($self->{ct}); # ENTITY
8054            redo A;
8055          } else {
8056            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
8057            
8058        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8059          $self->{line_prev} = $self->{line};
8060          $self->{column_prev} = $self->{column};
8061          $self->{column}++;
8062          $self->{nc}
8063              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8064        } else {
8065          $self->{set_nc}->($self);
8066        }
8067      
8068            redo A;
8069          }
8070        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE) {
8071          if ($self->{nc} == 0x0027) { # '
8072            $self->{state} = AFTER_MD_DEF_STATE;
8073            
8074        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8075          $self->{line_prev} = $self->{line};
8076          $self->{column_prev} = $self->{column};
8077          $self->{column}++;
8078          $self->{nc}
8079              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8080        } else {
8081          $self->{set_nc}->($self);
8082        }
8083      
8084            redo A;
8085          } elsif ($self->{nc} == 0x0026) { # &
8086            $self->{prev_state} = $self->{state};
8087            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
8088            $self->{entity_add} = 0x0027; # '
8089            
8090        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8091          $self->{line_prev} = $self->{line};
8092          $self->{column_prev} = $self->{column};
8093          $self->{column}++;
8094          $self->{nc}
8095              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8096        } else {
8097          $self->{set_nc}->($self);
8098        }
8099      
8100            redo A;
8101    ## TODO: %
8102          } elsif ($self->{nc} == -1) {
8103            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed entity value'); ## TODO: type
8104            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8105            ## Reconsume.
8106            return  ($self->{ct}); # ENTITY
8107            redo A;
8108          } else {
8109            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
8110            
8111        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8112          $self->{line_prev} = $self->{line};
8113          $self->{column_prev} = $self->{column};
8114          $self->{column}++;
8115          $self->{nc}
8116              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8117        } else {
8118          $self->{set_nc}->($self);
8119        }
8120      
8121            redo A;
8122          }
8123        } elsif ($self->{state} == ENTITY_VALUE_ENTITY_STATE) {
8124          if ($is_space->{$self->{nc}} or
8125              {
8126                0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
8127                $self->{entity_add} => 1,
8128              }->{$self->{nc}}) {
8129            $self->{parse_error}->(level => $self->{level}->{must}, type => 'bare ero',
8130                            line => $self->{line_prev},
8131                            column => $self->{column_prev}
8132                                + ($self->{nc} == -1 ? 1 : 0));
8133            ## Don't consume
8134            ## Return nothing.
8135            #
8136          } elsif ($self->{nc} == 0x0023) { # #
8137            $self->{ca} = $self->{ct};
8138            $self->{state} = ENTITY_HASH_STATE;
8139            $self->{kwd} = '#';
8140            
8141        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8142          $self->{line_prev} = $self->{line};
8143          $self->{column_prev} = $self->{column};
8144          $self->{column}++;
8145          $self->{nc}
8146              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8147        } else {
8148          $self->{set_nc}->($self);
8149        }
8150      
8151            redo A;
8152          } else {
8153            #
8154          }
8155    
8156          $self->{ct}->{value} .= '&';
8157          $self->{state} = $self->{prev_state};
8158          ## Reconsume.
8159          redo A;
8160        } elsif ($self->{state} == AFTER_ELEMENT_NAME_STATE) {
8161          if ($is_space->{$self->{nc}}) {
8162            $self->{state} = BEFORE_ELEMENT_CONTENT_STATE;
8163            
8164        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8165          $self->{line_prev} = $self->{line};
8166          $self->{column_prev} = $self->{column};
8167          $self->{column}++;
8168          $self->{nc}
8169              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8170        } else {
8171          $self->{set_nc}->($self);
8172        }
8173      
8174            redo A;
8175          } elsif ($self->{nc} == 0x0028) { # (
8176            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8177            $self->{ct}->{content} = ['('];
8178            $self->{group_depth} = 1;
8179            
8180        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8181          $self->{line_prev} = $self->{line};
8182          $self->{column_prev} = $self->{column};
8183          $self->{column}++;
8184          $self->{nc}
8185              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8186        } else {
8187          $self->{set_nc}->($self);
8188        }
8189      
8190            redo A;
8191          } elsif ($self->{nc} == 0x003E) { # >
8192            $self->{parse_error}->(level => $self->{level}->{must}, type => 'no md def'); ## TODO: type
8193            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8194            
8195        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8196          $self->{line_prev} = $self->{line};
8197          $self->{column_prev} = $self->{column};
8198          $self->{column}++;
8199          $self->{nc}
8200              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8201        } else {
8202          $self->{set_nc}->($self);
8203        }
8204      
8205            return  ($self->{ct}); # ELEMENT
8206            redo A;
8207          } elsif ($self->{nc} == -1) {
8208            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
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            $self->{ct}->{content} = [chr $self->{nc}];
8225            $self->{state} = CONTENT_KEYWORD_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} == CONTENT_KEYWORD_STATE) {
8240          if ($is_space->{$self->{nc}}) {
8241            $self->{state} = AFTER_MD_DEF_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} == 0x003E) { # >
8255            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8256            
8257        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8258          $self->{line_prev} = $self->{line};
8259          $self->{column_prev} = $self->{column};
8260          $self->{column}++;
8261          $self->{nc}
8262              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8263        } else {
8264          $self->{set_nc}->($self);
8265        }
8266      
8267            return  ($self->{ct}); # ELEMENT
8268            redo A;
8269          } elsif ($self->{nc} == -1) {
8270            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8271            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8272            
8273        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8274          $self->{line_prev} = $self->{line};
8275          $self->{column_prev} = $self->{column};
8276          $self->{column}++;
8277          $self->{nc}
8278              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8279        } else {
8280          $self->{set_nc}->($self);
8281        }
8282      
8283            return  ($self->{ct}); # ELEMENT
8284            redo A;
8285          } else {
8286            $self->{ct}->{content}->[-1] .= chr $self->{nc}; # ELEMENT
8287            ## Stay in the state.
8288            
8289        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8290          $self->{line_prev} = $self->{line};
8291          $self->{column_prev} = $self->{column};
8292          $self->{column}++;
8293          $self->{nc}
8294              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8295        } else {
8296          $self->{set_nc}->($self);
8297        }
8298      
8299            redo A;
8300          }
8301        } elsif ($self->{state} == AFTER_CM_GROUP_OPEN_STATE) {
8302          if ($is_space->{$self->{nc}}) {
8303            ## Stay in the 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} == 0x0028) { # (
8317            $self->{group_depth}++;
8318            push @{$self->{ct}->{content}}, chr $self->{nc};
8319            ## Stay in the 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} == 0x007C or # |
8333                   $self->{nc} == 0x002C) { # ,
8334            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8335            ## Stay in the 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} == 0x0029) { # )
8349            $self->{parse_error}->(level => $self->{level}->{must}, type => 'empty element name'); ## TODO: type
8350            push @{$self->{ct}->{content}}, chr $self->{nc};
8351            $self->{group_depth}--;
8352            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8353            
8354        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8355          $self->{line_prev} = $self->{line};
8356          $self->{column_prev} = $self->{column};
8357          $self->{column}++;
8358          $self->{nc}
8359              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8360        } else {
8361          $self->{set_nc}->($self);
8362        }
8363      
8364            redo A;
8365          } elsif ($self->{nc} == 0x003E) { # >
8366            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## 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          } elsif ($self->{nc} == -1) {
8383            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8384            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8385            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8386            
8387        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8388          $self->{line_prev} = $self->{line};
8389          $self->{column_prev} = $self->{column};
8390          $self->{column}++;
8391          $self->{nc}
8392              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8393        } else {
8394          $self->{set_nc}->($self);
8395        }
8396      
8397            return  ($self->{ct}); # ELEMENT
8398            redo A;
8399          } else {
8400            push @{$self->{ct}->{content}}, chr $self->{nc};
8401            $self->{state} = CM_ELEMENT_NAME_STATE;
8402            
8403        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8404          $self->{line_prev} = $self->{line};
8405          $self->{column_prev} = $self->{column};
8406          $self->{column}++;
8407          $self->{nc}
8408              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8409        } else {
8410          $self->{set_nc}->($self);
8411        }
8412      
8413            redo A;
8414          }
8415        } elsif ($self->{state} == CM_ELEMENT_NAME_STATE) {
8416          if ($is_space->{$self->{nc}}) {
8417            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8418            
8419        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8420          $self->{line_prev} = $self->{line};
8421          $self->{column_prev} = $self->{column};
8422          $self->{column}++;
8423          $self->{nc}
8424              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8425        } else {
8426          $self->{set_nc}->($self);
8427        }
8428      
8429            redo A;
8430          } elsif ($self->{nc} == 0x002A or # *
8431                   $self->{nc} == 0x002B or # +
8432                   $self->{nc} == 0x003F) { # ?
8433            push @{$self->{ct}->{content}}, chr $self->{nc};
8434            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8435            
8436        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8437          $self->{line_prev} = $self->{line};
8438          $self->{column_prev} = $self->{column};
8439          $self->{column}++;
8440          $self->{nc}
8441              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8442        } else {
8443          $self->{set_nc}->($self);
8444        }
8445      
8446            redo A;
8447          } elsif ($self->{nc} == 0x007C or # |
8448                   $self->{nc} == 0x002C) { # ,
8449            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8450            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8451            
8452        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8453          $self->{line_prev} = $self->{line};
8454          $self->{column_prev} = $self->{column};
8455          $self->{column}++;
8456          $self->{nc}
8457              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8458        } else {
8459          $self->{set_nc}->($self);
8460        }
8461      
8462            redo A;
8463          } elsif ($self->{nc} == 0x0029) { # )
8464            $self->{group_depth}--;
8465            push @{$self->{ct}->{content}}, chr $self->{nc};
8466            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8467            
8468        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8469          $self->{line_prev} = $self->{line};
8470          $self->{column_prev} = $self->{column};
8471          $self->{column}++;
8472          $self->{nc}
8473              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8474        } else {
8475          $self->{set_nc}->($self);
8476        }
8477      
8478            redo A;
8479          } elsif ($self->{nc} == 0x003E) { # >
8480            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8481            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8482            $self->{state} = DOCTYPE_INTERNAL_SUBSET_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            return  ($self->{ct}); # ELEMENT
8495            redo A;
8496          } elsif ($self->{nc} == -1) {
8497            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8498            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8499            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8500            
8501        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8502          $self->{line_prev} = $self->{line};
8503          $self->{column_prev} = $self->{column};
8504          $self->{column}++;
8505          $self->{nc}
8506              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8507        } else {
8508          $self->{set_nc}->($self);
8509        }
8510      
8511            return  ($self->{ct}); # ELEMENT
8512            redo A;
8513          } else {
8514            $self->{ct}->{content}->[-1] .= chr $self->{nc};
8515            ## Stay in the state.
8516            
8517        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8518          $self->{line_prev} = $self->{line};
8519          $self->{column_prev} = $self->{column};
8520          $self->{column}++;
8521          $self->{nc}
8522              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8523        } else {
8524          $self->{set_nc}->($self);
8525        }
8526      
8527            redo A;
8528          }
8529        } elsif ($self->{state} == AFTER_CM_ELEMENT_NAME_STATE) {
8530          if ($is_space->{$self->{nc}}) {
8531            ## Stay in the state.
8532            
8533        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8534          $self->{line_prev} = $self->{line};
8535          $self->{column_prev} = $self->{column};
8536          $self->{column}++;
8537          $self->{nc}
8538              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8539        } else {
8540          $self->{set_nc}->($self);
8541        }
8542      
8543            redo A;
8544          } elsif ($self->{nc} == 0x007C or # |
8545                   $self->{nc} == 0x002C) { # ,
8546            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
8547            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
8548            
8549        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8550          $self->{line_prev} = $self->{line};
8551          $self->{column_prev} = $self->{column};
8552          $self->{column}++;
8553          $self->{nc}
8554              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8555        } else {
8556          $self->{set_nc}->($self);
8557        }
8558      
8559            redo A;
8560          } elsif ($self->{nc} == 0x0029) { # )
8561            $self->{group_depth}--;
8562            push @{$self->{ct}->{content}}, chr $self->{nc};
8563            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
8564            
8565        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8566          $self->{line_prev} = $self->{line};
8567          $self->{column_prev} = $self->{column};
8568          $self->{column}++;
8569          $self->{nc}
8570              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8571        } else {
8572          $self->{set_nc}->($self);
8573        }
8574      
8575            redo A;
8576          } elsif ($self->{nc} == 0x003E) { # >
8577            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8578            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8579            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8580            
8581        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8582          $self->{line_prev} = $self->{line};
8583          $self->{column_prev} = $self->{column};
8584          $self->{column}++;
8585          $self->{nc}
8586              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8587        } else {
8588          $self->{set_nc}->($self);
8589        }
8590      
8591            return  ($self->{ct}); # ELEMENT
8592            redo A;
8593          } elsif ($self->{nc} == -1) {
8594            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8595            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8596            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8597            
8598        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8599          $self->{line_prev} = $self->{line};
8600          $self->{column_prev} = $self->{column};
8601          $self->{column}++;
8602          $self->{nc}
8603              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8604        } else {
8605          $self->{set_nc}->($self);
8606        }
8607      
8608            return  ($self->{ct}); # ELEMENT
8609            redo A;
8610          } else {
8611            $self->{parse_error}->(level => $self->{level}->{must}, type => 'after element name'); ## TODO: type
8612            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8613            $self->{state} = BOGUS_MD_STATE;
8614            
8615        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8616          $self->{line_prev} = $self->{line};
8617          $self->{column_prev} = $self->{column};
8618          $self->{column}++;
8619          $self->{nc}
8620              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8621        } else {
8622          $self->{set_nc}->($self);
8623        }
8624      
8625            redo A;
8626          }
8627        } elsif ($self->{state} == AFTER_CM_GROUP_CLOSE_STATE) {
8628          if ($is_space->{$self->{nc}}) {
8629            if ($self->{group_depth}) {
8630              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8631            } else {
8632              $self->{state} = AFTER_MD_DEF_STATE;
8633            }
8634            
8635        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8636          $self->{line_prev} = $self->{line};
8637          $self->{column_prev} = $self->{column};
8638          $self->{column}++;
8639          $self->{nc}
8640              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8641        } else {
8642          $self->{set_nc}->($self);
8643        }
8644      
8645            redo A;
8646          } elsif ($self->{nc} == 0x002A or # *
8647                   $self->{nc} == 0x002B or # +
8648                   $self->{nc} == 0x003F) { # ?
8649            push @{$self->{ct}->{content}}, chr $self->{nc};
8650            if ($self->{group_depth}) {
8651              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8652            } else {
8653              $self->{state} = AFTER_MD_DEF_STATE;
8654            }
8655            
8656        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8657          $self->{line_prev} = $self->{line};
8658          $self->{column_prev} = $self->{column};
8659          $self->{column}++;
8660          $self->{nc}
8661              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8662        } else {
8663          $self->{set_nc}->($self);
8664        }
8665      
8666            redo A;
8667          } elsif ($self->{nc} == 0x0029) { # )
8668            if ($self->{group_depth}) {
8669              $self->{group_depth}--;
8670              push @{$self->{ct}->{content}}, chr $self->{nc};
8671              ## Stay in the state.
8672              
8673        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8674          $self->{line_prev} = $self->{line};
8675          $self->{column_prev} = $self->{column};
8676          $self->{column}++;
8677          $self->{nc}
8678              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8679        } else {
8680          $self->{set_nc}->($self);
8681        }
8682      
8683              redo A;
8684            } else {
8685              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8686              $self->{state} = BOGUS_MD_STATE;
8687              ## Reconsume.
8688              redo A;
8689            }
8690          } elsif ($self->{nc} == 0x003E) { # >
8691            if ($self->{group_depth}) {
8692              $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed cm group'); ## TODO: type
8693              push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8694            }
8695            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8696            
8697        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8698          $self->{line_prev} = $self->{line};
8699          $self->{column_prev} = $self->{column};
8700          $self->{column}++;
8701          $self->{nc}
8702              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8703        } else {
8704          $self->{set_nc}->($self);
8705        }
8706      
8707            return  ($self->{ct}); # ELEMENT
8708            redo A;
8709          } elsif ($self->{nc} == -1) {
8710            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8711            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
8712            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8713            
8714        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8715          $self->{line_prev} = $self->{line};
8716          $self->{column_prev} = $self->{column};
8717          $self->{column}++;
8718          $self->{nc}
8719              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8720        } else {
8721          $self->{set_nc}->($self);
8722        }
8723      
8724            return  ($self->{ct}); # ELEMENT
8725            redo A;
8726          } else {
8727            if ($self->{group_depth}) {
8728              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
8729            } else {
8730              $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8731              $self->{state} = BOGUS_MD_STATE;
8732            }
8733            ## Reconsume.
8734            redo A;
8735          }
8736        } elsif ($self->{state} == AFTER_MD_DEF_STATE) {
8737          if ($is_space->{$self->{nc}}) {
8738            ## Stay in the state.
8739            
8740        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8741          $self->{line_prev} = $self->{line};
8742          $self->{column_prev} = $self->{column};
8743          $self->{column}++;
8744          $self->{nc}
8745              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8746        } else {
8747          $self->{set_nc}->($self);
8748        }
8749      
8750            redo A;
8751          } elsif ($self->{nc} == 0x003E) { # >
8752            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8753            
8754        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8755          $self->{line_prev} = $self->{line};
8756          $self->{column_prev} = $self->{column};
8757          $self->{column}++;
8758          $self->{nc}
8759              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8760        } else {
8761          $self->{set_nc}->($self);
8762        }
8763      
8764            return  ($self->{ct}); # ENTITY/ELEMENT
8765            redo A;
8766          } elsif ($self->{nc} == -1) {
8767            $self->{parse_error}->(level => $self->{level}->{must}, type => 'unclosed md'); ## TODO: type
8768            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
8769            
8770        if ($self->{char_buffer_pos} < length $self->{char_buffer}) {
8771          $self->{line_prev} = $self->{line};
8772          $self->{column_prev} = $self->{column};
8773          $self->{column}++;
8774          $self->{nc}
8775              = ord substr ($self->{char_buffer}, $self->{char_buffer_pos}++, 1);
8776        } else {
8777          $self->{set_nc}->($self);
8778        }
8779      
8780            return  ($self->{ct}); # ENTITY/ELEMENT
8781            redo A;
8782          } else {
8783            $self->{parse_error}->(level => $self->{level}->{must}, type => 'string after md def'); ## TODO: type
8784            $self->{state} = BOGUS_MD_STATE;
8785            ## Reconsume.
8786            redo A;
8787          }
8788      } elsif ($self->{state} == BOGUS_MD_STATE) {      } elsif ($self->{state} == BOGUS_MD_STATE) {
8789        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
8790          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;

Legend:
Removed from v.1.17  
changed lines
  Added in v.1.32

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24