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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.44 by wakaba, Sat Jul 21 07:34:32 2007 UTC revision 1.50 by wakaba, Sat Jul 21 10:59:40 2007 UTC
# Line 2067  sub _reset_insertion_mode ($) { Line 2067  sub _reset_insertion_mode ($) {
2067                        th => 'in cell',                        th => 'in cell',
2068                        tr => 'in row',                        tr => 'in row',
2069                        tbody => 'in table body',                        tbody => 'in table body',
2070                        thead => 'in table head',                        thead => 'in table body',
2071                        tfoot => 'in table foot',                        tfoot => 'in table body',
2072                        caption => 'in caption',                        caption => 'in caption',
2073                        colgroup => 'in column group',                        colgroup => 'in column group',
2074                        table => 'in table',                        table => 'in table',
# Line 3409  sub _tree_construction_main ($) { Line 3409  sub _tree_construction_main ($) {
3409        }        }
3410        !!!next-token;        !!!next-token;
3411        redo B;        redo B;
3412      } elsif ($self->{insertion_mode} eq 'before head') {      } elsif ($self->{insertion_mode} eq 'in head' or
3413            if ($token->{type} eq 'character') {               $self->{insertion_mode} eq 'in head noscript' or
3414              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {               $self->{insertion_mode} eq 'after head' or
3415                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);               $self->{insertion_mode} eq 'before head') {
3416                unless (length $token->{data}) {        if ($token->{type} eq 'character') {
3417                  !!!next-token;          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {
3418                  redo B;            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
3419                }            unless (length $token->{data}) {
3420              }              !!!next-token;
3421              ## As if <head>              redo B;
3422              !!!create-element ($self->{head_element}, 'head');            }
3423              $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});          }
3424              push @{$self->{open_elements}}, [$self->{head_element}, 'head'];  
3425              $self->{insertion_mode} = 'in head';          if ($self->{insertion_mode} eq 'before head') {
3426              ## As if <head>
3427              !!!create-element ($self->{head_element}, 'head');
3428              $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3429              push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3430    
3431              ## Reprocess in the "in head" insertion mode...
3432              pop @{$self->{open_elements}};
3433    
3434              ## Reprocess in the "after head" insertion mode...
3435            } elsif ($self->{insertion_mode} eq 'in head noscript') {
3436              ## As if </noscript>
3437              pop @{$self->{open_elements}};
3438              !!!parse-error (type => 'in noscript:#character');
3439              
3440              ## Reprocess in the "in head" insertion mode...
3441              ## As if </head>
3442              pop @{$self->{open_elements}};
3443    
3444              ## Reprocess in the "after head" insertion mode...
3445            } elsif ($self->{insertion_mode} eq 'in head') {
3446              pop @{$self->{open_elements}};
3447    
3448              ## Reprocess in the "after head" insertion mode...
3449            }
3450    
3451                ## "after head" insertion mode
3452                ## As if <body>
3453                !!!insert-element ('body');
3454                $self->{insertion_mode} = 'in body';
3455              ## reprocess              ## reprocess
3456              redo B;              redo B;
3457            } elsif ($token->{type} eq 'start tag') {            } elsif ($token->{type} eq 'start tag') {
             my $attr = $token->{tag_name} eq 'head' ? $token->{attributes} : {};  
             !!!create-element ($self->{head_element}, 'head', $attr);  
             $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});  
             push @{$self->{open_elements}}, [$self->{head_element}, 'head'];  
             $self->{insertion_mode} = 'in head';  
3458              if ($token->{tag_name} eq 'head') {              if ($token->{tag_name} eq 'head') {
3459                !!!next-token;                if ($self->{insertion_mode} eq 'before head') {
3460              #} elsif ({                  !!!create-element ($self->{head_element}, $token->{tag_name}, $token->{attributes});
3461              #          base => 1, link => 1, meta => 1,                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3462              #          script => 1, style => 1, title => 1,                  push @{$self->{open_elements}}, [$self->{head_element}, $token->{tag_name}];
3463              #         }->{$token->{tag_name}}) {                  $self->{insertion_mode} = 'in head';
3464              #  ## reprocess                  !!!next-token;
3465              } else {                  redo B;
3466                ## reprocess                } elsif ($self->{insertion_mode} ne 'after head') {
3467              }                  !!!parse-error (type => 'in head:head'); # or in head noscript
3468              redo B;                  ## Ignore the token
3469            } elsif ($token->{type} eq 'end tag') {                  !!!next-token;
3470              if ({                  redo B;
3471                   head => 1, body => 1, html => 1,                } else {
3472                   p => 1, br => 1,                  #
3473                  }->{$token->{tag_name}}) {                }
3474                } elsif ($self->{insertion_mode} eq 'before head') {
3475                ## As if <head>                ## As if <head>
3476                !!!create-element ($self->{head_element}, 'head');                !!!create-element ($self->{head_element}, 'head');
3477                $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3478                push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3479    
3480                $self->{insertion_mode} = 'in head';                $self->{insertion_mode} = 'in head';
3481                ## reprocess                ## Reprocess in the "in head" insertion mode...
               redo B;  
             } else {  
               !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});  
               ## Ignore the token ## ISSUE: An issue in the spec.  
               !!!next-token;  
               redo B;  
