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

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

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.27 by wakaba, Thu Jul 2 22:24:28 2009 UTC
# Line 177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO Line 177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATIO
177  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_STATE () { 82 }
178  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }  sub DOCTYPE_ATTLIST_ATTRIBUTE_DECLARATION_AFTER_STATE () { 83 }
179  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }  sub AFTER_ATTLIST_ATTR_VALUE_QUOTED_STATE () { 84 }
180  sub 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 1254  sub _get_next_token ($) { Line 1270  sub _get_next_token ($) {
1270    
1271          redo A;          redo A;
1272        } else {        } else {
1273          if ($self->{nc} == 0x003D) { # =          if ($self->{nc} == 0x003D or $self->{nc} == 0x003C) { # =, <
1274            !!!cp (93);            !!!cp (93);
1275            ## XML5: Not a parse error.            ## XML5: Not a parse error.
1276            !!!parse-error (type => 'bad attribute value');            !!!parse-error (type => 'bad attribute value');
# Line 1300  sub _get_next_token ($) { Line 1316  sub _get_next_token ($) {
1316          $self->{state} = ENTITY_STATE;          $self->{state} = ENTITY_STATE;
1317          !!!next-input-character;          !!!next-input-character;
1318          redo A;          redo A;
1319          } elsif ($self->{is_xml} and
1320                   $is_space->{$self->{nc}}) {
1321            !!!cp (97.1);
1322            $self->{ca}->{value} .= ' ';
1323            ## Stay in the state.
1324            !!!next-input-character;
1325            redo A;
1326        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1327          !!!parse-error (type => 'unclosed attribute value');          !!!parse-error (type => 'unclosed attribute value');
1328          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1347  sub _get_next_token ($) { Line 1370  sub _get_next_token ($) {
1370          }          }
1371          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1372          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1373                                q["&<],                                qq["&<\x09\x0C\x20],
1374                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1375    
1376          ## Stay in the state          ## Stay in the state
# Line 1384  sub _get_next_token ($) { Line 1407  sub _get_next_token ($) {
1407          $self->{state} = ENTITY_STATE;          $self->{state} = ENTITY_STATE;
1408          !!!next-input-character;          !!!next-input-character;
1409          redo A;          redo A;
1410          } elsif ($self->{is_xml} and
1411                   $is_space->{$self->{nc}}) {
1412            !!!cp (103.1);
1413            $self->{ca}->{value} .= ' ';
1414            ## Stay in the state.
1415            !!!next-input-character;
1416            redo A;
1417        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1418          !!!parse-error (type => 'unclosed attribute value');          !!!parse-error (type => 'unclosed attribute value');
1419          if ($self->{ct}->{type} == START_TAG_TOKEN) {          if ($self->{ct}->{type} == START_TAG_TOKEN) {
# Line 1431  sub _get_next_token ($) { Line 1461  sub _get_next_token ($) {
1461          }          }
1462          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1463          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1464                                q['&<],                                qq['&<\x09\x0C\x20],
1465                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1466    
1467          ## Stay in the state          ## Stay in the state
# Line 1543  sub _get_next_token ($) { Line 1573  sub _get_next_token ($) {
1573               0x0022 => 1, # "               0x0022 => 1, # "
1574               0x0027 => 1, # '               0x0027 => 1, # '
1575               0x003D => 1, # =               0x003D => 1, # =
1576                 0x003C => 1, # <
1577              }->{$self->{nc}}) {              }->{$self->{nc}}) {
1578            !!!cp (115);            !!!cp (115);
1579            ## XML5: Not a parse error.            ## XML5: Not a parse error.
# Line 1552  sub _get_next_token ($) { Line 1583  sub _get_next_token ($) {
1583          }          }
1584          $self->{ca}->{value} .= chr ($self->{nc});          $self->{ca}->{value} .= chr ($self->{nc});
1585          $self->{read_until}->($self->{ca}->{value},          $self->{read_until}->($self->{ca}->{value},
1586                                q["'=& >],                                qq["'=& \x09\x0C>],
1587                                length $self->{ca}->{value});                                length $self->{ca}->{value});
1588    
1589          ## Stay in the state          ## Stay in the state
# Line 2088  sub _get_next_token ($) { Line 2119  sub _get_next_token ($) {
2119          redo A;          redo A;
2120        } else {        } else {
2121          !!!cp (154);          !!!cp (154);
         ## XML5: Not a parse error.  
         !!!parse-error (type => 'dash in comment',  
                         line => $self->{line_prev},  
                         column => $self->{column_prev});  
2122          $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment          $self->{ct}->{data} .= '--' . chr ($self->{nc}); # comment
2123          $self->{state} = COMMENT_STATE;          $self->{state} = COMMENT_STATE;
2124          !!!next-input-character;          !!!next-input-character;
# Line 2256  sub _get_next_token ($) { Line 2283  sub _get_next_token ($) {
2283          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
2284          !!!next-input-character;          !!!next-input-character;
2285          redo A;          redo A;
2286  ## TODO: " and ' for ENTITY        } elsif ($self->{nc} == 0x0022 and # "
2287                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
2288                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
2289            !!!cp (167.21);
2290            $self->{state} = DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE;
2291            $self->{ct}->{value} = ''; # ENTITY
2292            !!!next-input-character;
2293            redo A;
2294          } elsif ($self->{nc} == 0x0027 and # '
2295                   ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN or
2296                    $self->{ct}->{type} == PARAMETER_ENTITY_TOKEN)) {
2297            !!!cp (167.22);
2298            $self->{state} = DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE;
2299            $self->{ct}->{value} = ''; # ENTITY
2300            !!!next-input-character;
2301            redo A;
2302        } elsif ($self->{is_xml} and        } elsif ($self->{is_xml} and
2303                 $self->{ct}->{type} == DOCTYPE_TOKEN and                 $self->{ct}->{type} == DOCTYPE_TOKEN and
2304                 $self->{nc} == 0x005B) { # [                 $self->{nc} == 0x005B) { # [
# Line 2812  sub _get_next_token ($) { Line 2854  sub _get_next_token ($) {
2854        }        }
2855      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
2856        if ($is_space->{$self->{nc}}) {        if ($is_space->{$self->{nc}}) {
2857          !!!cp (215);          if ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN) {
2858          ## Stay in the state            !!!cp (215.1);
2859              $self->{state} = BEFORE_NDATA_STATE;
2860            } else {
2861              !!!cp (215);
2862              ## Stay in the state
2863            }
2864          !!!next-input-character;          !!!next-input-character;
2865          redo A;          redo A;
2866        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
# Line 2829  sub _get_next_token ($) { Line 2876  sub _get_next_token ($) {
2876          !!!next-input-character;          !!!next-input-character;
2877          !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION          !!!emit ($self->{ct}); # DOCTYPE/ENTITY/NOTATION
2878          redo A;          redo A;
2879  ## TODO: "NDATA"        } elsif ($self->{ct}->{type} == GENERAL_ENTITY_TOKEN and
2880                   ($self->{nc} == 0x004E or # N
2881                    $self->{nc} == 0x006E)) { # n
2882            !!!cp (216.2);
2883            !!!parse-error (type => 'no space before NDATA'); ## TODO: type
2884            $self->{state} = NDATA_STATE;
2885            $self->{kwd} = chr $self->{nc};
2886            !!!next-input-character;
2887            redo A;
2888        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2889          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {          if ($self->{ct}->{type} == DOCTYPE_TOKEN) {
2890            !!!cp (217);            !!!cp (217);
# Line 2871  sub _get_next_token ($) { Line 2926  sub _get_next_token ($) {
2926          !!!next-input-character;          !!!next-input-character;
2927          redo A;          redo A;
2928        }        }
2929        } elsif ($self->{state} == BEFORE_NDATA_STATE) {
2930          if ($is_space->{$self->{nc}}) {
2931            !!!cp (218.3);
2932            ## Stay in the state.
2933            !!!next-input-character;
2934            redo A;
2935          } elsif ($self->{nc} == 0x003E) { # >
2936            !!!cp (218.4);
2937            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2938            !!!next-input-character;
2939            !!!emit ($self->{ct}); # ENTITY
2940            redo A;
2941          } elsif ($self->{nc} == 0x004E or # N
2942                   $self->{nc} == 0x006E) { # n
2943            !!!cp (218.5);
2944            $self->{state} = NDATA_STATE;
2945            $self->{kwd} = chr $self->{nc};
2946            !!!next-input-character;
2947            redo A;
2948          } elsif ($self->{nc} == -1) {
2949            !!!cp (218.6);
2950            !!!parse-error (type => 'unclosed md'); ## TODO: type
2951            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
2952            ## reconsume
2953            !!!emit ($self->{ct}); # ENTITY
2954            redo A;
2955          } else {
2956            !!!cp (218.7);
2957            !!!parse-error (type => 'string after SYSTEM literal');
2958            $self->{state} = BOGUS_MD_STATE;
2959            !!!next-input-character;
2960            redo A;
2961          }
2962      } elsif ($self->{state} == BOGUS_DOCTYPE_STATE) {      } elsif ($self->{state} == BOGUS_DOCTYPE_STATE) {
2963        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
2964          !!!cp (219);          !!!cp (219);
# Line 3001  sub _get_next_token ($) { Line 3089  sub _get_next_token ($) {
3089              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
3090              $self->{entity_add} => 1,              $self->{entity_add} => 1,
3091            }->{$self->{nc}}) {            }->{$self->{nc}}) {
3092          !!!cp (1001);          if ($self->{is_xml}) {
3093              !!!cp (1001.1);
3094              !!!parse-error (type => 'bare ero',
3095                              line => $self->{line_prev},
3096                              column => $self->{column_prev}
3097                                  + ($self->{nc} == -1 ? 1 : 0));
3098            } else {
3099              !!!cp (1001);
3100              ## No error
3101            }
3102          ## Don't consume          ## Don't consume
         ## No error  
3103          ## Return nothing.          ## Return nothing.
3104          #          #
3105        } elsif ($self->{nc} == 0x0023) { # #        } elsif ($self->{nc} == 0x0023) { # #
# Line 3012  sub _get_next_token ($) { Line 3108  sub _get_next_token ($) {
3108          $self->{kwd} = '#';          $self->{kwd} = '#';
3109          !!!next-input-character;          !!!next-input-character;
3110          redo A;          redo A;
3111        } elsif ((0x0041 <= $self->{nc} and        } elsif ($self->{is_xml} or
3112                   (0x0041 <= $self->{nc} and
3113                  $self->{nc} <= 0x005A) or # A..Z                  $self->{nc} <= 0x005A) or # A..Z
3114                 (0x0061 <= $self->{nc} and                 (0x0061 <= $self->{nc} and
3115                  $self->{nc} <= 0x007A)) { # a..z                  $self->{nc} <= 0x007A)) { # a..z
# Line 3056  sub _get_next_token ($) { Line 3153  sub _get_next_token ($) {
3153          redo A;          redo A;
3154        }        }
3155      } elsif ($self->{state} == ENTITY_HASH_STATE) {      } elsif ($self->{state} == ENTITY_HASH_STATE) {
3156        if ($self->{nc} == 0x0078 or # x        if ($self->{nc} == 0x0078) { # x
           $self->{nc} == 0x0058) { # X  
3157          !!!cp (995);          !!!cp (995);
3158          $self->{state} = HEXREF_X_STATE;          $self->{state} = HEXREF_X_STATE;
3159          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
3160          !!!next-input-character;          !!!next-input-character;
3161          redo A;          redo A;
3162          } elsif ($self->{nc} == 0x0058) { # X
3163            !!!cp (995.1);
3164            if ($self->{is_xml}) {
3165              !!!parse-error (type => 'uppercase hcro'); ## TODO: type
3166            }
3167            $self->{state} = HEXREF_X_STATE;
3168            $self->{kwd} .= chr $self->{nc};
3169            !!!next-input-character;
3170            redo A;
3171        } elsif (0x0030 <= $self->{nc} and        } elsif (0x0030 <= $self->{nc} and
3172                 $self->{nc} <= 0x0039) { # 0..9                 $self->{nc} <= 0x0039) { # 0..9
3173          !!!cp (994);          !!!cp (994);
# Line 3123  sub _get_next_token ($) { Line 3228  sub _get_next_token ($) {
3228        my $code = $self->{kwd};        my $code = $self->{kwd};
3229        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3230        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3231        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
3232              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
3233              ($self->{is_xml} and $code == 0x0000)) {
3234          !!!cp (1015);          !!!cp (1015);
3235          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3236                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 3236  sub _get_next_token ($) { Line 3343  sub _get_next_token ($) {
3343        my $code = $self->{kwd};        my $code = $self->{kwd};
3344        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3345        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3346        if ($charref_map->{$code}) {        if ((not $self->{is_xml} and $charref_map->{$code}) or
3347              ($self->{is_xml} and 0xD800 <= $code and $code <= 0xDFFF) or
3348              ($self->{is_xml} and $code == 0x0000)) {
3349          !!!cp (1008);          !!!cp (1008);
3350          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3351                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
# Line 3270  sub _get_next_token ($) { Line 3379  sub _get_next_token ($) {
3379          redo A;          redo A;
3380        }        }
3381      } elsif ($self->{state} == ENTITY_NAME_STATE) {      } elsif ($self->{state} == ENTITY_NAME_STATE) {
3382        if (length $self->{kwd} < 30 and        if ((0x0041 <= $self->{nc} and # a
3383            ## NOTE: Some number greater than the maximum length of entity name             $self->{nc} <= 0x005A) or # x
3384            ((0x0041 <= $self->{nc} and # a            (0x0061 <= $self->{nc} and # a
3385              $self->{nc} <= 0x005A) or # x             $self->{nc} <= 0x007A) or # z
3386             (0x0061 <= $self->{nc} and # a            (0x0030 <= $self->{nc} and # 0
3387              $self->{nc} <= 0x007A) or # z             $self->{nc} <= 0x0039) or # 9
3388             (0x0030 <= $self->{nc} and # 0            $self->{nc} == 0x003B or # ;
3389              $self->{nc} <= 0x0039) or # 9            ($self->{is_xml} and
3390             $self->{nc} == 0x003B)) { # ;             not ($is_space->{$self->{nc}} or
3391                    {
3392                      0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
3393                      $self->{entity_add} => 1,
3394                    }->{$self->{nc}}))) {
3395          our $EntityChar;          our $EntityChar;
3396          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
3397          if (defined $EntityChar->{$self->{kwd}}) {          if (defined $EntityChar->{$self->{kwd}} or
3398                $self->{ge}->{$self->{kwd}}) {
3399            if ($self->{nc} == 0x003B) { # ;            if ($self->{nc} == 0x003B) { # ;
3400              !!!cp (1020);              if (defined $self->{ge}->{$self->{kwd}}) {
3401              $self->{entity__value} = $EntityChar->{$self->{kwd}};                if ($self->{ge}->{$self->{kwd}}->{only_text}) {
3402                    !!!cp (1020.1);
3403                    $self->{entity__value} = $self->{ge}->{$self->{kwd}}->{value};
3404                  } else {
3405                    if (defined $self->{ge}->{$self->{kwd}}->{notation}) {
3406                      !!!cp (1020.2);
3407                      !!!parse-error (type => 'unparsed entity', ## TODO: type
3408                                      value => $self->{kwd});
3409                    } else {
3410                      !!!cp (1020.3);
3411                    }
3412                    $self->{entity__value} = '&' . $self->{kwd}; ## TODO: expand
3413                  }
3414                } else {
3415                  if ($self->{is_xml}) {
3416                    !!!cp (1020.4);
3417                    !!!parse-error (type => 'entity not declared', ## TODO: type
3418                                    value => $self->{kwd},
3419                                    level => {
3420                                              'amp;' => $self->{level}->{warn},
3421                                              'quot;' => $self->{level}->{warn},
3422                                              'lt;' => $self->{level}->{warn},
3423                                              'gt;' => $self->{level}->{warn},
3424                                              'apos;' => $self->{level}->{warn},
3425                                             }->{$self->{kwd}} ||
3426                                             $self->{level}->{must});
3427                  } else {
3428                    !!!cp (1020);
3429                  }
3430                  $self->{entity__value} = $EntityChar->{$self->{kwd}};
3431                }
3432              $self->{entity__match} = 1;              $self->{entity__match} = 1;
3433              !!!next-input-character;              !!!next-input-character;
3434              #              #
# Line 3530  sub _get_next_token ($) { Line 3674  sub _get_next_token ($) {
3674          ## XML5: Not defined yet.          ## XML5: Not defined yet.
3675    
3676          ## TODO:          ## TODO:
3677    
3678            if (not $self->{stop_processing} and
3679                not $self->{document}->xml_standalone) {
3680              !!!parse-error (type => 'stop processing', ## TODO: type
3681                              level => $self->{level}->{info});
3682              $self->{stop_processing} = 1;
3683            }
3684    
3685          !!!next-input-character;          !!!next-input-character;
3686          redo A;          redo A;
3687        } elsif ($self->{nc} == 0x005D) { # ]        } elsif ($self->{nc} == 0x005D) { # ]
# Line 3632  sub _get_next_token ($) { Line 3784  sub _get_next_token ($) {
3784          $self->{state} = MD_HYPHEN_STATE;          $self->{state} = MD_HYPHEN_STATE;
3785          !!!next-input-character;          !!!next-input-character;
3786          redo A;          redo A;
3787        } elsif ($self->{nc} == 0x0045) { # E        } elsif ($self->{nc} == 0x0045 or # E
3788                   $self->{nc} == 0x0065) { # e
3789          $self->{state} = MD_E_STATE;          $self->{state} = MD_E_STATE;
3790          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
3791          !!!next-input-character;          !!!next-input-character;
3792          redo A;          redo A;
3793        } elsif ($self->{nc} == 0x0041) { # A        } elsif ($self->{nc} == 0x0041 or # A
3794                   $self->{nc} == 0x0061) { # a
3795          $self->{state} = MD_ATTLIST_STATE;          $self->{state} = MD_ATTLIST_STATE;
3796          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
3797          !!!next-input-character;          !!!next-input-character;
3798          redo A;          redo A;
3799        } elsif ($self->{nc} == 0x004E) { # N        } elsif ($self->{nc} == 0x004E or # N
3800                   $self->{nc} == 0x006E) { # n
3801          $self->{state} = MD_NOTATION_STATE;          $self->{state} = MD_NOTATION_STATE;
3802          $self->{kwd} = chr $self->{nc};          $self->{kwd} = chr $self->{nc};
3803          !!!next-input-character;          !!!next-input-character;
# Line 3660  sub _get_next_token ($) { Line 3815  sub _get_next_token ($) {
3815        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.        $self->{ct} = {type => COMMENT_TOKEN, data => ''}; ## Will be discarded.
3816        redo A;        redo A;
3817      } elsif ($self->{state} == MD_E_STATE) {      } elsif ($self->{state} == MD_E_STATE) {
3818        if ($self->{nc} == 0x004E) { # N        if ($self->{nc} == 0x004E or # N
3819              $self->{nc} == 0x006E) { # n
3820          $self->{state} = MD_ENTITY_STATE;          $self->{state} = MD_ENTITY_STATE;
3821          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
3822          !!!next-input-character;          !!!next-input-character;
3823          redo A;          redo A;
3824        } elsif ($self->{nc} == 0x004C) { # L        } elsif ($self->{nc} == 0x004C or # L
3825                   $self->{nc} == 0x006C) { # l
3826          ## XML5: <!ELEMENT> not supported.          ## XML5: <!ELEMENT> not supported.
3827          $self->{state} = MD_ELEMENT_STATE;          $self->{state} = MD_ELEMENT_STATE;
3828          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
# Line 3683  sub _get_next_token ($) { Line 3840  sub _get_next_token ($) {
3840          redo A;          redo A;
3841        }        }
3842      } elsif ($self->{state} == MD_ENTITY_STATE) {      } elsif ($self->{state} == MD_ENTITY_STATE) {
3843        if ($self->{nc} == {        if ($self->{nc} == [
3844              'EN' => 0x0054, # T              undef,
3845              'ENT' => 0x0049, # I              undef,
3846              'ENTI' => 0x0054, # T              0x0054, # T
3847            }->{$self->{kwd}}) {              0x0049, # I
3848                0x0054, # T
3849              ]->[length $self->{kwd}] or
3850              $self->{nc} == [
3851                undef,
3852                undef,
3853                0x0074, # t
3854                0x0069, # i
3855                0x0074, # t
3856              ]->[length $self->{kwd}]) {
3857          ## Stay in the state.          ## Stay in the state.
3858          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
3859          !!!next-input-character;          !!!next-input-character;
3860          redo A;          redo A;
3861        } elsif ($self->{kwd} eq 'ENTIT' and        } elsif ((length $self->{kwd}) == 5 and
3862                 $self->{nc} == 0x0059) { # Y                 ($self->{nc} == 0x0059 or # Y
3863          $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '', text => '',                  $self->{nc} == 0x0079)) { # y
3864            if ($self->{kwd} ne 'ENTIT' or $self->{nc} == 0x0079) {
3865              !!!parse-error (type => 'lowercase keyword', ## TODO: type
3866                              text => 'ENTITY',
3867                              line => $self->{line_prev},
3868                              column => $self->{column_prev} - 4);
3869            }
3870            $self->{ct} = {type => GENERAL_ENTITY_TOKEN, name => '',
3871                         line => $self->{line_prev},                         line => $self->{line_prev},
3872                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 6};
3873          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
# Line 3712  sub _get_next_token ($) { Line 3885  sub _get_next_token ($) {
3885          redo A;          redo A;
3886        }        }
3887      } elsif ($self->{state} == MD_ELEMENT_STATE) {      } elsif ($self->{state} == MD_ELEMENT_STATE) {
3888        if ($self->{nc} == {        if ($self->{nc} == [
3889              'EL' => 0x0045, # E             undef,
3890              'ELE' => 0x004D, # M             undef,
3891              'ELEM' => 0x0045, # E             0x0045, # E
3892              'ELEME' => 0x004E, # N             0x004D, # M
3893            }->{$self->{kwd}}) {             0x0045, # E
3894               0x004E, # N
3895              ]->[length $self->{kwd}] or
3896              $self->{nc} == [
3897               undef,
3898               undef,
3899               0x0065, # e
3900               0x006D, # m
3901               0x0065, # e
3902               0x006E, # n
3903              ]->[length $self->{kwd}]) {
3904          ## Stay in the state.          ## Stay in the state.
3905          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
3906          !!!next-input-character;          !!!next-input-character;
3907          redo A;          redo A;
3908        } elsif ($self->{kwd} eq 'ELEMEN' and        } elsif ((length $self->{kwd}) == 6 and
3909                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
3910                    $self->{nc} == 0x0074)) { # t
3911            if ($self->{kwd} ne 'ELEMEN' or $self->{nc} == 0x0074) {
3912              !!!parse-error (type => 'lowercase keyword', ## TODO: type
3913                              text => 'ELEMENT',
3914                              line => $self->{line_prev},
3915                              column => $self->{column_prev} - 5);
3916            }
3917          $self->{ct} = {type => ELEMENT_TOKEN, name => '',          $self->{ct} = {type => ELEMENT_TOKEN, name => '',
3918                         line => $self->{line_prev},                         line => $self->{line_prev},
3919                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
3920          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
3921          !!!next-input-character;          !!!next-input-character;
3922          redo A;          redo A;
# Line 3742  sub _get_next_token ($) { Line 3932  sub _get_next_token ($) {
3932          redo A;          redo A;
3933        }        }
3934      } elsif ($self->{state} == MD_ATTLIST_STATE) {      } elsif ($self->{state} == MD_ATTLIST_STATE) {
3935        if ($self->{nc} == {        if ($self->{nc} == [
3936              'A' => 0x0054, # T             undef,
3937              'AT' => 0x0054, # T             0x0054, # T
3938              'ATT' => 0x004C, # L             0x0054, # T
3939              'ATTL' => 0x0049, # I             0x004C, # L
3940              'ATTLI' => 0x0053, # S             0x0049, # I
3941            }->{$self->{kwd}}) {             0x0053, # S
3942              ]->[length $self->{kwd}] or
3943              $self->{nc} == [
3944               undef,
3945               0x0074, # t
3946               0x0074, # t
3947               0x006C, # l
3948               0x0069, # i
3949               0x0073, # s
3950              ]->[length $self->{kwd}]) {
3951          ## Stay in the state.          ## Stay in the state.
3952          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
3953          !!!next-input-character;          !!!next-input-character;
3954          redo A;          redo A;
3955        } elsif ($self->{kwd} eq 'ATTLIS' and        } elsif ((length $self->{kwd}) == 6 and
3956                 $self->{nc} == 0x0054) { # T                 ($self->{nc} == 0x0054 or # T
3957                    $self->{nc} == 0x0074)) { # t
3958            if ($self->{kwd} ne 'ATTLIS' or $self->{nc} == 0x0074) {
3959              !!!parse-error (type => 'lowercase keyword', ## TODO: type
3960                              text => 'ATTLIST',
3961                              line => $self->{line_prev},
3962                              column => $self->{column_prev} - 5);
3963            }
3964          $self->{ct} = {type => ATTLIST_TOKEN, name => '',          $self->{ct} = {type => ATTLIST_TOKEN, name => '',
3965                         attrdefs => [],                         attrdefs => [],
3966                         line => $self->{line_prev},                         line => $self->{line_prev},
3967                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 7};
3968          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
3969          !!!next-input-character;          !!!next-input-character;
3970          redo A;          redo A;
# Line 3774  sub _get_next_token ($) { Line 3980  sub _get_next_token ($) {
3980          redo A;          redo A;
3981        }        }
3982      } elsif ($self->{state} == MD_NOTATION_STATE) {      } elsif ($self->{state} == MD_NOTATION_STATE) {
3983        if ($self->{nc} == {        if ($self->{nc} == [
3984              'N' => 0x004F, # O             undef,
3985              'NO' => 0x0054, # T             0x004F, # O
3986              'NOT' => 0x0041, # A             0x0054, # T
3987              'NOTA' => 0x0054, # T             0x0041, # A
3988              'NOTAT' => 0x0049, # I             0x0054, # T
3989              'NOTATI' => 0x004F, # O             0x0049, # I
3990            }->{$self->{kwd}}) {             0x004F, # O
3991              ]->[length $self->{kwd}] or
3992              $self->{nc} == [
3993               undef,
3994               0x006F, # o
3995               0x0074, # t
3996               0x0061, # a
3997               0x0074, # t
3998               0x0069, # i
3999               0x006F, # o
4000              ]->[length $self->{kwd}]) {
4001          ## Stay in the state.          ## Stay in the state.
4002          $self->{kwd} .= chr $self->{nc};          $self->{kwd} .= chr $self->{nc};
4003          !!!next-input-character;          !!!next-input-character;
4004          redo A;          redo A;
4005        } elsif ($self->{kwd} eq 'NOTATIO' and        } elsif ((length $self->{kwd}) == 7 and
4006                 $self->{nc} == 0x004E) { # N                 ($self->{nc} == 0x004E or # N
4007                    $self->{nc} == 0x006E)) { # n
4008            if ($self->{kwd} ne 'NOTATIO' or $self->{nc} == 0x006E) {
4009              !!!parse-error (type => 'lowercase keyword', ## TODO: type
4010                              text => 'NOTATION',
4011                              line => $self->{line_prev},
4012                              column => $self->{column_prev} - 6);
4013            }
4014          $self->{ct} = {type => NOTATION_TOKEN, name => '',          $self->{ct} = {type => NOTATION_TOKEN, name => '',
4015                         line => $self->{line_prev},                         line => $self->{line_prev},
4016                         column => $self->{column_prev} - 6};                         column => $self->{column_prev} - 8};
4017          $self->{state} = DOCTYPE_MD_STATE;          $self->{state} = DOCTYPE_MD_STATE;
4018          !!!next-input-character;          !!!next-input-character;
4019          redo A;          redo A;
# Line 3902  sub _get_next_token ($) { Line 4125  sub _get_next_token ($) {
4125          if ($self->{ct}->{type} == ATTLIST_TOKEN) {          if ($self->{ct}->{type} == ATTLIST_TOKEN) {
4126            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;            $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;
4127          } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {          } elsif ($self->{ct}->{type} == ELEMENT_TOKEN) {
4128            ## TODO: ...            $self->{state} = AFTER_ELEMENT_NAME_STATE;
           $self->{state} = DOCTYPE_ATTLIST_NAME_AFTER_STATE;  
4129          } else { # ENTITY/NOTATION          } else { # ENTITY/NOTATION
4130            $self->{state} = AFTER_DOCTYPE_NAME_STATE;            $self->{state} = AFTER_DOCTYPE_NAME_STATE;
4131          }          }
# Line 4431  sub _get_next_token ($) { Line 4653  sub _get_next_token ($) {
4653          ## Reconsume.          ## Reconsume.
4654          redo A;          redo A;
4655        }        }
4656        } elsif ($self->{state} == NDATA_STATE) {
4657          ## ASCII case-insensitive
4658          if ($self->{nc} == [
4659                undef,
4660                0x0044, # D
4661                0x0041, # A
4662                0x0054, # T
4663              ]->[length $self->{kwd}] or
4664              $self->{nc} == [
4665                undef,
4666                0x0064, # d
4667                0x0061, # a
4668                0x0074, # t
4669              ]->[length $self->{kwd}]) {
4670            !!!cp (172.2);
4671            ## Stay in the state.
4672            $self->{kwd} .= chr $self->{nc};
4673            !!!next-input-character;
4674            redo A;
4675          } elsif ((length $self->{kwd}) == 4 and
4676                   ($self->{nc} == 0x0041 or # A
4677                    $self->{nc} == 0x0061)) { # a
4678            if ($self->{kwd} ne 'NDAT' or $self->{nc} == 0x0061) { # a
4679              !!!cp (172.3);
4680              !!!parse-error (type => 'lowercase keyword', ## TODO: type
4681                              text => 'NDATA',
4682                              line => $self->{line_prev},
4683                              column => $self->{column_prev} - 4);
4684            } else {
4685              !!!cp (172.4);
4686            }
4687            $self->{state} = AFTER_NDATA_STATE;
4688            !!!next-input-character;
4689            redo A;
4690          } else {
4691            !!!parse-error (type => 'string after literal', ## TODO: type
4692                            line => $self->{line_prev},
4693                            column => $self->{column_prev} + 1
4694                                - length $self->{kwd});
4695            !!!cp (172.5);
4696            $self->{state} = BOGUS_MD_STATE;
4697            ## Reconsume.
4698            redo A;
4699          }
4700        } elsif ($self->{state} == AFTER_NDATA_STATE) {
4701          if ($is_space->{$self->{nc}}) {
4702            $self->{state} = BEFORE_NOTATION_NAME_STATE;
4703            !!!next-input-character;
4704            redo A;
4705          } elsif ($self->{nc} == 0x003E) { # >
4706            !!!parse-error (type => 'no notation name'); ## TODO: type
4707            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4708            !!!next-input-character;
4709            !!!emit ($self->{ct}); # ENTITY
4710            redo A;
4711          } elsif ($self->{nc} == -1) {
4712            !!!parse-error (type => 'unclosed md'); ## TODO: type
4713            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4714            !!!next-input-character;
4715            !!!emit ($self->{ct}); # ENTITY
4716            redo A;
4717          } else {
4718            !!!parse-error (type => 'string after literal', ## TODO: type
4719                            line => $self->{line_prev},
4720                            column => $self->{column_prev} + 1
4721                                - length $self->{kwd});
4722            $self->{state} = BOGUS_MD_STATE;
4723            ## Reconsume.
4724            redo A;
4725          }
4726        } elsif ($self->{state} == BEFORE_NOTATION_NAME_STATE) {
4727          if ($is_space->{$self->{nc}}) {
4728            ## Stay in the state.
4729            !!!next-input-character;
4730            redo A;
4731          } elsif ($self->{nc} == 0x003E) { # >
4732            !!!parse-error (type => 'no notation name'); ## TODO: type
4733            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4734            !!!next-input-character;
4735            !!!emit ($self->{ct}); # ENTITY
4736            redo A;
4737          } elsif ($self->{nc} == -1) {
4738            !!!parse-error (type => 'unclosed md'); ## TODO: type
4739            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4740            !!!next-input-character;
4741            !!!emit ($self->{ct}); # ENTITY
4742            redo A;
4743          } else {
4744            $self->{ct}->{notation} = chr $self->{nc}; # ENTITY
4745            $self->{state} = NOTATION_NAME_STATE;
4746            !!!next-input-character;
4747            redo A;
4748          }
4749        } elsif ($self->{state} == NOTATION_NAME_STATE) {
4750          if ($is_space->{$self->{nc}}) {
4751            $self->{state} = AFTER_MD_DEF_STATE;
4752            !!!next-input-character;
4753            redo A;
4754          } elsif ($self->{nc} == 0x003E) { # >
4755            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4756            !!!next-input-character;
4757            !!!emit ($self->{ct}); # ENTITY
4758            redo A;
4759          } elsif ($self->{nc} == -1) {
4760            !!!parse-error (type => 'unclosed md'); ## TODO: type
4761            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4762            !!!next-input-character;
4763            !!!emit ($self->{ct}); # ENTITY
4764            redo A;
4765          } else {
4766            $self->{ct}->{notation} .= chr $self->{nc}; # ENTITY
4767            ## Stay in the state.
4768            !!!next-input-character;
4769            redo A;
4770          }
4771        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_DOUBLE_QUOTED_STATE) {
4772          if ($self->{nc} == 0x0022) { # "
4773            $self->{state} = AFTER_MD_DEF_STATE;
4774            !!!next-input-character;
4775            redo A;
4776          } elsif ($self->{nc} == 0x0026) { # &
4777            $self->{prev_state} = $self->{state};
4778            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
4779            $self->{entity_add} = 0x0022; # "
4780            !!!next-input-character;
4781            redo A;
4782    ## TODO: %
4783          } elsif ($self->{nc} == -1) {
4784            !!!parse-error (type => 'unclosed entity value'); ## TODO: type
4785            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4786            ## Reconsume.
4787            !!!emit ($self->{ct}); # ENTITY
4788            redo A;
4789          } else {
4790            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
4791            !!!next-input-character;
4792            redo A;
4793          }
4794        } elsif ($self->{state} == DOCTYPE_ENTITY_VALUE_SINGLE_QUOTED_STATE) {
4795          if ($self->{nc} == 0x0027) { # '
4796            $self->{state} = AFTER_MD_DEF_STATE;
4797            !!!next-input-character;
4798            redo A;
4799          } elsif ($self->{nc} == 0x0026) { # &
4800            $self->{prev_state} = $self->{state};
4801            $self->{state} = ENTITY_VALUE_ENTITY_STATE;
4802            $self->{entity_add} = 0x0027; # '
4803            !!!next-input-character;
4804            redo A;
4805    ## TODO: %
4806          } elsif ($self->{nc} == -1) {
4807            !!!parse-error (type => 'unclosed entity value'); ## TODO: type
4808            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4809            ## Reconsume.
4810            !!!emit ($self->{ct}); # ENTITY
4811            redo A;
4812          } else {
4813            $self->{ct}->{value} .= chr $self->{nc}; # ENTITY
4814            !!!next-input-character;
4815            redo A;
4816          }
4817        } elsif ($self->{state} == ENTITY_VALUE_ENTITY_STATE) {
4818          if ($is_space->{$self->{nc}} or
4819              {
4820                0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
4821                $self->{entity_add} => 1,
4822              }->{$self->{nc}}) {
4823            !!!parse-error (type => 'bare ero',
4824                            line => $self->{line_prev},
4825                            column => $self->{column_prev}
4826                                + ($self->{nc} == -1 ? 1 : 0));
4827            ## Don't consume
4828            ## Return nothing.
4829            #
4830          } elsif ($self->{nc} == 0x0023) { # #
4831            $self->{ca} = $self->{ct};
4832            $self->{state} = ENTITY_HASH_STATE;
4833            $self->{kwd} = '#';
4834            !!!next-input-character;
4835            redo A;
4836          } else {
4837            #
4838          }
4839    
4840          $self->{ct}->{value} .= '&';
4841          $self->{state} = $self->{prev_state};
4842          ## Reconsume.
4843          redo A;
4844        } elsif ($self->{state} == AFTER_ELEMENT_NAME_STATE) {
4845          if ($is_space->{$self->{nc}}) {
4846            $self->{state} = BEFORE_ELEMENT_CONTENT_STATE;
4847            !!!next-input-character;
4848            redo A;
4849          } elsif ($self->{nc} == 0x0028) { # (
4850            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
4851            $self->{ct}->{content} = ['('];
4852            $self->{group_depth} = 1;
4853            !!!next-input-character;
4854            redo A;
4855          } elsif ($self->{nc} == 0x003E) { # >
4856            !!!parse-error (type => 'no md def'); ## TODO: type
4857            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4858            !!!next-input-character;
4859            !!!emit ($self->{ct}); # ELEMENT
4860            redo A;
4861          } elsif ($self->{nc} == -1) {
4862            !!!parse-error (type => 'unclosed md'); ## TODO: type
4863            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4864            !!!next-input-character;
4865            !!!emit ($self->{ct}); # ELEMENT
4866            redo A;
4867          } else {
4868            $self->{ct}->{content} = [chr $self->{nc}];
4869            $self->{state} = CONTENT_KEYWORD_STATE;
4870            !!!next-input-character;
4871            redo A;
4872          }
4873        } elsif ($self->{state} == CONTENT_KEYWORD_STATE) {
4874          if ($is_space->{$self->{nc}}) {
4875            $self->{state} = AFTER_MD_DEF_STATE;
4876            !!!next-input-character;
4877            redo A;
4878          } elsif ($self->{nc} == 0x003E) { # >
4879            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4880            !!!next-input-character;
4881            !!!emit ($self->{ct}); # ELEMENT
4882            redo A;
4883          } elsif ($self->{nc} == -1) {
4884            !!!parse-error (type => 'unclosed md'); ## TODO: type
4885            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4886            !!!next-input-character;
4887            !!!emit ($self->{ct}); # ELEMENT
4888            redo A;
4889          } else {
4890            $self->{ct}->{content}->[-1] .= chr $self->{nc}; # ELEMENT
4891            ## Stay in the state.
4892            !!!next-input-character;
4893            redo A;
4894          }
4895        } elsif ($self->{state} == AFTER_CM_GROUP_OPEN_STATE) {
4896          if ($is_space->{$self->{nc}}) {
4897            ## Stay in the state.
4898            !!!next-input-character;
4899            redo A;
4900          } elsif ($self->{nc} == 0x0028) { # (
4901            $self->{group_depth}++;
4902            push @{$self->{ct}->{content}}, chr $self->{nc};
4903            ## Stay in the state.
4904            !!!next-input-character;
4905            redo A;
4906          } elsif ($self->{nc} == 0x007C or # |
4907                   $self->{nc} == 0x002C) { # ,
4908            !!!parse-error (type => 'empty element name'); ## TODO: type
4909            ## Stay in the state.
4910            !!!next-input-character;
4911            redo A;
4912          } elsif ($self->{nc} == 0x0029) { # )
4913            !!!parse-error (type => 'empty element name'); ## TODO: type
4914            push @{$self->{ct}->{content}}, chr $self->{nc};
4915            $self->{group_depth}--;
4916            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
4917            !!!next-input-character;
4918            redo A;
4919          } elsif ($self->{nc} == 0x003E) { # >
4920            !!!parse-error (type => 'unclosed cm group'); ## TODO: type
4921            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
4922            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4923            !!!next-input-character;
4924            !!!emit ($self->{ct}); # ELEMENT
4925            redo A;
4926          } elsif ($self->{nc} == -1) {
4927            !!!parse-error (type => 'unclosed md'); ## TODO: type
4928            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
4929            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4930            !!!next-input-character;
4931            !!!emit ($self->{ct}); # ELEMENT
4932            redo A;
4933          } else {
4934            push @{$self->{ct}->{content}}, chr $self->{nc};
4935            $self->{state} = CM_ELEMENT_NAME_STATE;
4936            !!!next-input-character;
4937            redo A;
4938          }
4939        } elsif ($self->{state} == CM_ELEMENT_NAME_STATE) {
4940          if ($is_space->{$self->{nc}}) {
4941            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
4942            !!!next-input-character;
4943            redo A;
4944          } elsif ($self->{nc} == 0x002A or # *
4945                   $self->{nc} == 0x002B or # +
4946                   $self->{nc} == 0x003F) { # ?
4947            push @{$self->{ct}->{content}}, chr $self->{nc};
4948            $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
4949            !!!next-input-character;
4950            redo A;
4951          } elsif ($self->{nc} == 0x007C or # |
4952                   $self->{nc} == 0x002C) { # ,
4953            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
4954            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
4955            !!!next-input-character;
4956            redo A;
4957          } elsif ($self->{nc} == 0x0029) { # )
4958            $self->{group_depth}--;
4959            push @{$self->{ct}->{content}}, chr $self->{nc};
4960            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
4961            !!!next-input-character;
4962            redo A;
4963          } elsif ($self->{nc} == 0x003E) { # >
4964            !!!parse-error (type => 'unclosed cm group'); ## TODO: type
4965            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
4966            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4967            !!!next-input-character;
4968            !!!emit ($self->{ct}); # ELEMENT
4969            redo A;
4970          } elsif ($self->{nc} == -1) {
4971            !!!parse-error (type => 'unclosed md'); ## TODO: type
4972            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
4973            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
4974            !!!next-input-character;
4975            !!!emit ($self->{ct}); # ELEMENT
4976            redo A;
4977          } else {
4978            $self->{ct}->{content}->[-1] .= chr $self->{nc};
4979            ## Stay in the state.
4980            !!!next-input-character;
4981            redo A;
4982          }
4983        } elsif ($self->{state} == AFTER_CM_ELEMENT_NAME_STATE) {
4984          if ($is_space->{$self->{nc}}) {
4985            ## Stay in the state.
4986            !!!next-input-character;
4987            redo A;
4988          } elsif ($self->{nc} == 0x007C or # |
4989                   $self->{nc} == 0x002C) { # ,
4990            push @{$self->{ct}->{content}}, $self->{nc} == 0x007C ? ' | ' : ', ';
4991            $self->{state} = AFTER_CM_GROUP_OPEN_STATE;
4992            !!!next-input-character;
4993            redo A;
4994          } elsif ($self->{nc} == 0x0029) { # )
4995            $self->{group_depth}--;
4996            push @{$self->{ct}->{content}}, chr $self->{nc};
4997            $self->{state} = AFTER_CM_GROUP_CLOSE_STATE;
4998            !!!next-input-character;
4999            redo A;
5000          } elsif ($self->{nc} == 0x003E) { # >
5001            !!!parse-error (type => 'unclosed cm group'); ## TODO: type
5002            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5003            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5004            !!!next-input-character;
5005            !!!emit ($self->{ct}); # ELEMENT
5006            redo A;
5007          } elsif ($self->{nc} == -1) {
5008            !!!parse-error (type => 'unclosed md'); ## TODO: type
5009            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5010            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5011            !!!next-input-character;
5012            !!!emit ($self->{ct}); # ELEMENT
5013            redo A;
5014          } else {
5015            !!!parse-error (type => 'after element name'); ## TODO: type
5016            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5017            $self->{state} = BOGUS_MD_STATE;
5018            !!!next-input-character;
5019            redo A;
5020          }
5021        } elsif ($self->{state} == AFTER_CM_GROUP_CLOSE_STATE) {
5022          if ($is_space->{$self->{nc}}) {
5023            if ($self->{group_depth}) {
5024              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5025            } else {
5026              $self->{state} = AFTER_MD_DEF_STATE;
5027            }
5028            !!!next-input-character;
5029            redo A;
5030          } elsif ($self->{nc} == 0x002A or # *
5031                   $self->{nc} == 0x002B or # +
5032                   $self->{nc} == 0x003F) { # ?
5033            push @{$self->{ct}->{content}}, chr $self->{nc};
5034            if ($self->{group_depth}) {
5035              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5036            } else {
5037              $self->{state} = AFTER_MD_DEF_STATE;
5038            }
5039            !!!next-input-character;
5040            redo A;
5041          } elsif ($self->{nc} == 0x0029) { # )
5042            if ($self->{group_depth}) {
5043              $self->{group_depth}--;
5044              push @{$self->{ct}->{content}}, chr $self->{nc};
5045              ## Stay in the state.
5046              !!!next-input-character;
5047              redo A;
5048            } else {
5049              !!!parse-error (type => 'string after md def'); ## TODO: type
5050              $self->{state} = BOGUS_MD_STATE;
5051              ## Reconsume.
5052              redo A;
5053            }
5054          } elsif ($self->{nc} == 0x003E) { # >
5055            if ($self->{group_depth}) {
5056              !!!parse-error (type => 'unclosed cm group'); ## TODO: type
5057              push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5058            }
5059            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5060            !!!next-input-character;
5061            !!!emit ($self->{ct}); # ELEMENT
5062            redo A;
5063          } elsif ($self->{nc} == -1) {
5064            !!!parse-error (type => 'unclosed md'); ## TODO: type
5065            push @{$self->{ct}->{content}}, (')') x $self->{group_depth};
5066            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5067            !!!next-input-character;
5068            !!!emit ($self->{ct}); # ELEMENT
5069            redo A;
5070          } else {
5071            if ($self->{group_depth}) {
5072              $self->{state} = AFTER_CM_ELEMENT_NAME_STATE;
5073            } else {
5074              !!!parse-error (type => 'string after md def'); ## TODO: type
5075              $self->{state} = BOGUS_MD_STATE;
5076            }
5077            ## Reconsume.
5078            redo A;
5079          }
5080        } elsif ($self->{state} == AFTER_MD_DEF_STATE) {
5081          if ($is_space->{$self->{nc}}) {
5082            ## Stay in the state.
5083            !!!next-input-character;
5084            redo A;
5085          } elsif ($self->{nc} == 0x003E) { # >
5086            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5087            !!!next-input-character;
5088            !!!emit ($self->{ct}); # ENTITY/ELEMENT
5089            redo A;
5090          } elsif ($self->{nc} == -1) {
5091            !!!parse-error (type => 'unclosed md'); ## TODO: type
5092            $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;
5093            !!!next-input-character;
5094            !!!emit ($self->{ct}); # ENTITY/ELEMENT
5095            redo A;
5096          } else {
5097            !!!parse-error (type => 'string after md def'); ## TODO: type
5098            $self->{state} = BOGUS_MD_STATE;
5099            ## Reconsume.
5100            redo A;
5101          }
5102      } elsif ($self->{state} == BOGUS_MD_STATE) {      } elsif ($self->{state} == BOGUS_MD_STATE) {
5103        if ($self->{nc} == 0x003E) { # >        if ($self->{nc} == 0x003E) { # >
5104          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;          $self->{state} = DOCTYPE_INTERNAL_SUBSET_STATE;

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24