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

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24