3482              }              }
3483            } else {  
3484              die "$0: $token->{type}: Unknown type";              if ($token->{tag_name} eq 'base') {
3485            }                if ($self->{insertion_mode} eq 'in head noscript') {
3486          } elsif ($self->{insertion_mode} eq 'in head' or                  ## As if </noscript>
3487                   $self->{insertion_mode} eq 'in head noscript' or                  pop @{$self->{open_elements}};
3488                   $self->{insertion_mode} eq 'after head') {                  !!!parse-error (type => 'in noscript:base');
3489            if ($token->{type} eq 'character') {                
3490              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {                  $self->{insertion_mode} = 'in head';
3491                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);                  ## Reprocess in the "in head" insertion mode...
               unless (length $token->{data}) {  
                 !!!next-token;  
                 redo B;  
3492                }                }
3493              }  
3494                              ## NOTE: There is a "as if in head" code clone.
3495              #                if ($self->{insertion_mode} eq 'after head') {
3496            } elsif ($token->{type} eq 'start tag') {                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3497              if ({base => ($self->{insertion_mode} eq 'in head' or                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3498                            $self->{insertion_mode} eq 'after head'),                }
3499                   link => 1}->{$token->{tag_name}}) {                !!!insert-element ($token->{tag_name}, $token->{attributes});
3500                  pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
3501                  pop @{$self->{open_elements}}
3502                      if $self->{insertion_mode} eq 'after head';
3503                  !!!next-token;
3504                  redo B;
3505                } elsif ($token->{tag_name} eq 'link') {
3506                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3507                if ($self->{insertion_mode} eq 'after head') {                if ($self->{insertion_mode} eq 'after head') {
3508                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
# Line 3522  sub _tree_construction_main ($) { Line 3545  sub _tree_construction_main ($) {
3545                    if $self->{insertion_mode} eq 'after head';                    if $self->{insertion_mode} eq 'after head';
3546                !!!next-token;                !!!next-token;
3547                redo B;                redo B;
3548              } elsif ($token->{tag_name} eq 'title' and              } elsif ($token->{tag_name} eq 'title') {
3549                       $self->{insertion_mode} eq 'in head') {                if ($self->{insertion_mode} eq 'in head noscript') {
3550                ## NOTE: There is a "as if in head" code clone.                  ## As if </noscript>
3551                if ($self->{insertion_mode} eq 'after head') {                  pop @{$self->{open_elements}};
3552                    !!!parse-error (type => 'in noscript:title');
3553                  
3554                    $self->{insertion_mode} = 'in head';
3555                    ## Reprocess in the "in head" insertion mode...
3556                  } elsif ($self->{insertion_mode} eq 'after head') {
3557                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3558                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3559                }                }
3560    
3561                  ## NOTE: There is a "as if in head" code clone.
3562                my $parent = defined $self->{head_element} ? $self->{head_element}                my $parent = defined $self->{head_element} ? $self->{head_element}
3563                    : $self->{open_elements}->[-1]->[0];                    : $self->{open_elements}->[-1]->[0];
3564                $parse_rcdata->(RCDATA_CONTENT_MODEL,                $parse_rcdata->(RCDATA_CONTENT_MODEL,
# Line 3563  sub _tree_construction_main ($) { Line 3593  sub _tree_construction_main ($) {
3593                } else {                } else {
3594                  #                  #
3595                }                }
3596              } elsif ($token->{tag_name} eq 'head' and              } elsif ($token->{tag_name} eq 'script') {
3597                       $self->{insertion_mode} ne 'after head') {                if ($self->{insertion_mode} eq 'in head noscript') {
3598                !!!parse-error (type => 'in head:head'); # or in head noscript                  ## As if </noscript>
3599                ## Ignore the token                  pop @{$self->{open_elements}};
3600                !!!next-token;                  !!!parse-error (type => 'in noscript:script');
3601                redo B;                
3602              } elsif ($self->{insertion_mode} ne 'in head noscript' and                  $self->{insertion_mode} = 'in head';
3603                       $token->{tag_name} eq 'script') {                  ## Reprocess in the "in head" insertion mode...
3604                if ($self->{insertion_mode} eq 'after head') {                } elsif ($self->{insertion_mode} eq 'after head') {
3605                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3606                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3607                }                }
3608    
3609                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3610                $script_start_tag->($insert_to_current);                $script_start_tag->($insert_to_current);
3611                pop @{$self->{open_elements}}                pop @{$self->{open_elements}}
3612                    if $self->{insertion_mode} eq 'after head';                    if $self->{insertion_mode} eq 'after head';
3613                redo B;                redo B;
3614              } elsif ($self->{insertion_mode} eq 'after head' and              } elsif ($token->{tag_name} eq 'body' or
                      $token->{tag_name} eq 'body') {  
               !!!insert-element ('body', $token->{attributes});  
               $self->{insertion_mode} = 'in body';  
               !!!next-token;  
               redo B;  
             } elsif ($self->{insertion_mode} eq 'after head' and  
3615                       $token->{tag_name} eq 'frameset') {                       $token->{tag_name} eq 'frameset') {
3616                !!!insert-element ('frameset', $token->{attributes});                if ($self->{insertion_mode} eq 'in head noscript') {
3617                $self->{insertion_mode} = 'in frameset';                  ## As if </noscript>
3618                    pop @{$self->{open_elements}};
3619                    !!!parse-error (type => 'in noscript:'.$token->{tag_name});
3620                    
3621                    ## Reprocess in the "in head" insertion mode...
3622                    ## As if </head>
3623                    pop @{$self->{open_elements}};
3624                    
3625                    ## Reprocess in the "after head" insertion mode...
3626                  } elsif ($self->{insertion_mode} eq 'in head') {
3627                    pop @{$self->{open_elements}};
3628                    
3629                    ## Reprocess in the "after head" insertion mode...
3630                  }
3631    
3632                  ## "after head" insertion mode
3633                  !!!insert-element ($token->{tag_name}, $token->{attributes});
3634                  $self->{insertion_mode} = 'in '.$token->{tag_name};
3635                !!!next-token;                !!!next-token;
3636                redo B;                redo B;
3637              } else {              } else {
3638                #                #
3639              }              }
3640            } elsif ($token->{type} eq 'end tag') {  
3641              if ($self->{insertion_mode} eq 'in head' and              if ($self->{insertion_mode} eq 'in head noscript') {
3642                  $token->{tag_name} eq 'head') {                ## As if </noscript>
3643                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
3644                $self->{insertion_mode} = 'after head';                !!!parse-error (type => 'in noscript:/'.$token->{tag_name});
3645                !!!next-token;                
3646                redo B;                ## Reprocess in the "in head" insertion mode...
3647              } elsif ($self->{insertion_mode} eq 'in head noscript' and                ## As if </head>
                 $token->{tag_name} eq 'noscript') {  
3648                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
3649                $self->{insertion_mode} = 'in head';  
3650                !!!next-token;                ## Reprocess in the "after head" insertion mode...
3651                redo B;              } elsif ($self->{insertion_mode} eq 'in head') {
3652              } elsif ($self->{insertion_mode} eq 'in head' and                ## As if </head>
3653                       {                pop @{$self->{open_elements}};
3654    
3655                  ## Reprocess in the "after head" insertion mode...
3656                }
3657    
3658                ## "after head" insertion mode
3659                ## As if <body>
3660                !!!insert-element ('body');
3661                $self->{insertion_mode} = 'in body';
3662                ## reprocess
3663                redo B;
3664              } elsif ($token->{type} eq 'end tag') {
3665                if ($token->{tag_name} eq 'head') {
3666                  if ($self->{insertion_mode} eq 'before head') {
3667                    ## As if <head>
3668                    !!!create-element ($self->{head_element}, 'head');
3669                    $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3670                    push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3671    
3672                    ## Reprocess in the "in head" insertion mode...
3673                    pop @{$self->{open_elements}};
3674                    $self->{insertion_mode} = 'after head';
3675                    !!!next-token;
3676                    redo B;
3677                  } elsif ($self->{insertion_mode} eq 'in head noscript') {
3678                    ## As if </noscript>
3679                    pop @{$self->{open_elements}};
3680                    !!!parse-error (type => 'in noscript:script');
3681                    
3682                    ## Reprocess in the "in head" insertion mode...
3683                    pop @{$self->{open_elements}};
3684                    $self->{insertion_mode} = 'after head';
3685                    !!!next-token;
3686                    redo B;
3687                  } elsif ($self->{insertion_mode} eq 'in head') {
3688                    pop @{$self->{open_elements}};
3689                    $self->{insertion_mode} = 'after head';
3690                    !!!next-token;
3691                    redo B;
3692                  } else {
3693                    #
3694                  }
3695                } elsif ($token->{tag_name} eq 'noscript') {
3696                  if ($self->{insertion_mode} eq 'in head noscript') {
3697                    pop @{$self->{open_elements}};
3698                    $self->{insertion_mode} = 'in head';
3699                    !!!next-token;
3700                    redo B;
3701                  } elsif ($self->{insertion_mode} eq 'before head') {
3702                    !!!parse-error (type => 'unmatched end tag:noscript');
3703                    ## Ignore the token ## ISSUE: An issue in the spec.
3704                    !!!next-token;
3705                    redo B;
3706                  } else {
3707                    #
3708                  }
3709                } elsif ({
3710                        body => 1, html => 1,                        body => 1, html => 1,
                       p => 1, br => 1,  
3711                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
3712                  if ($self->{insertion_mode} eq 'before head') {
3713                    ## As if <head>
3714                    !!!create-element ($self->{head_element}, 'head');
3715                    $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3716                    push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3717    
3718                    $self->{insertion_mode} = 'in head';
3719                    ## Reprocess in the "in head" insertion mode...
3720                  } elsif ($self->{insertion_mode} eq 'in head noscript') {
3721                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3722                    ## Ignore the token
3723                    !!!next-token;
3724                    redo B;
3725                  }
3726                  
3727                #                #
3728              } elsif ($self->{insertion_mode} eq 'in head noscript' and              } elsif ({
                      {  
3729                        p => 1, br => 1,                        p => 1, br => 1,
3730                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
3731                  if ($self->{insertion_mode} eq 'before head') {
3732                    ## As if <head>
3733                    !!!create-element ($self->{head_element}, 'head');
3734                    $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3735                    push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3736    
3737                    $self->{insertion_mode} = 'in head';
3738                    ## Reprocess in the "in head" insertion mode...
3739                  }
3740    
3741                #                #
3742              } elsif ($self->{insertion_mode} ne 'after head') {              } else {
3743                  if ($self->{insertion_mode} ne 'after head') {
3744                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3745                    ## Ignore the token
3746                    !!!next-token;
3747                    redo B;
3748                  } else {
3749                    #
3750                  }
3751                }
3752    
3753                if ($self->{insertion_mode} eq 'in head noscript') {
3754                  ## As if </noscript>
3755                  pop @{$self->{open_elements}};
3756                  !!!parse-error (type => 'in noscript:/'.$token->{tag_name});
3757                  
3758                  ## Reprocess in the "in head" insertion mode...
3759                  ## As if </head>
3760                  pop @{$self->{open_elements}};
3761    
3762                  ## Reprocess in the "after head" insertion mode...
3763                } elsif ($self->{insertion_mode} eq 'in head') {
3764                  ## As if </head>
3765                  pop @{$self->{open_elements}};
3766    
3767                  ## Reprocess in the "after head" insertion mode...
3768                } elsif ($self->{insertion_mode} eq 'before head') {
3769                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3770                ## Ignore the token                ## Ignore the token ## ISSUE: An issue in the spec.
3771                !!!next-token;                !!!next-token;
3772                redo B;                redo B;
             } else {  
               #  
3773              }              }
           } else {  
             #  
           }  
3774    
3775            ## As if </head> or </noscript> or <body>              ## "after head" insertion mode
3776            if ($self->{insertion_mode} eq 'in head') {              ## As if <body>
             pop @{$self->{open_elements}};  
             $self->{insertion_mode} = 'after head';  
           } elsif ($self->{insertion_mode} eq 'in head noscript') {  
             pop @{$self->{open_elements}};  
             !!!parse-error (type => 'in noscript:'.(defined $token->{tag_name} ? ($token->{type} eq 'end tag' ? '/' : '') . $token->{tag_name} : '#' . $token->{type}));  
             $self->{insertion_mode} = 'in head';  
           } else { # 'after head'  
3777              !!!insert-element ('body');              !!!insert-element ('body');
3778              $self->{insertion_mode} = 'in body';              $self->{insertion_mode} = 'in body';
3779                ## reprocess
3780                redo B;
3781              } else {
3782                die "$0: $token->{type}: Unknown token type";
3783            }            }
           ## reprocess  
           redo B;  
3784    
3785            ## ISSUE: An issue in the spec.            ## ISSUE: An issue in the spec.
3786          } elsif ($self->{insertion_mode} eq 'in body' or      } elsif ($self->{insertion_mode} eq 'in body' or
3787                   $self->{insertion_mode} eq 'in cell' or               $self->{insertion_mode} eq 'in cell' or
3788                   $self->{insertion_mode} eq 'in caption') {               $self->{insertion_mode} eq 'in caption') {
3789            if ($token->{type} eq 'character') {            if ($token->{type} eq 'character') {
3790              ## NOTE: There is a code clone of "character in body".              ## NOTE: There is a code clone of "character in body".
3791              $reconstruct_active_formatting_elements->($insert_to_current);              $reconstruct_active_formatting_elements->($insert_to_current);
# Line 3970  sub _tree_construction_main ($) { Line 4106  sub _tree_construction_main ($) {
4106                        
4107            $in_body->($insert_to_current);            $in_body->($insert_to_current);
4108            redo B;            redo B;
4109          } elsif ($self->{insertion_mode} eq 'in table') {          } elsif ($self->{insertion_mode} eq 'in row' or
4110                     $self->{insertion_mode} eq 'in table body' or
4111                     $self->{insertion_mode} eq 'in table') {
4112            if ($token->{type} eq 'character') {            if ($token->{type} eq 'character') {
4113              ## NOTE: There are "character in table" code clones.              ## NOTE: There are "character in table" code clones.
4114              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {
# Line 4031  sub _tree_construction_main ($) { Line 4169  sub _tree_construction_main ($) {
4169              redo B;              redo B;
4170            } elsif ($token->{type} eq 'start tag') {            } elsif ($token->{type} eq 'start tag') {
4171              if ({              if ({
4172                   caption => 1,                   tr => ($self->{insertion_mode} ne 'in row'),
4173                   colgroup => 1,                   th => 1, td => 1,
                  tbody => 1, tfoot => 1, thead => 1,  
4174                  }->{$token->{tag_name}}) {                  }->{$token->{tag_name}}) {
4175                ## Clear back to table context                if ($self->{insertion_mode} eq 'in table') {
4176                while ($self->{open_elements}->[-1]->[1] ne 'table' and                  ## Clear back to table context
4177                       $self->{open_elements}->[-1]->[1] ne 'html') {                  while ($self->{open_elements}->[-1]->[1] ne 'table' and
4178                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                         $self->{open_elements}->[-1]->[1] ne 'html') {
4179                  pop @{$self->{open_elements}};                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4180                      pop @{$self->{open_elements}};
4181                    }
4182                    
4183                    !!!insert-element ('tbody');
4184                    $self->{insertion_mode} = 'in table body';
4185                    ## reprocess in the "in table body" insertion mode...
4186                }                }
4187    
4188                push @$active_formatting_elements, ['#marker', '']                if ($self->{insertion_mode} eq 'in table body') {
4189                  if $token->{tag_name} eq 'caption';                  unless ($token->{tag_name} eq 'tr') {
4190                      !!!parse-error (type => 'missing start tag:tr');
4191                    }
4192                    
4193                    ## Clear back to table body context
4194                    while (not {
4195                      tbody => 1, tfoot => 1, thead => 1, html => 1,
4196                    }->{$self->{open_elements}->[-1]->[1]}) {
4197                      !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4198                      pop @{$self->{open_elements}};
4199                    }
4200                    
4201                    $self->{insertion_mode} = 'in row';
4202                    if ($token->{tag_name} eq 'tr') {
4203                      !!!insert-element ($token->{tag_name}, $token->{attributes});
4204                      !!!next-token;
4205                      redo B;
4206                    } else {
4207                      !!!insert-element ('tr');
4208                      ## reprocess in the "in row" insertion mode
4209                    }
4210                  }
4211    
4212                  ## Clear back to table row context
4213                  while (not {
4214                    tr => 1, html => 1,
4215                  }->{$self->{open_elements}->[-1]->[1]}) {
4216                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4217                    pop @{$self->{open_elements}};
4218                  }
4219                  
4220                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
4221                $self->{insertion_mode} = {                $self->{insertion_mode} = 'in cell';
4222                                   caption => 'in caption',  
4223                                   colgroup => 'in column group',                push @$active_formatting_elements, ['#marker', ''];
4224                                   tbody => 'in table body',                
                                  tfoot => 'in table body',  
                                  thead => 'in table body',  
                                 }->{$token->{tag_name}};  
4225                !!!next-token;                !!!next-token;
4226                redo B;                redo B;
4227              } elsif ({              } elsif ({
4228                        col => 1,                        caption => 1, col => 1, colgroup => 1,
4229                        td => 1, th => 1, tr => 1,                        tbody => 1, tfoot => 1, thead => 1,
4230                          tr => 1, # $self->{insertion_mode} eq 'in row'
4231                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
4232                ## Clear back to table context                if ($self->{insertion_mode} eq 'in row') {
4233                while ($self->{open_elements}->[-1]->[1] ne 'table' and                  ## As if </tr>
4234                       $self->{open_elements}->[-1]->[1] ne 'html') {                  ## have an element in table scope
4235                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                  my $i;
4236                    INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4237                      my $node = $self->{open_elements}->[$_];
4238                      if ($node->[1] eq 'tr') {
4239                        $i = $_;
4240                        last INSCOPE;
4241                      } elsif ({
4242                                table => 1, html => 1,
4243                               }->{$node->[1]}) {
4244                        last INSCOPE;
4245                      }
4246                    } # INSCOPE
4247                    unless (defined $i) {
4248                      !!!parse-error (type => 'unmacthed end tag:'.$token->{tag_name});
4249                      ## Ignore the token
4250                      !!!next-token;
4251                      redo B;
4252                    }
4253                    
4254                    ## Clear back to table row context
4255                    while (not {
4256                      tr => 1, html => 1,
4257                    }->{$self->{open_elements}->[-1]->[1]}) {
4258                      !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4259                      pop @{$self->{open_elements}};
4260                    }
4261                    
4262                    pop @{$self->{open_elements}}; # tr
4263                    $self->{insertion_mode} = 'in table body';
4264                    if ($token->{tag_name} eq 'tr') {
4265                      ## reprocess
4266                      redo B;
4267                    } else {
4268                      ## reprocess in the "in table body" insertion mode...
4269                    }
4270                  }
4271    
4272                  if ($self->{insertion_mode} eq 'in table body') {
4273                    ## have an element in table scope
4274                    my $i;
4275                    INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4276                      my $node = $self->{open_elements}->[$_];
4277                      if ({
4278                           tbody => 1, thead => 1, tfoot => 1,
4279                          }->{$node->[1]}) {
4280                        $i = $_;
4281                        last INSCOPE;
4282                      } elsif ({
4283                                table => 1, html => 1,
4284                               }->{$node->[1]}) {
4285                        last INSCOPE;
4286                      }
4287                    } # INSCOPE
4288                    unless (defined $i) {
4289                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4290                      ## Ignore the token
4291                      !!!next-token;
4292                      redo B;
4293                    }
4294    
4295                    ## Clear back to table body context
4296                    while (not {
4297                      tbody => 1, tfoot => 1, thead => 1, html => 1,
4298                    }->{$self->{open_elements}->[-1]->[1]}) {
4299                      !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4300                      pop @{$self->{open_elements}};
4301                    }
4302                    
4303                    ## As if <{current node}>
4304                    ## have an element in table scope
4305                    ## true by definition
4306                    
4307                    ## Clear back to table body context
4308                    ## nop by definition
4309                    
4310                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4311                    $self->{insertion_mode} = 'in table';
4312                    ## reprocess in "in table" insertion mode...
4313                }                }
4314    
4315                !!!insert-element ($token->{tag_name} eq 'col' ? 'colgroup' : 'tbody');                if ($token->{tag_name} eq 'col') {
4316                $self->{insertion_mode} = $token->{tag_name} eq 'col'                  ## Clear back to table context
4317                  ? 'in column group' : 'in table body';                  while ($self->{open_elements}->[-1]->[1] ne 'table' and
4318                ## reprocess                         $self->{open_elements}->[-1]->[1] ne 'html') {
4319                redo B;                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4320                      pop @{$self->{open_elements}};
4321                    }
4322                    
4323                    !!!insert-element ('colgroup');
4324                    $self->{insertion_mode} = 'in column group';
4325                    ## reprocess
4326                    redo B;
4327                  } elsif ({
4328                            caption => 1,
4329                            colgroup => 1,
4330                            tbody => 1, tfoot => 1, thead => 1,
4331                           }->{$token->{tag_name}}) {
4332                    ## Clear back to table context
4333                    while ($self->{open_elements}->[-1]->[1] ne 'table' and
4334                           $self->{open_elements}->[-1]->[1] ne 'html') {
4335                      !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4336                      pop @{$self->{open_elements}};
4337                    }
4338                    
4339                    push @$active_formatting_elements, ['#marker', '']
4340                        if $token->{tag_name} eq 'caption';
4341                    
4342                    !!!insert-element ($token->{tag_name}, $token->{attributes});
4343                    $self->{insertion_mode} = {
4344                                               caption => 'in caption',
4345                                               colgroup => 'in column group',
4346                                               tbody => 'in table body',
4347                                               tfoot => 'in table body',
4348                                               thead => 'in table body',
4349                                              }->{$token->{tag_name}};
4350                    !!!next-token;
4351                    redo B;
4352                  } else {
4353                    die "$0: in table: <>: $token->{tag_name}";
4354                  }
4355              } elsif ($token->{tag_name} eq 'table') {              } elsif ($token->{tag_name} eq 'table') {
4356                ## NOTE: There are code clones for this "table in table"                ## NOTE: There are code clones for this "table in table"
4357                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
# Line 4124  sub _tree_construction_main ($) { Line 4405  sub _tree_construction_main ($) {
4405                #                #
4406              }              }
4407            } elsif ($token->{type} eq 'end tag') {            } elsif ($token->{type} eq 'end tag') {
4408              if ($token->{tag_name} eq 'table') {              if ($token->{tag_name} eq 'tr' and
4409                ## have a table element in table scope                  $self->{insertion_mode} eq 'in row') {
4410                  ## have an element in table scope
4411                my $i;                my $i;
4412                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4413                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
# Line 4144  sub _tree_construction_main ($) { Line 4426  sub _tree_construction_main ($) {
4426                  !!!next-token;                  !!!next-token;
4427                  redo B;                  redo B;
4428                }                }
                 
               ## generate implied end tags  
               if ({  
                    dd => 1, dt => 1, li => 1, p => 1,  
                    td => 1, th => 1, tr => 1,  
                    tbody => 1, tfoot=> 1, thead => 1,  
                   }->{$self->{open_elements}->[-1]->[1]}) {  
                 !!!back-token;  
                 $token = {type => 'end tag',  
                           tag_name => $self->{open_elements}->[-1]->[1]}; # MUST  
                 redo B;  
               }  
4429    
4430                if ($self->{open_elements}->[-1]->[1] ne 'table') {                ## Clear back to table row context
4431                  while (not {
4432                    tr => 1, html => 1,
4433                  }->{$self->{open_elements}->[-1]->[1]}) {
4434                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4435                    pop @{$self->{open_elements}};
4436                }                }
4437    
4438                splice @{$self->{open_elements}}, $i;                pop @{$self->{open_elements}}; # tr
4439                  $self->{insertion_mode} = 'in table body';
               $self->_reset_insertion_mode;  
   
               !!!next-token;  
               redo B;  
             } elsif ({  
                       body => 1, caption => 1, col => 1, colgroup => 1,  
                       html => 1, tbody => 1, td => 1, tfoot => 1, th => 1,  
                       thead => 1, tr => 1,  
                      }->{$token->{tag_name}}) {  
               !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});  
               ## Ignore the token  
               !!!next-token;  
               redo B;  
             } else {  
               #  
             }  
           } else {  
             #  
           }  
   
           !!!parse-error (type => 'in table:'.$token->{tag_name});  
           $in_body->($insert_to_foster);  
           redo B;  
         } elsif ($self->{insertion_mode} eq 'in column group') {  
           if ($token->{type} eq 'character') {  
             if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {  
               $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);  
               unless (length $token->{data}) {  
                 !!!next-token;  
                 redo B;  
               }  
             }  
               
             #  
           } elsif ($token->{type} eq 'start tag') {  
             if ($token->{tag_name} eq 'col') {  
               !!!insert-element ($token->{tag_name}, $token->{attributes});  
               pop @{$self->{open_elements}};  
               !!!next-token;  
               redo B;  
             } else {  
               #  
             }  
           } elsif ($token->{type} eq 'end tag') {  
             if ($token->{tag_name} eq 'colgroup') {  
               if ($self->{open_elements}->[-1]->[1] eq 'html') {  
                 !!!parse-error (type => 'unmatched end tag:colgroup');  
                 ## Ignore the token  
                 !!!next-token;  
                 redo B;  
               } else {  
                 pop @{$self->{open_elements}}; # colgroup  
                 $self->{insertion_mode} = 'in table';  
                 !!!next-token;  
                 redo B;              
               }  
             } elsif ($token->{tag_name} eq 'col') {  
               !!!parse-error (type => 'unmatched end tag:col');  
               ## Ignore the token  
4440                !!!next-token;                !!!next-token;
4441                redo B;                redo B;
4442              } else {              } elsif ($token->{tag_name} eq 'table') {
4443                #                if ($self->{insertion_mode} eq 'in row') {
4444              }                  ## As if </tr>
4445            } else {                  ## have an element in table scope
4446              #                  my $i;
4447            }                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4448                      my $node = $self->{open_elements}->[$_];
4449            ## As if </colgroup>                    if ($node->[1] eq 'tr') {
4450            if ($self->{open_elements}->[-1]->[1] eq 'html') {                      $i = $_;
4451              !!!parse-error (type => 'unmatched end tag:colgroup');                      last INSCOPE;
4452              ## Ignore the token                    } elsif ({
4453              !!!next-token;                              table => 1, html => 1,
4454              redo B;                             }->{$node->[1]}) {
4455            } else {                      last INSCOPE;
             pop @{$self->{open_elements}}; # colgroup  
             $self->{insertion_mode} = 'in table';  
             ## reprocess  
             redo B;  
           }  
         } elsif ($self->{insertion_mode} eq 'in table body') {  
           if ($token->{type} eq 'character') {  
             ## NOTE: This is a "character in table" code clone.  
             if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {  
               $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);  
                 
               unless (length $token->{data}) {  
                 !!!next-token;  
                 redo B;  
               }  
             }  
   
             !!!parse-error (type => 'in table:#character');  
   
             ## As if in body, but insert into foster parent element  
             ## ISSUE: Spec says that "whenever a node would be inserted  
             ## into the current node" while characters might not be  
             ## result in a new Text node.  
             $reconstruct_active_formatting_elements->($insert_to_foster);  
   
             if ({  
                  table => 1, tbody => 1, tfoot => 1,  
                  thead => 1, tr => 1,  
                 }->{$self->{open_elements}->[-1]->[1]}) {  
               # MUST  
               my $foster_parent_element;  
               my $next_sibling;  
               my $prev_sibling;  
               OE: for (reverse 0..$#{$self->{open_elements}}) {  
                 if ($self->{open_elements}->[$_]->[1] eq 'table') {  
                   my $parent = $self->{open_elements}->[$_]->[0]->parent_node;  
                   if (defined $parent and $parent->node_type == 1) {  
                     $foster_parent_element = $parent;  
                     $next_sibling = $self->{open_elements}->[$_]->[0];  
                     $prev_sibling = $next_sibling->previous_sibling;  
                   } else {  
                     $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];  
                     $prev_sibling = $foster_parent_element->last_child;  
4456                    }                    }
4457                    last OE;                  } # INSCOPE
4458                    unless (defined $i) {
4459                      !!!parse-error (type => 'unmatched end tag:'.$token->{type});
4460                      ## Ignore the token
4461                      !!!next-token;
4462                      redo B;
4463                  }                  }
4464                } # OE                  
4465                $foster_parent_element = $self->{open_elements}->[0]->[0] and                  ## Clear back to table row context
4466                $prev_sibling = $foster_parent_element->last_child                  while (not {
4467                  unless defined $foster_parent_element;                    tr => 1, html => 1,
4468                if (defined $prev_sibling and                  }->{$self->{open_elements}->[-1]->[1]}) {
4469                    $prev_sibling->node_type == 3) {                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4470                  $prev_sibling->manakai_append_text ($token->{data});                    pop @{$self->{open_elements}};
               } else {  
                 $foster_parent_element->insert_before  
                   ($self->{document}->create_text_node ($token->{data}),  
                    $next_sibling);  
               }  
             } else {  
               $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});  
             }  
               
             !!!next-token;  
             redo B;  
           } elsif ($token->{type} eq 'start tag') {  
             if ({  
                  tr => 1,  
                  th => 1, td => 1,  
                 }->{$token->{tag_name}}) {  
               unless ($token->{tag_name} eq 'tr') {  
                 !!!parse-error (type => 'missing start tag:tr');  
               }  
   
               ## Clear back to table body context  
               while (not {  
                 tbody => 1, tfoot => 1, thead => 1, html => 1,  
               }->{$self->{open_elements}->[-1]->[1]}) {  
                 !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);  
                 pop @{$self->{open_elements}};  
               }  
                 
               $self->{insertion_mode} = 'in row';  
               if ($token->{tag_name} eq 'tr') {  
                 !!!insert-element ($token->{tag_name}, $token->{attributes});  
                 !!!next-token;  
               } else {  
                 !!!insert-element ('tr');  
                 ## reprocess  
               }  
               redo B;  
             } elsif ({  
                       caption => 1, col => 1, colgroup => 1,  
                       tbody => 1, tfoot => 1, thead => 1,  
                      }->{$token->{tag_name}}) {  
               ## have an element in table scope  
               my $i;  
               INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {  
                 my $node = $self->{open_elements}->[$_];  
                 if ({  
                      tbody => 1, thead => 1, tfoot => 1,  
                     }->{$node->[1]}) {  
                   $i = $_;  
                   last INSCOPE;  
                 } elsif ({  
                           table => 1, html => 1,  
                          }->{$node->[1]}) {  
                   last INSCOPE;  
4471                  }                  }
4472                } # INSCOPE                  
4473                unless (defined $i) {                  pop @{$self->{open_elements}}; # tr
4474                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  $self->{insertion_mode} = 'in table body';
4475                  ## Ignore the token                  ## reprocess in the "in table body" insertion mode...
                 !!!next-token;  
                 redo B;  
4476                }                }
4477    
4478                ## Clear back to table body context                if ($self->{insertion_mode} eq 'in table body') {
4479                while (not {                  ## have an element in table scope
4480                  tbody => 1, tfoot => 1, thead => 1, html => 1,                  my $i;
4481                }->{$self->{open_elements}->[-1]->[1]}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4482                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    my $node = $self->{open_elements}->[$_];
4483                      if ({
4484                           tbody => 1, thead => 1, tfoot => 1,
4485                          }->{$node->[1]}) {
4486                        $i = $_;
4487                        last INSCOPE;
4488                      } elsif ({
4489                                table => 1, html => 1,
4490                               }->{$node->[1]}) {
4491                        last INSCOPE;
4492                      }
4493                    } # INSCOPE
4494                    unless (defined $i) {
4495                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4496                      ## Ignore the token
4497                      !!!next-token;
4498                      redo B;
4499                    }
4500                    
4501                    ## Clear back to table body context
4502                    while (not {
4503                      tbody => 1, tfoot => 1, thead => 1, html => 1,
4504                    }->{$self->{open_elements}->[-1]->[1]}) {
4505                      !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4506                      pop @{$self->{open_elements}};
4507                    }
4508                    
4509                    ## As if <{current node}>
4510                    ## have an element in table scope
4511                    ## true by definition
4512                    
4513                    ## Clear back to table body context
4514                    ## nop by definition
4515                    
4516                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4517                    $self->{insertion_mode} = 'in table';
4518                    ## reprocess in the "in table" insertion mode...
4519                }                }
4520    
               ## As if <{current node}>  
               ## have an element in table scope  
               ## true by definition  
   
               ## Clear back to table body context  
               ## nop by definition  
   
               pop @{$self->{open_elements}};  
               $self->{insertion_mode} = 'in table';  
               ## reprocess  
               redo B;  
             } elsif ($token->{tag_name} eq 'table') {  
               ## NOTE: This is a code clone of "table in table"  
               !!!parse-error (type => 'not closed:table');  
   
               ## As if </table>  
4521                ## have a table element in table scope                ## have a table element in table scope
4522                my $i;                my $i;
4523                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4524                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4525                  if ($node->[1] eq 'table') {                  if ($node->[1] eq $token->{tag_name}) {
4526                    $i = $_;                    $i = $_;
4527                    last INSCOPE;                    last INSCOPE;
4528                  } elsif ({                  } elsif ({
# Line 4392  sub _tree_construction_main ($) { Line 4532  sub _tree_construction_main ($) {
4532                  }                  }
4533                } # INSCOPE                } # INSCOPE
4534                unless (defined $i) {                unless (defined $i) {
4535                  !!!parse-error (type => 'unmatched end tag:table');                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4536                  ## Ignore tokens </table><table>                  ## Ignore the token
4537                  !!!next-token;                  !!!next-token;
4538                  redo B;                  redo B;
4539                }                }
4540                  
4541                ## generate implied end tags                ## generate implied end tags
4542                if ({                if ({
4543                     dd => 1, dt => 1, li => 1, p => 1,                     dd => 1, dt => 1, li => 1, p => 1,
4544                     td => 1, th => 1, tr => 1,                     td => 1, th => 1, tr => 1,
4545                     tbody => 1, tfoot=> 1, thead => 1,                     tbody => 1, tfoot=> 1, thead => 1,
4546                    }->{$self->{open_elements}->[-1]->[1]}) {                    }->{$self->{open_elements}->[-1]->[1]}) {
                 !!!back-token; # <table>  
                 $token = {type => 'end tag', tag_name => 'table'};  
4547                  !!!back-token;                  !!!back-token;
4548                  $token = {type => 'end tag',                  $token = {type => 'end tag',
4549                            tag_name => $self->{open_elements}->[-1]->[1]}; # MUST                            tag_name => $self->{open_elements}->[-1]->[1]}; # MUST
4550                  redo B;                  redo B;
4551                }                }
4552                  
4553                if ($self->{open_elements}->[-1]->[1] ne 'table') {                if ($self->{open_elements}->[-1]->[1] ne 'table') {
4554                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4555                }                }
4556                    
4557                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
4558                  
4559                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
4560                  
4561                ## reprocess                !!!next-token;
4562                redo B;                redo B;
4563              } else {              } elsif ({
4564                #                        tbody => 1, tfoot => 1, thead => 1,
4565              }                       }->{$token->{tag_name}} and
4566            } elsif ($token->{type} eq 'end tag') {                       ($self->{insertion_mode} eq 'in row' or
4567              if ({                        $self->{insertion_mode} eq 'in table body')) {
4568                   tbody => 1, tfoot => 1, thead => 1,                if ($self->{insertion_mode} eq 'in row') {
4569                  }->{$token->{tag_name}}) {                  ## have an element in table scope
4570                ## have an element in table scope                  my $i;
4571                my $i;                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4572                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                    my $node = $self->{open_elements}->[$_];
4573                  my $node = $self->{open_elements}->[$_];                    if ($node->[1] eq $token->{tag_name}) {
4574                  if ($node->[1] eq $token->{tag_name}) {                      $i = $_;
4575                    $i = $_;                      last INSCOPE;
4576                    last INSCOPE;                    } elsif ({
4577                  } elsif ({                              table => 1, html => 1,
4578                            table => 1, html => 1,                             }->{$node->[1]}) {
4579                           }->{$node->[1]}) {                      last INSCOPE;
4580                    last INSCOPE;                    }
4581                    } # INSCOPE
4582                      unless (defined $i) {
4583                        !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4584                        ## Ignore the token
4585                        !!!next-token;
4586                        redo B;
4587                      }
4588                    
4589                    ## As if </tr>
4590                    ## have an element in table scope
4591                    my $i;
4592                    INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4593                      my $node = $self->{open_elements}->[$_];
4594                      if ($node->[1] eq 'tr') {
4595                        $i = $_;
4596                        last INSCOPE;
4597                      } elsif ({
4598                                table => 1, html => 1,
4599                               }->{$node->[1]}) {
4600                        last INSCOPE;
4601                      }
4602                    } # INSCOPE
4603                      unless (defined $i) {
4604                        !!!parse-error (type => 'unmatched end tag:tr');
4605                        ## Ignore the token
4606                        !!!next-token;
4607                        redo B;
4608                      }
4609                    
4610                    ## Clear back to table row context
4611                    while (not {
4612                      tr => 1, html => 1,
4613                    }->{$self->{open_elements}->[-1]->[1]}) {
4614                      !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4615                      pop @{$self->{open_elements}};
4616                  }                  }
4617                } # INSCOPE                  
4618                unless (defined $i) {                  pop @{$self->{open_elements}}; # tr
4619                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  $self->{insertion_mode} = 'in table body';
4620                  ## Ignore the token                  ## reprocess in the "in table body" insertion mode...
                 !!!next-token;  
                 redo B;  
               }  
   
               ## Clear back to table body context  
               while (not {  
                 tbody => 1, tfoot => 1, thead => 1, html => 1,  
               }->{$self->{open_elements}->[-1]->[1]}) {  
                 !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);  
                 pop @{$self->{open_elements}};  
4621                }                }
4622    
               pop @{$self->{open_elements}};  
               $self->{insertion_mode} = 'in table';  
               !!!next-token;  
               redo B;  
             } elsif ($token->{tag_name} eq 'table') {  
4623                ## have an element in table scope                ## have an element in table scope
4624                my $i;                my $i;
4625                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4626                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4627                  if ({                  if ($node->[1] eq $token->{tag_name}) {
                      tbody => 1, thead => 1, tfoot => 1,  
                     }->{$node->[1]}) {  
4628                    $i = $_;                    $i = $_;
4629                    last INSCOPE;                    last INSCOPE;
4630                  } elsif ({                  } elsif ({
# Line 4492  sub _tree_construction_main ($) { Line 4648  sub _tree_construction_main ($) {
4648                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4649                }                }
4650    
               ## As if <{current node}>  
               ## have an element in table scope  
               ## true by definition  
   
               ## Clear back to table body context  
               ## nop by definition  
   
4651                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
4652                $self->{insertion_mode} = 'in table';                $self->{insertion_mode} = 'in table';
4653                ## reprocess                !!!next-token;
4654                redo B;                redo B;
4655              } elsif ({              } elsif ({
4656                        body => 1, caption => 1, col => 1, colgroup => 1,                        body => 1, caption => 1, col => 1, colgroup => 1,
4657                        html => 1, td => 1, th => 1, tr => 1,                        html => 1, td => 1, th => 1,
4658                          tr => 1, # $self->{insertion_mode} eq 'in row'
4659                          tbody => 1, tfoot => 1, thead => 1, # $self->{insertion_mode} eq 'in table'
4660                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
4661                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4662                ## Ignore the token                ## Ignore the token
# Line 4515  sub _tree_construction_main ($) { Line 4666  sub _tree_construction_main ($) {
4666                #                #
4667              }              }
4668            } else {            } else {
4669              #              die "$0: $token->{type}: Unknown token type";
4670            }            }
4671              
           ## As if in table  
4672            !!!parse-error (type => 'in table:'.$token->{tag_name});            !!!parse-error (type => 'in table:'.$token->{tag_name});
4673            $in_body->($insert_to_foster);            $in_body->($insert_to_foster);
4674            redo B;            redo B;
4675          } elsif ($self->{insertion_mode} eq 'in row') {          } elsif ($self->{insertion_mode} eq 'in column group') {
4676            if ($token->{type} eq 'character') {            if ($token->{type} eq 'character') {
             ## NOTE: This is a "character in table" code clone.  
4677              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {
4678                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
                 
4679                unless (length $token->{data}) {                unless (length $token->{data}) {
4680                  !!!next-token;                  !!!next-token;
4681                  redo B;                  redo B;
4682                }                }
4683              }              }
   
             !!!parse-error (type => 'in table:#character');  
   
             ## As if in body, but insert into foster parent element  
             ## ISSUE: Spec says that "whenever a node would be inserted  
             ## into the current node" while characters might not be  
             ## result in a new Text node.  
             $reconstruct_active_formatting_elements->($insert_to_foster);  
               
             if ({  
                  table => 1, tbody => 1, tfoot => 1,  
                  thead => 1, tr => 1,  
                 }->{$self->{open_elements}->[-1]->[1]}) {  
               # MUST  
               my $foster_parent_element;  
               my $next_sibling;  
               my $prev_sibling;  
               OE: for (reverse 0..$#{$self->{open_elements}}) {  
                 if ($self->{open_elements}->[$_]->[1] eq 'table') {  
                   my $parent = $self->{open_elements}->[$_]->[0]->parent_node;  
                   if (defined $parent and $parent->node_type == 1) {  
                     $foster_parent_element = $parent;  
                     $next_sibling = $self->{open_elements}->[$_]->[0];  
                     $prev_sibling = $next_sibling->previous_sibling;  
                   } else {  
                     $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];  
                     $prev_sibling = $foster_parent_element->last_child;  
                   }  
                   last OE;  
                 }  
               } # OE  
               $foster_parent_element = $self->{open_elements}->[0]->[0] and  
               $prev_sibling = $foster_parent_element->last_child  
                 unless defined $foster_parent_element;  
               if (defined $prev_sibling and  
                   $prev_sibling->node_type == 3) {  
                 $prev_sibling->manakai_append_text ($token->{data});  
               } else {  
                 $foster_parent_element->insert_before  
                   ($self->{document}->create_text_node ($token->{data}),  
                    $next_sibling);  
               }  
             } else {  
               $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});  
             }  
4684                            
4685              !!!next-token;              #
             redo B;  
4686            } elsif ($token->{type} eq 'start tag') {            } elsif ($token->{type} eq 'start tag') {
4687              if ($token->{tag_name} eq 'th' or              if ($token->{tag_name} eq 'col') {
                 $token->{tag_name} eq 'td') {  
               ## Clear back to table row context  
               while (not {  
                 tr => 1, html => 1,  
               }->{$self->{open_elements}->[-1]->[1]}) {  
                 !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);  
                 pop @{$self->{open_elements}};  
               }  
                 
4688                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
4689                $self->{insertion_mode} = 'in cell';                pop @{$self->{open_elements}};
   
               push @$active_formatting_elements, ['#marker', ''];  
                 
4690                !!!next-token;                !!!next-token;
4691                redo B;                redo B;
4692              } elsif ({              } else {
                       caption => 1, col => 1, colgroup => 1,  
                       tbody => 1, tfoot => 1, thead => 1, tr => 1,  
                      }->{$token->{tag_name}}) {  
               ## As if </tr>  
               ## have an element in table scope  
               my $i;  
               INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {  
                 my $node = $self->{open_elements}->[$_];  
                 if ($node->[1] eq 'tr') {  
                   $i = $_;  
                   last INSCOPE;  
                 } elsif ({  
                           table => 1, html => 1,  
                          }->{$node->[1]}) {  
                   last INSCOPE;  
                 }  
               } # INSCOPE  
               unless (defined $i) {  
                 !!!parse-error (type => 'unmacthed end tag:'.$token->{tag_name});  
                 ## Ignore the token  
                 !!!next-token;  
                 redo B;  
               }  
   
               ## Clear back to table row context  
               while (not {  
                 tr => 1, html => 1,  
               }->{$self->{open_elements}->[-1]->[1]}) {  
                 !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);  
                 pop @{$self->{open_elements}};  
               }  
   
               pop @{$self->{open_elements}}; # tr  
               $self->{insertion_mode} = 'in table body';  
               ## reprocess  
               redo B;  
             } elsif ($token->{tag_name} eq 'table') {  
               ## NOTE: This is a code clone of "table in table"  
               !!!parse-error (type => 'not closed:table');  
   
               ## As if </table>  
               ## have a table element in table scope  
               my $i;  
               INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {  
                 my $node = $self->{open_elements}->[$_];  
                 if ($node->[1] eq 'table') {  
                   $i = $_;  
                   last INSCOPE;  
                 } elsif ({  
                           table => 1, html => 1,  
                          }->{$node->[1]}) {  
                   last INSCOPE;  
                 }  
               } # INSCOPE  
               unless (defined $i) {  
                 !!!parse-error (type => 'unmatched end tag:table');  
                 ## Ignore tokens </table><table>  
                 !!!next-token;  
                 redo B;  
               }  
                 
               ## generate implied end tags  
               if ({  
                    dd => 1, dt => 1, li => 1, p => 1,  
                    td => 1, th => 1, tr => 1,  
                    tbody => 1, tfoot=> 1, thead => 1,  
                   }->{$self->{open_elements}->[-1]->[1]}) {  
                 !!!back-token; # <table>  
                 $token = {type => 'end tag', tag_name => 'table'};  
                 !!!back-token;  
                 $token = {type => 'end tag',  
                           tag_name => $self->{open_elements}->[-1]->[1]}; # MUST  
                 redo B;  
               }  
   
               if ($self->{open_elements}->[-1]->[1] ne 'table') {  
                 !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);  
               }  
   
               splice @{$self->{open_elements}}, $i;  
   
               $self->_reset_insertion_mode;  
   
               ## reprocess  
               redo B;  
             } else {  
4693                #                #
4694              }              }
4695            } elsif ($token->{type} eq 'end tag') {            } elsif ($token->{type} eq 'end tag') {
4696              if ($token->{tag_name} eq 'tr') {              if ($token->{tag_name} eq 'colgroup') {
4697                ## have an element in table scope                if ($self->{open_elements}->[-1]->[1] eq 'html') {
4698                my $i;                  !!!parse-error (type => 'unmatched end tag:colgroup');
               INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {  
                 my $node = $self->{open_elements}->[$_];  
                 if ($node->[1] eq $token->{tag_name}) {  
                   $i = $_;  
                   last INSCOPE;  
                 } elsif ({  
                           table => 1, html => 1,  
                          }->{$node->[1]}) {  
                   last INSCOPE;  
                 }  
               } # INSCOPE  
               unless (defined $i) {  
                 !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});  
                 ## Ignore the token  
                 !!!next-token;  
                 redo B;  
               }  
   
               ## Clear back to table row context  
               while (not {  
                 tr => 1, html => 1,  
               }->{$self->{open_elements}->[-1]->[1]}) {  
                 !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);  
                 pop @{$self->{open_elements}};  
               }  
   
               pop @{$self->{open_elements}}; # tr  
               $self->{insertion_mode} = 'in table body';  
               !!!next-token;  
               redo B;  
             } elsif ($token->{tag_name} eq 'table') {  
               ## As if </tr>  
               ## have an element in table scope  
               my $i;  
               INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {  
                 my $node = $self->{open_elements}->[$_];  
                 if ($node->[1] eq 'tr') {  
                   $i = $_;  
                   last INSCOPE;  
                 } elsif ({  
                           table => 1, html => 1,  
                          }->{$node->[1]}) {  
                   last INSCOPE;  
                 }  
               } # INSCOPE  
               unless (defined $i) {  
                 !!!parse-error (type => 'unmatched end tag:'.$token->{type});  
                 ## Ignore the token  
                 !!!next-token;  
                 redo B;  
               }  
   
               ## Clear back to table row context  
               while (not {  
                 tr => 1, html => 1,  
               }->{$self->{open_elements}->[-1]->[1]}) {  
                 !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);  
                 pop @{$self->{open_elements}};  
               }  
   
               pop @{$self->{open_elements}}; # tr  
               $self->{insertion_mode} = 'in table body';  
               ## reprocess  
               redo B;  
             } elsif ({  
                       tbody => 1, tfoot => 1, thead => 1,  
                      }->{$token->{tag_name}}) {  
               ## have an element in table scope  
               my $i;  
               INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {  
                 my $node = $self->{open_elements}->[$_];  
                 if ($node->[1] eq $token->{tag_name}) {  
                   $i = $_;  
                   last INSCOPE;  
                 } elsif ({  
                           table => 1, html => 1,  
                          }->{$node->[1]}) {  
                   last INSCOPE;  
                 }  
               } # INSCOPE  
               unless (defined $i) {  
                 !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});  
4699                  ## Ignore the token                  ## Ignore the token
4700                  !!!next-token;                  !!!next-token;
4701                  redo B;                  redo B;
4702                }                } else {
4703                    pop @{$self->{open_elements}}; # colgroup
4704                ## As if </tr>                  $self->{insertion_mode} = 'in table';
               ## have an element in table scope  
               my $i;  
               INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {  
                 my $node = $self->{open_elements}->[$_];  
                 if ($node->[1] eq 'tr') {  
                   $i = $_;  
                   last INSCOPE;  
                 } elsif ({  
                           table => 1, html => 1,  
                          }->{$node->[1]}) {  
                   last INSCOPE;  
                 }  
               } # INSCOPE  
               unless (defined $i) {  
                 !!!parse-error (type => 'unmatched end tag:tr');  
                 ## Ignore the token  
4705                  !!!next-token;                  !!!next-token;
4706                  redo B;                  redo B;            
               }  
   
               ## Clear back to table row context  
               while (not {  
                 tr => 1, html => 1,  
               }->{$self->{open_elements}->[-1]->[1]}) {  
                 !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);  
                 pop @{$self->{open_elements}};  
4707                }                }
4708                } elsif ($token->{tag_name} eq 'col') {
4709                pop @{$self->{open_elements}}; # tr                !!!parse-error (type => 'unmatched end tag:col');
               $self->{insertion_mode} = 'in table body';  
               ## reprocess  
               redo B;  
             } elsif ({  
                       body => 1, caption => 1, col => 1,  
                       colgroup => 1, html => 1, td => 1, th => 1,  
                      }->{$token->{tag_name}}) {  
               !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});  
4710                ## Ignore the token                ## Ignore the token
4711                !!!next-token;                !!!next-token;
4712                redo B;                redo B;
4713              } else {              } else {
4714                #                #
4715              }              }
4716            } else {            } else {
4717              #              #
4718            }            }
4719    
4720            ## As if in table            ## As if </colgroup>
4721            !!!parse-error (type => 'in table:'.$token->{tag_name});            if ($self->{open_elements}->[-1]->[1] eq 'html') {
4722            $in_body->($insert_to_foster);              !!!parse-error (type => 'unmatched end tag:colgroup');
4723            redo B;              ## Ignore the token
4724                !!!next-token;
4725                redo B;
4726              } else {
4727                pop @{$self->{open_elements}}; # colgroup
4728                $self->{insertion_mode} = 'in table';
4729                ## reprocess
4730                redo B;
4731              }
4732          } elsif ($self->{insertion_mode} eq 'in select') {          } elsif ($self->{insertion_mode} eq 'in select') {
4733            if ($token->{type} eq 'character') {            if ($token->{type} eq 'character') {
4734              $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});              $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});

Legend:
Removed from v.1.44  
changed lines
  Added in v.1.50

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24