/[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.145 by wakaba, Sat May 24 11:57:47 2008 UTC revision 1.163 by wakaba, Sat Sep 13 04:19:56 2008 UTC
# Line 45  sub MISC_SPECIAL_EL () { 0b1000000000000 Line 45  sub MISC_SPECIAL_EL () { 0b1000000000000
45  sub FOREIGN_EL () { 0b10000000000000000000000000 }  sub FOREIGN_EL () { 0b10000000000000000000000000 }
46  sub FOREIGN_FLOW_CONTENT_EL () { 0b100000000000000000000000000 }  sub FOREIGN_FLOW_CONTENT_EL () { 0b100000000000000000000000000 }
47  sub MML_AXML_EL () { 0b1000000000000000000000000000 }  sub MML_AXML_EL () { 0b1000000000000000000000000000 }
48    sub RUBY_EL () { 0b10000000000000000000000000000 }
49    sub RUBY_COMPONENT_EL () { 0b100000000000000000000000000000 }
50    
51  sub TABLE_ROWS_EL () {  sub TABLE_ROWS_EL () {
52    TABLE_EL |    TABLE_EL |
# Line 52  sub TABLE_ROWS_EL () { Line 54  sub TABLE_ROWS_EL () {
54    TABLE_ROW_GROUP_EL    TABLE_ROW_GROUP_EL
55  }  }
56    
57    ## NOTE: Used in "generate implied end tags" algorithm.
58    ## NOTE: There is a code where a modified version of END_TAG_OPTIONAL_EL
59    ## is used in "generate implied end tags" implementation (search for the
60    ## function mae).
61  sub END_TAG_OPTIONAL_EL () {  sub END_TAG_OPTIONAL_EL () {
62    DD_EL |    DD_EL |
63    DT_EL |    DT_EL |
64    LI_EL |    LI_EL |
65    P_EL    P_EL |
66      RUBY_COMPONENT_EL
67  }  }
68    
69    ## NOTE: Used in </body> and EOF algorithms.
70  sub ALL_END_TAG_OPTIONAL_EL () {  sub ALL_END_TAG_OPTIONAL_EL () {
71    END_TAG_OPTIONAL_EL |    DD_EL |
72      DT_EL |
73      LI_EL |
74      P_EL |
75    
76    BODY_EL |    BODY_EL |
77    HTML_EL |    HTML_EL |
78    TABLE_CELL_EL |    TABLE_CELL_EL |
# Line 96  sub SPECIAL_EL () { Line 108  sub SPECIAL_EL () {
108    ADDRESS_EL |    ADDRESS_EL |
109    BODY_EL |    BODY_EL |
110    DIV_EL |    DIV_EL |
111    END_TAG_OPTIONAL_EL |  
112      DD_EL |
113      DT_EL |
114      LI_EL |
115      P_EL |
116    
117    FORM_EL |    FORM_EL |
118    FRAMESET_EL |    FRAMESET_EL |
119    HEADING_EL |    HEADING_EL |
# Line 170  my $el_category = { Line 187  my $el_category = {
187    param => MISC_SPECIAL_EL,    param => MISC_SPECIAL_EL,
188    plaintext => MISC_SPECIAL_EL,    plaintext => MISC_SPECIAL_EL,
189    pre => MISC_SPECIAL_EL,    pre => MISC_SPECIAL_EL,
190      rp => RUBY_COMPONENT_EL,
191      rt => RUBY_COMPONENT_EL,
192      ruby => RUBY_EL,
193    s => FORMATTING_EL,    s => FORMATTING_EL,
194    script => MISC_SPECIAL_EL,    script => MISC_SPECIAL_EL,
195    select => SELECT_EL,    select => SELECT_EL,
# Line 211  my $el_category_f = { Line 231  my $el_category_f = {
231  };  };
232    
233  my $svg_attr_name = {  my $svg_attr_name = {
234      attributename => 'attributeName',
235    attributetype => 'attributeType',    attributetype => 'attributeType',
236    basefrequency => 'baseFrequency',    basefrequency => 'baseFrequency',
237    baseprofile => 'baseProfile',    baseprofile => 'baseProfile',
# Line 221  my $svg_attr_name = { Line 242  my $svg_attr_name = {
242    diffuseconstant => 'diffuseConstant',    diffuseconstant => 'diffuseConstant',
243    edgemode => 'edgeMode',    edgemode => 'edgeMode',
244    externalresourcesrequired => 'externalResourcesRequired',    externalresourcesrequired => 'externalResourcesRequired',
   fecolormatrix => 'feColorMatrix',  
   fecomposite => 'feComposite',  
   fegaussianblur => 'feGaussianBlur',  
   femorphology => 'feMorphology',  
   fetile => 'feTile',  
245    filterres => 'filterRes',    filterres => 'filterRes',
246    filterunits => 'filterUnits',    filterunits => 'filterUnits',
247    glyphref => 'glyphRef',    glyphref => 'glyphRef',
# Line 259  my $svg_attr_name = { Line 275  my $svg_attr_name = {
275    repeatcount => 'repeatCount',    repeatcount => 'repeatCount',
276    repeatdur => 'repeatDur',    repeatdur => 'repeatDur',
277    requiredextensions => 'requiredExtensions',    requiredextensions => 'requiredExtensions',
278      requiredfeatures => 'requiredFeatures',
279    specularconstant => 'specularConstant',    specularconstant => 'specularConstant',
280    specularexponent => 'specularExponent',    specularexponent => 'specularExponent',
281    spreadmethod => 'spreadMethod',    spreadmethod => 'spreadMethod',
# Line 337  sub parse_byte_string ($$$$;$) { Line 354  sub parse_byte_string ($$$$;$) {
354    return $self->parse_byte_stream ($charset_name, $input, @_[1..$#_]);    return $self->parse_byte_stream ($charset_name, $input, @_[1..$#_]);
355  } # parse_byte_string  } # parse_byte_string
356    
357  sub parse_byte_stream ($$$$;$) {  sub parse_byte_stream ($$$$;$$) {
358      # my ($self, $charset_name, $byte_stream, $doc, $onerror, $get_wrapper) = @_;
359    my $self = ref $_[0] ? shift : shift->new;    my $self = ref $_[0] ? shift : shift->new;
360    my $charset_name = shift;    my $charset_name = shift;
361    my $byte_stream = $_[0];    my $byte_stream = $_[0];
# Line 348  sub parse_byte_stream ($$$$;$) { Line 366  sub parse_byte_stream ($$$$;$) {
366    };    };
367    $self->{parse_error} = $onerror; # updated later by parse_char_string    $self->{parse_error} = $onerror; # updated later by parse_char_string
368    
369      my $get_wrapper = $_[3] || sub ($) {
370        return $_[0]; # $_[0] = byte stream handle, returned = arg to char handle
371      };
372    
373    ## HTML5 encoding sniffing algorithm    ## HTML5 encoding sniffing algorithm
374    require Message::Charset::Info;    require Message::Charset::Info;
375    my $charset;    my $charset;
# Line 355  sub parse_byte_stream ($$$$;$) { Line 377  sub parse_byte_stream ($$$$;$) {
377    my ($char_stream, $e_status);    my ($char_stream, $e_status);
378    
379    SNIFFING: {    SNIFFING: {
380        ## NOTE: By setting |allow_fallback| option true when the
381        ## |get_decode_handle| method is invoked, we ignore what the HTML5
382        ## spec requires, i.e. unsupported encoding should be ignored.
383          ## TODO: We should not do this unless the parser is invoked
384          ## in the conformance checking mode, in which this behavior
385          ## would be useful.
386    
387      ## Step 1      ## Step 1
388      if (defined $charset_name) {      if (defined $charset_name) {
389        $charset = Message::Charset::Info->get_by_iana_name ($charset_name);        $charset = Message::Charset::Info->get_by_html_name ($charset_name);
390              ## TODO: Is this ok?  Transfer protocol's parameter should be
391              ## interpreted in its semantics?
392    
393        ## ISSUE: Unsupported encoding is not ignored according to the spec.        ## ISSUE: Unsupported encoding is not ignored according to the spec.
394        ($char_stream, $e_status) = $charset->get_decode_handle        ($char_stream, $e_status) = $charset->get_decode_handle
# Line 382  sub parse_byte_stream ($$$$;$) { Line 412  sub parse_byte_stream ($$$$;$) {
412    
413      ## Step 3      ## Step 3
414      if ($byte_buffer =~ /^\xFE\xFF/) {      if ($byte_buffer =~ /^\xFE\xFF/) {
415        $charset = Message::Charset::Info->get_by_iana_name ('utf-16be');        $charset = Message::Charset::Info->get_by_html_name ('utf-16be');
416        ($char_stream, $e_status) = $charset->get_decode_handle        ($char_stream, $e_status) = $charset->get_decode_handle
417            ($byte_stream, allow_error_reporting => 1,            ($byte_stream, allow_error_reporting => 1,
418             allow_fallback => 1, byte_buffer => \$byte_buffer);             allow_fallback => 1, byte_buffer => \$byte_buffer);
419        $self->{confident} = 1;        $self->{confident} = 1;
420        last SNIFFING;        last SNIFFING;
421      } elsif ($byte_buffer =~ /^\xFF\xFE/) {      } elsif ($byte_buffer =~ /^\xFF\xFE/) {
422        $charset = Message::Charset::Info->get_by_iana_name ('utf-16le');        $charset = Message::Charset::Info->get_by_html_name ('utf-16le');
423        ($char_stream, $e_status) = $charset->get_decode_handle        ($char_stream, $e_status) = $charset->get_decode_handle
424            ($byte_stream, allow_error_reporting => 1,            ($byte_stream, allow_error_reporting => 1,
425             allow_fallback => 1, byte_buffer => \$byte_buffer);             allow_fallback => 1, byte_buffer => \$byte_buffer);
426        $self->{confident} = 1;        $self->{confident} = 1;
427        last SNIFFING;        last SNIFFING;
428      } elsif ($byte_buffer =~ /^\xEF\xBB\xBF/) {      } elsif ($byte_buffer =~ /^\xEF\xBB\xBF/) {
429        $charset = Message::Charset::Info->get_by_iana_name ('utf-8');        $charset = Message::Charset::Info->get_by_html_name ('utf-8');
430        ($char_stream, $e_status) = $charset->get_decode_handle        ($char_stream, $e_status) = $charset->get_decode_handle
431            ($byte_stream, allow_error_reporting => 1,            ($byte_stream, allow_error_reporting => 1,
432             allow_fallback => 1, byte_buffer => \$byte_buffer);             allow_fallback => 1, byte_buffer => \$byte_buffer);
# Line 415  sub parse_byte_stream ($$$$;$) { Line 445  sub parse_byte_stream ($$$$;$) {
445      $charset_name = Whatpm::Charset::UniversalCharDet->detect_byte_string      $charset_name = Whatpm::Charset::UniversalCharDet->detect_byte_string
446          ($byte_buffer);          ($byte_buffer);
447      if (defined $charset_name) {      if (defined $charset_name) {
448        $charset = Message::Charset::Info->get_by_iana_name ($charset_name);        $charset = Message::Charset::Info->get_by_html_name ($charset_name);
449    
450        ## ISSUE: Unsupported encoding is not ignored according to the spec.        ## ISSUE: Unsupported encoding is not ignored according to the spec.
451        require Whatpm::Charset::DecodeHandle;        require Whatpm::Charset::DecodeHandle;
# Line 426  sub parse_byte_stream ($$$$;$) { Line 456  sub parse_byte_stream ($$$$;$) {
456             allow_fallback => 1, byte_buffer => \$byte_buffer);             allow_fallback => 1, byte_buffer => \$byte_buffer);
457        if ($char_stream) {        if ($char_stream) {
458          $buffer->{buffer} = $byte_buffer;          $buffer->{buffer} = $byte_buffer;
459          !!!parse-error (type => 'sniffing:chardet', ## TODO: type name          !!!parse-error (type => 'sniffing:chardet',
460                          value => $charset_name,                          text => $charset_name,
461                          level => $self->{info_level},                          level => $self->{level}->{info},
462                            layer => 'encode',
463                          line => 1, column => 1);                          line => 1, column => 1);
464          $self->{confident} = 0;          $self->{confident} = 0;
465          last SNIFFING;          last SNIFFING;
# Line 437  sub parse_byte_stream ($$$$;$) { Line 468  sub parse_byte_stream ($$$$;$) {
468    
469      ## Step 7: default      ## Step 7: default
470      ## TODO: Make this configurable.      ## TODO: Make this configurable.
471      $charset = Message::Charset::Info->get_by_iana_name ('windows-1252');      $charset = Message::Charset::Info->get_by_html_name ('windows-1252');
472          ## NOTE: We choose |windows-1252| here, since |utf-8| should be          ## NOTE: We choose |windows-1252| here, since |utf-8| should be
473          ## detectable in the step 6.          ## detectable in the step 6.
474      require Whatpm::Charset::DecodeHandle;      require Whatpm::Charset::DecodeHandle;
# Line 449  sub parse_byte_stream ($$$$;$) { Line 480  sub parse_byte_stream ($$$$;$) {
480                                         allow_fallback => 1,                                         allow_fallback => 1,
481                                         byte_buffer => \$byte_buffer);                                         byte_buffer => \$byte_buffer);
482      $buffer->{buffer} = $byte_buffer;      $buffer->{buffer} = $byte_buffer;
483      !!!parse-error (type => 'sniffing:default', ## TODO: type name      !!!parse-error (type => 'sniffing:default',
484                      value => 'windows-1252',                      text => 'windows-1252',
485                      level => $self->{info_level},                      level => $self->{level}->{info},
486                      line => 1, column => 1);                      line => 1, column => 1,
487                        layer => 'encode');
488      $self->{confident} = 0;      $self->{confident} = 0;
489    } # SNIFFING    } # SNIFFING
490    
   $self->{input_encoding} = $charset->get_iana_name;  
491    if ($e_status & Message::Charset::Info::FALLBACK_ENCODING_IMPL ()) {    if ($e_status & Message::Charset::Info::FALLBACK_ENCODING_IMPL ()) {
492      !!!parse-error (type => 'chardecode:fallback', ## TODO: type name      $self->{input_encoding} = $charset->get_iana_name; ## TODO: Should we set actual charset decoder's encoding name?
493                      value => $self->{input_encoding},      !!!parse-error (type => 'chardecode:fallback',
494                      level => $self->{unsupported_level},                      #text => $self->{input_encoding},
495                      line => 1, column => 1);                      level => $self->{level}->{uncertain},
496                        line => 1, column => 1,
497                        layer => 'encode');
498    } elsif (not ($e_status &    } elsif (not ($e_status &
499                  Message::Charset::Info::ERROR_REPORTING_ENCODING_IMPL())) {                  Message::Charset::Info::ERROR_REPORTING_ENCODING_IMPL())) {
500      !!!parse-error (type => 'chardecode:no error', ## TODO: type name      $self->{input_encoding} = $charset->get_iana_name;
501                      value => $self->{input_encoding},      !!!parse-error (type => 'chardecode:no error',
502                      level => $self->{unsupported_level},                      text => $self->{input_encoding},
503                      line => 1, column => 1);                      level => $self->{level}->{uncertain},
504                        line => 1, column => 1,
505                        layer => 'encode');
506      } else {
507        $self->{input_encoding} = $charset->get_iana_name;
508    }    }
509    
510    $self->{change_encoding} = sub {    $self->{change_encoding} = sub {
# Line 475  sub parse_byte_stream ($$$$;$) { Line 512  sub parse_byte_stream ($$$$;$) {
512      $charset_name = shift;      $charset_name = shift;
513      my $token = shift;      my $token = shift;
514    
515      $charset = Message::Charset::Info->get_by_iana_name ($charset_name);      $charset = Message::Charset::Info->get_by_html_name ($charset_name);
516      ($char_stream, $e_status) = $charset->get_decode_handle      ($char_stream, $e_status) = $charset->get_decode_handle
517          ($byte_stream, allow_error_reporting => 1, allow_fallback => 1,          ($byte_stream, allow_error_reporting => 1, allow_fallback => 1,
518           byte_buffer => \ $buffer->{buffer});           byte_buffer => \ $buffer->{buffer});
# Line 484  sub parse_byte_stream ($$$$;$) { Line 521  sub parse_byte_stream ($$$$;$) {
521        ## "Change the encoding" algorithm:        ## "Change the encoding" algorithm:
522    
523        ## Step 1            ## Step 1    
524        if ($charset->{iana_names}->{'utf-16'}) { ## ISSUE: UTF-16BE -> UTF-8? UTF-16LE -> UTF-8?        if ($charset->{category} &
525          $charset = Message::Charset::Info->get_by_iana_name ('utf-8');            Message::Charset::Info::CHARSET_CATEGORY_UTF16 ()) {
526            $charset = Message::Charset::Info->get_by_html_name ('utf-8');
527          ($char_stream, $e_status) = $charset->get_decode_handle          ($char_stream, $e_status) = $charset->get_decode_handle
528              ($byte_stream,              ($byte_stream,
529               byte_buffer => \ $buffer->{buffer});               byte_buffer => \ $buffer->{buffer});
# Line 495  sub parse_byte_stream ($$$$;$) { Line 533  sub parse_byte_stream ($$$$;$) {
533        ## Step 2        ## Step 2
534        if (defined $self->{input_encoding} and        if (defined $self->{input_encoding} and
535            $self->{input_encoding} eq $charset_name) {            $self->{input_encoding} eq $charset_name) {
536          !!!parse-error (type => 'charset label:matching', ## TODO: type          !!!parse-error (type => 'charset label:matching',
537                          value => $charset_name,                          text => $charset_name,
538                          level => $self->{info_level});                          level => $self->{level}->{info});
539          $self->{confident} = 1;          $self->{confident} = 1;
540          return;          return;
541        }        }
542    
543        !!!parse-error (type => 'charset label detected:'.$self->{input_encoding}.        !!!parse-error (type => 'charset label detected',
544            ':'.$charset_name, level => 'w', token => $token);                        text => $self->{input_encoding},
545                          value => $charset_name,
546                          level => $self->{level}->{warn},
547                          token => $token);
548                
549        ## Step 3        ## Step 3
550        # if (can) {        # if (can) {
# Line 519  sub parse_byte_stream ($$$$;$) { Line 560  sub parse_byte_stream ($$$$;$) {
560    
561    my $char_onerror = sub {    my $char_onerror = sub {
562      my (undef, $type, %opt) = @_;      my (undef, $type, %opt) = @_;
563      !!!parse-error (%opt, type => $type,      !!!parse-error (layer => 'encode',
564                        %opt, type => $type,
565                      line => $self->{line}, column => $self->{column} + 1);                      line => $self->{line}, column => $self->{column} + 1);
566      if ($opt{octets}) {      if ($opt{octets}) {
567        ${$opt{octets}} = "\x{FFFD}"; # relacement character        ${$opt{octets}} = "\x{FFFD}"; # relacement character
568      }      }
569    };    };
570    $char_stream->onerror ($char_onerror);  
571      my $wrapped_char_stream = $get_wrapper->($char_stream);
572      $wrapped_char_stream->onerror ($char_onerror);
573    
574    my @args = @_; shift @args; # $s    my @args = @_; shift @args; # $s
575    my $return;    my $return;
576    try {    try {
577      $return = $self->parse_char_stream ($char_stream, @args);        $return = $self->parse_char_stream ($wrapped_char_stream, @args);  
578    } catch Whatpm::HTML::RestartParser with {    } catch Whatpm::HTML::RestartParser with {
579      ## NOTE: Invoked after {change_encoding}.      ## NOTE: Invoked after {change_encoding}.
580    
     $self->{input_encoding} = $charset->get_iana_name;  
581      if ($e_status & Message::Charset::Info::FALLBACK_ENCODING_IMPL ()) {      if ($e_status & Message::Charset::Info::FALLBACK_ENCODING_IMPL ()) {
582        !!!parse-error (type => 'chardecode:fallback', ## TODO: type name        $self->{input_encoding} = $charset->get_iana_name; ## TODO: Should we set actual charset decoder's encoding name?
583                        value => $self->{input_encoding},        !!!parse-error (type => 'chardecode:fallback',
584                        level => $self->{unsupported_level},                        level => $self->{level}->{uncertain},
585                        line => 1, column => 1);                        #text => $self->{input_encoding},
586                          line => 1, column => 1,
587                          layer => 'encode');
588      } elsif (not ($e_status &      } elsif (not ($e_status &
589                    Message::Charset::Info::ERROR_REPORTING_ENCODING_IMPL())) {                    Message::Charset::Info::ERROR_REPORTING_ENCODING_IMPL())) {
590        !!!parse-error (type => 'chardecode:no error', ## TODO: type name        $self->{input_encoding} = $charset->get_iana_name;
591                        value => $self->{input_encoding},        !!!parse-error (type => 'chardecode:no error',
592                        level => $self->{unsupported_level},                        text => $self->{input_encoding},
593                        line => 1, column => 1);                        level => $self->{level}->{uncertain},
594                          line => 1, column => 1,
595                          layer => 'encode');
596        } else {
597          $self->{input_encoding} = $charset->get_iana_name;
598      }      }
599      $self->{confident} = 1;      $self->{confident} = 1;
600      $char_stream->onerror ($char_onerror);  
601      $return = $self->parse_char_stream ($char_stream, @args);      $wrapped_char_stream = $get_wrapper->($char_stream);
602        $wrapped_char_stream->onerror ($char_onerror);
603    
604        $return = $self->parse_char_stream ($wrapped_char_stream, @args);
605    };    };
606    return $return;    return $return;
607  } # parse_byte_stream  } # parse_byte_stream
# Line 563  sub parse_byte_stream ($$$$;$) { Line 615  sub parse_byte_stream ($$$$;$) {
615  ## such as |parse_byte_string| in this module, must ensure that it does  ## such as |parse_byte_string| in this module, must ensure that it does
616  ## strip the BOM and never strip any ZWNBSP.  ## strip the BOM and never strip any ZWNBSP.
617    
618  sub parse_char_string ($$$;$) {  sub parse_char_string ($$$;$$) {
619      #my ($self, $s, $doc, $onerror, $get_wrapper) = @_;
620    my $self = shift;    my $self = shift;
621    require utf8;    require utf8;
622    my $s = ref $_[0] ? $_[0] : \($_[0]);    my $s = ref $_[0] ? $_[0] : \($_[0]);
623    open my $input, '<' . (utf8::is_utf8 ($$s) ? ':utf8' : ''), $s;    open my $input, '<' . (utf8::is_utf8 ($$s) ? ':utf8' : ''), $s;
624      if ($_[3]) {
625        $input = $_[3]->($input);
626      }
627    return $self->parse_char_stream ($input, @_[1..$#_]);    return $self->parse_char_stream ($input, @_[1..$#_]);
628  } # parse_char_string  } # parse_char_string
629  *parse_string = \&parse_char_string;  *parse_string = \&parse_char_string; ## NOTE: Alias for backward compatibility.
630    
631  sub parse_char_stream ($$$;$) {  sub parse_char_stream ($$$;$) {
632    my $self = ref $_[0] ? shift : shift->new;    my $self = ref $_[0] ? shift : shift->new;
# Line 644  sub parse_char_stream ($$$;$) { Line 700  sub parse_char_stream ($$$;$) {
700                0x10FFFE => 1, 0x10FFFF => 1,                0x10FFFE => 1, 0x10FFFF => 1,
701               }->{$self->{next_char}}) {               }->{$self->{next_char}}) {
702        !!!cp ('j5');        !!!cp ('j5');
703        !!!parse-error (type => 'control char', level => $self->{must_level});        if ($self->{next_char} < 0x10000) {
704  ## TODO: error type documentation          !!!parse-error (type => 'control char',
705                            text => (sprintf 'U+%04X', $self->{next_char}));
706          } else {
707            !!!parse-error (type => 'control char',
708                            text => (sprintf 'U-%08X', $self->{next_char}));
709          }
710      }      }
711    };    };
712    $self->{prev_char} = [-1, -1, -1];    $self->{prev_char} = [-1, -1, -1];
# Line 674  sub parse_char_stream ($$$;$) { Line 735  sub parse_char_stream ($$$;$) {
735  sub new ($) {  sub new ($) {
736    my $class = shift;    my $class = shift;
737    my $self = bless {    my $self = bless {
738      must_level => 'm',      level => {must => 'm',
739      should_level => 's',                should => 's',
740      good_level => 'w',                warn => 'w',
741      warn_level => 'w',                info => 'i',
742      info_level => 'i',                uncertain => 'u'},
     unsupported_level => 'u',  
743    }, $class;    }, $class;
744    $self->{set_next_char} = sub {    $self->{set_next_char} = sub {
745      $self->{next_char} = -1;      $self->{next_char} = -1;
# Line 744  sub BOGUS_DOCTYPE_STATE () { 32 } Line 804  sub BOGUS_DOCTYPE_STATE () { 32 }
804  sub AFTER_ATTRIBUTE_VALUE_QUOTED_STATE () { 33 }  sub AFTER_ATTRIBUTE_VALUE_QUOTED_STATE () { 33 }
805  sub SELF_CLOSING_START_TAG_STATE () { 34 }  sub SELF_CLOSING_START_TAG_STATE () { 34 }
806  sub CDATA_BLOCK_STATE () { 35 }  sub CDATA_BLOCK_STATE () { 35 }
807    sub MD_HYPHEN_STATE () { 36 }
808    sub MD_DOCTYPE_STATE () { 37 }
809    sub MD_CDATA_STATE () { 38 }
810    
811  sub DOCTYPE_TOKEN () { 1 }  sub DOCTYPE_TOKEN () { 1 }
812  sub COMMENT_TOKEN () { 2 }  sub COMMENT_TOKEN () { 2 }
# Line 796  sub IN_COLUMN_GROUP_IM () { 0b10 } Line 859  sub IN_COLUMN_GROUP_IM () { 0b10 }
859  sub _initialize_tokenizer ($) {  sub _initialize_tokenizer ($) {
860    my $self = shift;    my $self = shift;
861    $self->{state} = DATA_STATE; # MUST    $self->{state} = DATA_STATE; # MUST
862      #$self->{state_keyword}; # initialized when used
863    $self->{content_model} = PCDATA_CONTENT_MODEL; # be    $self->{content_model} = PCDATA_CONTENT_MODEL; # be
864    undef $self->{current_token}; # start tag, end tag, comment, or DOCTYPE    undef $self->{current_token}; # start tag, end tag, comment, or DOCTYPE
865    undef $self->{current_attribute};    undef $self->{current_attribute};
# Line 826  sub _initialize_tokenizer ($) { Line 890  sub _initialize_tokenizer ($) {
890  ##     |->{self_closing}| is used to save the value of |$self->{self_closing}|  ##     |->{self_closing}| is used to save the value of |$self->{self_closing}|
891  ##     while the token is pushed back to the stack.  ##     while the token is pushed back to the stack.
892    
 ## ISSUE: "When a DOCTYPE token is created, its  
 ## <i>self-closing flag</i> must be unset (its other state is that it  
 ## be set), and its attributes list must be empty.": Wrong subject?  
   
893  ## Emitted token MUST immediately be handled by the tree construction state.  ## Emitted token MUST immediately be handled by the tree construction state.
894    
895  ## Before each step, UA MAY check to see if either one of the scripts in  ## Before each step, UA MAY check to see if either one of the scripts in
# Line 1342  sub _get_next_token ($) { Line 1402  sub _get_next_token ($) {
1402          if (exists $self->{current_token}->{attributes} # start tag or end tag          if (exists $self->{current_token}->{attributes} # start tag or end tag
1403              ->{$self->{current_attribute}->{name}}) { # MUST              ->{$self->{current_attribute}->{name}}) { # MUST
1404            !!!cp (57);            !!!cp (57);
1405            !!!parse-error (type => 'duplicate attribute:'.$self->{current_attribute}->{name}, line => $self->{current_attribute}->{line}, column => $self->{current_attribute}->{column});            !!!parse-error (type => 'duplicate attribute', text => $self->{current_attribute}->{name}, line => $self->{current_attribute}->{line}, column => $self->{current_attribute}->{column});
1406            ## Discard $self->{current_attribute} # MUST            ## Discard $self->{current_attribute} # MUST
1407          } else {          } else {
1408            !!!cp (58);            !!!cp (58);
# Line 1513  sub _get_next_token ($) { Line 1573  sub _get_next_token ($) {
1573    
1574          redo A;          redo A;
1575        } else {        } else {
1576          !!!cp (82);          if ($self->{next_char} == 0x0022 or # "
1577                $self->{next_char} == 0x0027) { # '
1578              !!!cp (78);
1579              !!!parse-error (type => 'bad attribute name');
1580            } else {
1581              !!!cp (82);
1582            }
1583          $self->{current_attribute}          $self->{current_attribute}
1584              = {name => chr ($self->{next_char}),              = {name => chr ($self->{next_char}),
1585                 value => '',                 value => '',
# Line 1548  sub _get_next_token ($) { Line 1614  sub _get_next_token ($) {
1614          !!!next-input-character;          !!!next-input-character;
1615          redo A;          redo A;
1616        } elsif ($self->{next_char} == 0x003E) { # >        } elsif ($self->{next_char} == 0x003E) { # >
1617            !!!parse-error (type => 'empty unquoted attribute value');
1618          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
1619            !!!cp (87);            !!!cp (87);
1620            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
# Line 1938  sub _get_next_token ($) { Line 2005  sub _get_next_token ($) {
2005        die "$0: _get_next_token: unexpected case [BC]";        die "$0: _get_next_token: unexpected case [BC]";
2006      } elsif ($self->{state} == MARKUP_DECLARATION_OPEN_STATE) {      } elsif ($self->{state} == MARKUP_DECLARATION_OPEN_STATE) {
2007        ## (only happen if PCDATA state)        ## (only happen if PCDATA state)
   
       my ($l, $c) = ($self->{line_prev}, $self->{column_prev} - 1);  
   
       my @next_char;  
       push @next_char, $self->{next_char};  
2008                
2009        if ($self->{next_char} == 0x002D) { # -        if ($self->{next_char} == 0x002D) { # -
2010            !!!cp (133);
2011            $self->{state} = MD_HYPHEN_STATE;
2012          !!!next-input-character;          !!!next-input-character;
2013          push @next_char, $self->{next_char};          redo A;
         if ($self->{next_char} == 0x002D) { # -  
           !!!cp (127);  
           $self->{current_token} = {type => COMMENT_TOKEN, data => '',  
                                     line => $l, column => $c,  
                                    };  
           $self->{state} = COMMENT_START_STATE;  
           !!!next-input-character;  
           redo A;  
         } else {  
           !!!cp (128);  
         }  
2014        } elsif ($self->{next_char} == 0x0044 or # D        } elsif ($self->{next_char} == 0x0044 or # D
2015                 $self->{next_char} == 0x0064) { # d                 $self->{next_char} == 0x0064) { # d
2016            ## ASCII case-insensitive.
2017            !!!cp (130);
2018            $self->{state} = MD_DOCTYPE_STATE;
2019            $self->{state_keyword} = chr $self->{next_char};
2020          !!!next-input-character;          !!!next-input-character;
2021          push @next_char, $self->{next_char};          redo A;
         if ($self->{next_char} == 0x004F or # O  
             $self->{next_char} == 0x006F) { # o  
           !!!next-input-character;  
           push @next_char, $self->{next_char};  
           if ($self->{next_char} == 0x0043 or # C  
               $self->{next_char} == 0x0063) { # c  
             !!!next-input-character;  
             push @next_char, $self->{next_char};  
             if ($self->{next_char} == 0x0054 or # T  
                 $self->{next_char} == 0x0074) { # t  
               !!!next-input-character;  
               push @next_char, $self->{next_char};  
               if ($self->{next_char} == 0x0059 or # Y  
                   $self->{next_char} == 0x0079) { # y  
                 !!!next-input-character;  
                 push @next_char, $self->{next_char};  
                 if ($self->{next_char} == 0x0050 or # P  
                     $self->{next_char} == 0x0070) { # p  
                   !!!next-input-character;  
                   push @next_char, $self->{next_char};  
                   if ($self->{next_char} == 0x0045 or # E  
                       $self->{next_char} == 0x0065) { # e  
                     !!!cp (129);  
                     ## TODO: What a stupid code this is!  
                     $self->{state} = DOCTYPE_STATE;  
                     $self->{current_token} = {type => DOCTYPE_TOKEN,  
                                               quirks => 1,  
                                               line => $l, column => $c,  
                                              };  
                     !!!next-input-character;  
                     redo A;  
                   } else {  
                     !!!cp (130);  
                   }  
                 } else {  
                   !!!cp (131);  
                 }  
               } else {  
                 !!!cp (132);  
               }  
             } else {  
               !!!cp (133);  
             }  
           } else {  
             !!!cp (134);  
           }  
         } else {  
           !!!cp (135);  
         }  
2022        } elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM and        } elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM and
2023                 $self->{open_elements}->[-1]->[1] & FOREIGN_EL and                 $self->{open_elements}->[-1]->[1] & FOREIGN_EL and
2024                 $self->{next_char} == 0x005B) { # [                 $self->{next_char} == 0x005B) { # [
2025            !!!cp (135.4);                
2026            $self->{state} = MD_CDATA_STATE;
2027            $self->{state_keyword} = '[';
2028          !!!next-input-character;          !!!next-input-character;
2029          push @next_char, $self->{next_char};          redo A;
         if ($self->{next_char} == 0x0043) { # C  
           !!!next-input-character;  
           push @next_char, $self->{next_char};  
           if ($self->{next_char} == 0x0044) { # D  
             !!!next-input-character;  
             push @next_char, $self->{next_char};  
             if ($self->{next_char} == 0x0041) { # A  
               !!!next-input-character;  
               push @next_char, $self->{next_char};  
               if ($self->{next_char} == 0x0054) { # T  
                 !!!next-input-character;  
                 push @next_char, $self->{next_char};  
                 if ($self->{next_char} == 0x0041) { # A  
                   !!!next-input-character;  
                   push @next_char, $self->{next_char};  
                   if ($self->{next_char} == 0x005B) { # [  
                     !!!cp (135.1);  
                     $self->{state} = CDATA_BLOCK_STATE;  
                     !!!next-input-character;  
                     redo A;  
                   } else {  
                     !!!cp (135.2);  
                   }  
                 } else {  
                   !!!cp (135.3);  
                 }  
               } else {  
                 !!!cp (135.4);                  
               }  
             } else {  
               !!!cp (135.5);  
             }  
           } else {  
             !!!cp (135.6);  
           }  
         } else {  
           !!!cp (135.7);  
         }  
2030        } else {        } else {
2031          !!!cp (136);          !!!cp (136);
2032        }        }
2033    
2034        !!!parse-error (type => 'bogus comment');        !!!parse-error (type => 'bogus comment',
2035        $self->{next_char} = shift @next_char;                        line => $self->{line_prev},
2036        !!!back-next-input-character (@next_char);                        column => $self->{column_prev} - 1);
2037          ## Reconsume.
2038        $self->{state} = BOGUS_COMMENT_STATE;        $self->{state} = BOGUS_COMMENT_STATE;
2039        $self->{current_token} = {type => COMMENT_TOKEN, data => '',        $self->{current_token} = {type => COMMENT_TOKEN, data => '',
2040                                  line => $l, column => $c,                                  line => $self->{line_prev},
2041                                    column => $self->{column_prev} - 1,
2042                                 };                                 };
2043        redo A;        redo A;
2044              } elsif ($self->{state} == MD_HYPHEN_STATE) {
2045        ## ISSUE: typos in spec: chacacters, is is a parse error        if ($self->{next_char} == 0x002D) { # -
2046        ## ISSUE: spec is somewhat unclear on "is the first character that will be in the comment"; what is "that will be in the comment" is what the algorithm defines, isn't it?          !!!cp (127);
2047            $self->{current_token} = {type => COMMENT_TOKEN, data => '',
2048                                      line => $self->{line_prev},
2049                                      column => $self->{column_prev} - 2,
2050                                     };
2051            $self->{state} = COMMENT_START_STATE;
2052            !!!next-input-character;
2053            redo A;
2054          } else {
2055            !!!cp (128);
2056            !!!parse-error (type => 'bogus comment',
2057                            line => $self->{line_prev},
2058                            column => $self->{column_prev} - 2);
2059            $self->{state} = BOGUS_COMMENT_STATE;
2060            ## Reconsume.
2061            $self->{current_token} = {type => COMMENT_TOKEN,
2062                                      data => '-',
2063                                      line => $self->{line_prev},
2064                                      column => $self->{column_prev} - 2,
2065                                     };
2066            redo A;
2067          }
2068        } elsif ($self->{state} == MD_DOCTYPE_STATE) {
2069          ## ASCII case-insensitive.
2070          if ($self->{next_char} == [
2071                undef,
2072                0x004F, # O
2073                0x0043, # C
2074                0x0054, # T
2075                0x0059, # Y
2076                0x0050, # P
2077              ]->[length $self->{state_keyword}] or
2078              $self->{next_char} == [
2079                undef,
2080                0x006F, # o
2081                0x0063, # c
2082                0x0074, # t
2083                0x0079, # y
2084                0x0070, # p
2085              ]->[length $self->{state_keyword}]) {
2086            !!!cp (131);
2087            ## Stay in the state.
2088            $self->{state_keyword} .= chr $self->{next_char};
2089            !!!next-input-character;
2090            redo A;
2091          } elsif ((length $self->{state_keyword}) == 6 and
2092                   ($self->{next_char} == 0x0045 or # E
2093                    $self->{next_char} == 0x0065)) { # e
2094            !!!cp (129);
2095            $self->{state} = DOCTYPE_STATE;
2096            $self->{current_token} = {type => DOCTYPE_TOKEN,
2097                                      quirks => 1,
2098                                      line => $self->{line_prev},
2099                                      column => $self->{column_prev} - 7,
2100                                     };
2101            !!!next-input-character;
2102            redo A;
2103          } else {
2104            !!!cp (132);        
2105            !!!parse-error (type => 'bogus comment',
2106                            line => $self->{line_prev},
2107                            column => $self->{column_prev} - 1 - length $self->{state_keyword});
2108            $self->{state} = BOGUS_COMMENT_STATE;
2109            ## Reconsume.
2110            $self->{current_token} = {type => COMMENT_TOKEN,
2111                                      data => $self->{state_keyword},
2112                                      line => $self->{line_prev},
2113                                      column => $self->{column_prev} - 1 - length $self->{state_keyword},
2114                                     };
2115            redo A;
2116          }
2117        } elsif ($self->{state} == MD_CDATA_STATE) {
2118          if ($self->{next_char} == {
2119                '[' => 0x0043, # C
2120                '[C' => 0x0044, # D
2121                '[CD' => 0x0041, # A
2122                '[CDA' => 0x0054, # T
2123                '[CDAT' => 0x0041, # A
2124              }->{$self->{state_keyword}}) {
2125            !!!cp (135.1);
2126            ## Stay in the state.
2127            $self->{state_keyword} .= chr $self->{next_char};
2128            !!!next-input-character;
2129            redo A;
2130          } elsif ($self->{state_keyword} eq '[CDATA' and
2131                   $self->{next_char} == 0x005B) { # [
2132            !!!cp (135.2);
2133            $self->{state} = CDATA_BLOCK_STATE;
2134            !!!next-input-character;
2135            redo A;
2136          } else {
2137            !!!cp (135.3);
2138            !!!parse-error (type => 'bogus comment',
2139                            line => $self->{line_prev},
2140                            column => $self->{column_prev} - 1 - length $self->{state_keyword});
2141            $self->{state} = BOGUS_COMMENT_STATE;
2142            ## Reconsume.
2143            $self->{current_token} = {type => COMMENT_TOKEN,
2144                                      data => $self->{state_keyword},
2145                                      line => $self->{line_prev},
2146                                      column => $self->{column_prev} - 1 - length $self->{state_keyword},
2147                                     };
2148            redo A;
2149          }
2150      } elsif ($self->{state} == COMMENT_START_STATE) {      } elsif ($self->{state} == COMMENT_START_STATE) {
2151        if ($self->{next_char} == 0x002D) { # -        if ($self->{next_char} == 0x002D) { # -
2152          !!!cp (137);          !!!cp (137);
# Line 2653  sub _get_next_token ($) { Line 2731  sub _get_next_token ($) {
2731          redo A;          redo A;
2732        } elsif ($self->{next_char} == 0x003E) { # >        } elsif ($self->{next_char} == 0x003E) { # >
2733          !!!cp (208);          !!!cp (208);
2734          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed SYSTEM literal');
2735    
2736          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2737          !!!next-input-character;          !!!next-input-character;
# Line 2689  sub _get_next_token ($) { Line 2767  sub _get_next_token ($) {
2767          redo A;          redo A;
2768        } elsif ($self->{next_char} == 0x003E) { # >        } elsif ($self->{next_char} == 0x003E) { # >
2769          !!!cp (212);          !!!cp (212);
2770          !!!parse-error (type => 'unclosed PUBLIC literal');          !!!parse-error (type => 'unclosed SYSTEM literal');
2771    
2772          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2773          !!!next-input-character;          !!!next-input-character;
# Line 2736  sub _get_next_token ($) { Line 2814  sub _get_next_token ($) {
2814          redo A;          redo A;
2815        } elsif ($self->{next_char} == -1) {        } elsif ($self->{next_char} == -1) {
2816          !!!cp (217);          !!!cp (217);
2817            !!!parse-error (type => 'unclosed DOCTYPE');
2818          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2819          ## reconsume          ## reconsume
2820    
# Line 2898  sub _tokenize_attempt_to_consume_an_enti Line 2976  sub _tokenize_attempt_to_consume_an_enti
2976    
2977          if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {          if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {
2978            !!!cp (1008);            !!!cp (1008);
2979            !!!parse-error (type => (sprintf 'invalid character reference:U+%04X', $code), line => $l, column => $c);            !!!parse-error (type => 'invalid character reference',
2980                              text => (sprintf 'U+%04X', $code),
2981                              line => $l, column => $c);
2982            $code = 0xFFFD;            $code = 0xFFFD;
2983          } elsif ($code > 0x10FFFF) {          } elsif ($code > 0x10FFFF) {
2984            !!!cp (1009);            !!!cp (1009);
2985            !!!parse-error (type => (sprintf 'invalid character reference:U-%08X', $code), line => $l, column => $c);            !!!parse-error (type => 'invalid character reference',
2986                              text => (sprintf 'U-%08X', $code),
2987                              line => $l, column => $c);
2988            $code = 0xFFFD;            $code = 0xFFFD;
2989          } elsif ($code == 0x000D) {          } elsif ($code == 0x000D) {
2990            !!!cp (1010);            !!!cp (1010);
# Line 2910  sub _tokenize_attempt_to_consume_an_enti Line 2992  sub _tokenize_attempt_to_consume_an_enti
2992            $code = 0x000A;            $code = 0x000A;
2993          } elsif (0x80 <= $code and $code <= 0x9F) {          } elsif (0x80 <= $code and $code <= 0x9F) {
2994            !!!cp (1011);            !!!cp (1011);
2995            !!!parse-error (type => (sprintf 'C1 character reference:U+%04X', $code), line => $l, column => $c);            !!!parse-error (type => 'C1 character reference', text => (sprintf 'U+%04X', $code), line => $l, column => $c);
2996            $code = $c1_entity_char->{$code};            $code = $c1_entity_char->{$code};
2997          }          }
2998    
# Line 2943  sub _tokenize_attempt_to_consume_an_enti Line 3025  sub _tokenize_attempt_to_consume_an_enti
3025    
3026        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {
3027          !!!cp (1015);          !!!cp (1015);
3028          !!!parse-error (type => (sprintf 'invalid character reference:U+%04X', $code), line => $l, column => $c);          !!!parse-error (type => 'invalid character reference',
3029                            text => (sprintf 'U+%04X', $code),
3030                            line => $l, column => $c);
3031          $code = 0xFFFD;          $code = 0xFFFD;
3032        } elsif ($code > 0x10FFFF) {        } elsif ($code > 0x10FFFF) {
3033          !!!cp (1016);          !!!cp (1016);
3034          !!!parse-error (type => (sprintf 'invalid character reference:U-%08X', $code), line => $l, column => $c);          !!!parse-error (type => 'invalid character reference',
3035                            text => (sprintf 'U-%08X', $code),
3036                            line => $l, column => $c);
3037          $code = 0xFFFD;          $code = 0xFFFD;
3038        } elsif ($code == 0x000D) {        } elsif ($code == 0x000D) {
3039          !!!cp (1017);          !!!cp (1017);
3040          !!!parse-error (type => 'CR character reference', line => $l, column => $c);          !!!parse-error (type => 'CR character reference',
3041                            line => $l, column => $c);
3042          $code = 0x000A;          $code = 0x000A;
3043        } elsif (0x80 <= $code and $code <= 0x9F) {        } elsif (0x80 <= $code and $code <= 0x9F) {
3044          !!!cp (1018);          !!!cp (1018);
3045          !!!parse-error (type => (sprintf 'C1 character reference:U+%04X', $code), line => $l, column => $c);          !!!parse-error (type => 'C1 character reference',
3046                            text => (sprintf 'U+%04X', $code),
3047                            line => $l, column => $c);
3048          $code = $c1_entity_char->{$code};          $code = $c1_entity_char->{$code};
3049        }        }
3050                
# Line 3053  sub _initialize_tree_constructor ($) { Line 3142  sub _initialize_tree_constructor ($) {
3142    ## TODO: Turn mutation events off # MUST    ## TODO: Turn mutation events off # MUST
3143    ## TODO: Turn loose Document option (manakai extension) on    ## TODO: Turn loose Document option (manakai extension) on
3144    $self->{document}->manakai_is_html (1); # MUST    $self->{document}->manakai_is_html (1); # MUST
3145      $self->{document}->set_user_data (manakai_source_line => 1);
3146      $self->{document}->set_user_data (manakai_source_column => 1);
3147  } # _initialize_tree_constructor  } # _initialize_tree_constructor
3148    
3149  sub _terminate_tree_constructor ($) {  sub _terminate_tree_constructor ($) {
# Line 3107  sub _tree_construction_initial ($) { Line 3198  sub _tree_construction_initial ($) {
3198        ## language.        ## language.
3199        my $doctype_name = $token->{name};        my $doctype_name = $token->{name};
3200        $doctype_name = '' unless defined $doctype_name;        $doctype_name = '' unless defined $doctype_name;
3201        $doctype_name =~ tr/a-z/A-Z/;        $doctype_name =~ tr/a-z/A-Z/; # ASCII case-insensitive
3202        if (not defined $token->{name} or # <!DOCTYPE>        if (not defined $token->{name} or # <!DOCTYPE>
           defined $token->{public_identifier} or  
3203            defined $token->{system_identifier}) {            defined $token->{system_identifier}) {
3204          !!!cp ('t1');          !!!cp ('t1');
3205          !!!parse-error (type => 'not HTML5', token => $token);          !!!parse-error (type => 'not HTML5', token => $token);
3206        } elsif ($doctype_name ne 'HTML') {        } elsif ($doctype_name ne 'HTML') {
3207          !!!cp ('t2');          !!!cp ('t2');
         ## ISSUE: ASCII case-insensitive? (in fact it does not matter)  
3208          !!!parse-error (type => 'not HTML5', token => $token);          !!!parse-error (type => 'not HTML5', token => $token);
3209          } elsif (defined $token->{public_identifier}) {
3210            if ($token->{public_identifier} eq 'XSLT-compat') {
3211              !!!cp ('t1.2');
3212              !!!parse-error (type => 'XSLT-compat', token => $token,
3213                              level => $self->{level}->{should});
3214            } else {
3215              !!!parse-error (type => 'not HTML5', token => $token);
3216            }
3217        } else {        } else {
3218          !!!cp ('t3');          !!!cp ('t3');
3219            #
3220        }        }
3221                
3222        my $doctype = $self->{document}->create_document_type_definition        my $doctype = $self->{document}->create_document_type_definition
# Line 3419  sub _reset_insertion_mode ($) { Line 3517  sub _reset_insertion_mode ($) {
3517          ## NOTE: Strictly spaking, the line below only applies to MathML and          ## NOTE: Strictly spaking, the line below only applies to MathML and
3518          ## SVG elements.  Currently the HTML syntax supports only MathML and          ## SVG elements.  Currently the HTML syntax supports only MathML and
3519          ## SVG elements as foreigners.          ## SVG elements as foreigners.
3520          $new_mode = $self->{insertion_mode} | IN_FOREIGN_CONTENT_IM;          $new_mode = IN_BODY_IM | IN_FOREIGN_CONTENT_IM;
         ## ISSUE: What is set as the secondary insertion mode?  
3521        } elsif ($node->[1] & TABLE_CELL_EL) {        } elsif ($node->[1] & TABLE_CELL_EL) {
3522          if ($last) {          if ($last) {
3523            !!!cp ('t28.2');            !!!cp ('t28.2');
# Line 3621  sub _tree_construction_main ($) { Line 3718  sub _tree_construction_main ($) {
3718        ## NOTE: An end-of-file token.        ## NOTE: An end-of-file token.
3719        if ($content_model_flag == CDATA_CONTENT_MODEL) {        if ($content_model_flag == CDATA_CONTENT_MODEL) {
3720          !!!cp ('t43');          !!!cp ('t43');
3721          !!!parse-error (type => 'in CDATA:#'.$token->{type}, token => $token);          !!!parse-error (type => 'in CDATA:#eof', token => $token);
3722        } elsif ($content_model_flag == RCDATA_CONTENT_MODEL) {        } elsif ($content_model_flag == RCDATA_CONTENT_MODEL) {
3723          !!!cp ('t44');          !!!cp ('t44');
3724          !!!parse-error (type => 'in RCDATA:#'.$token->{type}, token => $token);          !!!parse-error (type => 'in RCDATA:#eof', token => $token);
3725        } else {        } else {
3726          die "$0: $content_model_flag in parse_rcdata";          die "$0: $content_model_flag in parse_rcdata";
3727        }        }
# Line 3661  sub _tree_construction_main ($) { Line 3758  sub _tree_construction_main ($) {
3758        ## Ignore the token        ## Ignore the token
3759      } else {      } else {
3760        !!!cp ('t48');        !!!cp ('t48');
3761        !!!parse-error (type => 'in CDATA:#'.$token->{type}, token => $token);        !!!parse-error (type => 'in CDATA:#eof', token => $token);
3762        ## ISSUE: And ignore?        ## ISSUE: And ignore?
3763        ## TODO: mark as "already executed"        ## TODO: mark as "already executed"
3764      }      }
# Line 3712  sub _tree_construction_main ($) { Line 3809  sub _tree_construction_main ($) {
3809        } # AFE        } # AFE
3810        unless (defined $formatting_element) {        unless (defined $formatting_element) {
3811          !!!cp ('t53');          !!!cp ('t53');
3812          !!!parse-error (type => 'unmatched end tag:'.$tag_name, token => $end_tag_token);          !!!parse-error (type => 'unmatched end tag', text => $tag_name, token => $end_tag_token);
3813          ## Ignore the token          ## Ignore the token
3814          !!!next-token;          !!!next-token;
3815          return;          return;
# Line 3729  sub _tree_construction_main ($) { Line 3826  sub _tree_construction_main ($) {
3826              last INSCOPE;              last INSCOPE;
3827            } else { # in open elements but not in scope            } else { # in open elements but not in scope
3828              !!!cp ('t55');              !!!cp ('t55');
3829              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name},              !!!parse-error (type => 'unmatched end tag',
3830                                text => $token->{tag_name},
3831                              token => $end_tag_token);                              token => $end_tag_token);
3832              ## Ignore the token              ## Ignore the token
3833              !!!next-token;              !!!next-token;
# Line 3742  sub _tree_construction_main ($) { Line 3840  sub _tree_construction_main ($) {
3840        } # INSCOPE        } # INSCOPE
3841        unless (defined $formatting_element_i_in_open) {        unless (defined $formatting_element_i_in_open) {
3842          !!!cp ('t57');          !!!cp ('t57');
3843          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name},          !!!parse-error (type => 'unmatched end tag',
3844                            text => $token->{tag_name},
3845                          token => $end_tag_token);                          token => $end_tag_token);
3846          pop @$active_formatting_elements; # $formatting_element          pop @$active_formatting_elements; # $formatting_element
3847          !!!next-token; ## TODO: ok?          !!!next-token; ## TODO: ok?
# Line 3751  sub _tree_construction_main ($) { Line 3850  sub _tree_construction_main ($) {
3850        if (not $self->{open_elements}->[-1]->[0] eq $formatting_element->[0]) {        if (not $self->{open_elements}->[-1]->[0] eq $formatting_element->[0]) {
3851          !!!cp ('t58');          !!!cp ('t58');
3852          !!!parse-error (type => 'not closed',          !!!parse-error (type => 'not closed',
3853                          value => $self->{open_elements}->[-1]->[0]                          text => $self->{open_elements}->[-1]->[0]
3854                              ->manakai_local_name,                              ->manakai_local_name,
3855                          token => $end_tag_token);                          token => $end_tag_token);
3856        }        }
# Line 3960  sub _tree_construction_main ($) { Line 4059  sub _tree_construction_main ($) {
4059    B: while (1) {    B: while (1) {
4060      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
4061        !!!cp ('t73');        !!!cp ('t73');
4062        !!!parse-error (type => 'DOCTYPE in the middle', token => $token);        !!!parse-error (type => 'in html:#DOCTYPE', token => $token);
4063        ## Ignore the token        ## Ignore the token
4064        ## Stay in the phase        ## Stay in the phase
4065        !!!next-token;        !!!next-token;
# Line 3969  sub _tree_construction_main ($) { Line 4068  sub _tree_construction_main ($) {
4068               $token->{tag_name} eq 'html') {               $token->{tag_name} eq 'html') {
4069        if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {        if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
4070          !!!cp ('t79');          !!!cp ('t79');
4071          !!!parse-error (type => 'after html:html', token => $token);          !!!parse-error (type => 'after html', text => 'html', token => $token);
4072          $self->{insertion_mode} = AFTER_BODY_IM;          $self->{insertion_mode} = AFTER_BODY_IM;
4073        } elsif ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {        } elsif ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {
4074          !!!cp ('t80');          !!!cp ('t80');
4075          !!!parse-error (type => 'after html:html', token => $token);          !!!parse-error (type => 'after html', text => 'html', token => $token);
4076          $self->{insertion_mode} = AFTER_FRAMESET_IM;          $self->{insertion_mode} = AFTER_FRAMESET_IM;
4077        } else {        } else {
4078          !!!cp ('t81');          !!!cp ('t81');
# Line 4024  sub _tree_construction_main ($) { Line 4123  sub _tree_construction_main ($) {
4123            #            #
4124          } elsif ({          } elsif ({
4125                    b => 1, big => 1, blockquote => 1, body => 1, br => 1,                    b => 1, big => 1, blockquote => 1, body => 1, br => 1,
4126                    center => 1, code => 1, dd => 1, div => 1, dl => 1, em => 1,                    center => 1, code => 1, dd => 1, div => 1, dl => 1, dt => 1,
4127                    embed => 1, font => 1, h1 => 1, h2 => 1, h3 => 1, ## No h4!                    em => 1, embed => 1, font => 1, h1 => 1, h2 => 1, h3 => 1,
4128                    h5 => 1, h6 => 1, head => 1, hr => 1, i => 1, img => 1,                    h4 => 1, h5 => 1, h6 => 1, head => 1, hr => 1, i => 1,
4129                    li => 1, menu => 1, meta => 1, nobr => 1, p => 1, pre => 1,                    img => 1, li => 1, listing => 1, menu => 1, meta => 1,
4130                    ruby => 1, s => 1, small => 1, span => 1, strong => 1,                    nobr => 1, ol => 1, p => 1, pre => 1, ruby => 1, s => 1,
4131                    sub => 1, sup => 1, table => 1, tt => 1, u => 1, ul => 1,                    small => 1, span => 1, strong => 1, strike => 1, sub => 1,
4132                    var => 1,                    sup => 1, table => 1, tt => 1, u => 1, ul => 1, var => 1,
4133                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
4134            !!!cp ('t87.2');            !!!cp ('t87.2');
4135            !!!parse-error (type => 'not closed',            !!!parse-error (type => 'not closed',
4136                            value => $self->{open_elements}->[-1]->[0]                            text => $self->{open_elements}->[-1]->[0]
4137                                ->manakai_local_name,                                ->manakai_local_name,
4138                            token => $token);                            token => $token);
4139    
# Line 4110  sub _tree_construction_main ($) { Line 4209  sub _tree_construction_main ($) {
4209          !!!cp ('t87.5');          !!!cp ('t87.5');
4210          #          #
4211        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
         ## NOTE: "using the rules for secondary insertion mode" then "continue"  
4212          !!!cp ('t87.6');          !!!cp ('t87.6');
4213          #          !!!parse-error (type => 'not closed',
4214          ## TODO: ...                          text => $self->{open_elements}->[-1]->[0]
4215                                ->manakai_local_name,
4216                            token => $token);
4217    
4218            pop @{$self->{open_elements}}
4219                while $self->{open_elements}->[-1]->[1] & FOREIGN_EL;
4220    
4221            $self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM;
4222            ## Reprocess.
4223            next B;
4224        } else {        } else {
4225          die "$0: $token->{type}: Unknown token type";                  die "$0: $token->{type}: Unknown token type";        
4226        }        }
# Line 4154  sub _tree_construction_main ($) { Line 4261  sub _tree_construction_main ($) {
4261            !!!cp ('t90');            !!!cp ('t90');
4262            ## As if </noscript>            ## As if </noscript>
4263            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
4264            !!!parse-error (type => 'in noscript:#character', token => $token);            !!!parse-error (type => 'in noscript:#text', token => $token);
4265                        
4266            ## Reprocess in the "in head" insertion mode...            ## Reprocess in the "in head" insertion mode...
4267            ## As if </head>            ## As if </head>
# Line 4191  sub _tree_construction_main ($) { Line 4298  sub _tree_construction_main ($) {
4298              next B;              next B;
4299            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4300              !!!cp ('t93.2');              !!!cp ('t93.2');
4301              !!!parse-error (type => 'after head:head', token => $token); ## TODO: error type              !!!parse-error (type => 'after head', text => 'head',
4302                                token => $token);
4303              ## Ignore the token              ## Ignore the token
4304              !!!nack ('t93.3');              !!!nack ('t93.3');
4305              !!!next-token;              !!!next-token;
4306              next B;              next B;
4307            } else {            } else {
4308              !!!cp ('t95');              !!!cp ('t95');
4309              !!!parse-error (type => 'in head:head', token => $token); # or in head noscript              !!!parse-error (type => 'in head:head',
4310                                token => $token); # or in head noscript
4311              ## Ignore the token              ## Ignore the token
4312              !!!nack ('t95.1');              !!!nack ('t95.1');
4313              !!!next-token;              !!!next-token;
# Line 4223  sub _tree_construction_main ($) { Line 4332  sub _tree_construction_main ($) {
4332                  !!!cp ('t98');                  !!!cp ('t98');
4333                  ## As if </noscript>                  ## As if </noscript>
4334                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4335                  !!!parse-error (type => 'in noscript:base', token => $token);                  !!!parse-error (type => 'in noscript', text => 'base',
4336                                    token => $token);
4337                                
4338                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
4339                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
# Line 4234  sub _tree_construction_main ($) { Line 4344  sub _tree_construction_main ($) {
4344                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
4345                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4346                  !!!cp ('t100');                  !!!cp ('t100');
4347                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'after head',
4348                                    text => $token->{tag_name}, token => $token);
4349                  push @{$self->{open_elements}},                  push @{$self->{open_elements}},
4350                      [$self->{head_element}, $el_category->{head}];                      [$self->{head_element}, $el_category->{head}];
4351                } else {                } else {
# Line 4251  sub _tree_construction_main ($) { Line 4362  sub _tree_construction_main ($) {
4362                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
4363                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4364                  !!!cp ('t102');                  !!!cp ('t102');
4365                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'after head',
4366                                    text => $token->{tag_name}, token => $token);
4367                  push @{$self->{open_elements}},                  push @{$self->{open_elements}},
4368                      [$self->{head_element}, $el_category->{head}];                      [$self->{head_element}, $el_category->{head}];
4369                } else {                } else {
# Line 4268  sub _tree_construction_main ($) { Line 4380  sub _tree_construction_main ($) {
4380                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
4381                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4382                  !!!cp ('t104');                  !!!cp ('t104');
4383                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'after head',
4384                                    text => $token->{tag_name}, token => $token);
4385                  push @{$self->{open_elements}},                  push @{$self->{open_elements}},
4386                      [$self->{head_element}, $el_category->{head}];                      [$self->{head_element}, $el_category->{head}];
4387                } else {                } else {
# Line 4337  sub _tree_construction_main ($) { Line 4450  sub _tree_construction_main ($) {
4450                  !!!cp ('t111');                  !!!cp ('t111');
4451                  ## As if </noscript>                  ## As if </noscript>
4452                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4453                  !!!parse-error (type => 'in noscript:title', token => $token);                  !!!parse-error (type => 'in noscript', text => 'title',
4454                                    token => $token);
4455                                
4456                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
4457                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
4458                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4459                  !!!cp ('t112');                  !!!cp ('t112');
4460                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'after head',
4461                                    text => $token->{tag_name}, token => $token);
4462                  push @{$self->{open_elements}},                  push @{$self->{open_elements}},
4463                      [$self->{head_element}, $el_category->{head}];                      [$self->{head_element}, $el_category->{head}];
4464                } else {                } else {
# Line 4357  sub _tree_construction_main ($) { Line 4472  sub _tree_construction_main ($) {
4472                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
4473                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4474                next B;                next B;
4475              } elsif ($token->{tag_name} eq 'style') {              } elsif ($token->{tag_name} eq 'style' or
4476                         $token->{tag_name} eq 'noframes') {
4477                ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and                ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and
4478                ## insertion mode IN_HEAD_IM)                ## insertion mode IN_HEAD_IM)
4479                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
4480                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4481                  !!!cp ('t114');                  !!!cp ('t114');
4482                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'after head',
4483                                    text => $token->{tag_name}, token => $token);
4484                  push @{$self->{open_elements}},                  push @{$self->{open_elements}},
4485                      [$self->{head_element}, $el_category->{head}];                      [$self->{head_element}, $el_category->{head}];
4486                } else {                } else {
# Line 4384  sub _tree_construction_main ($) { Line 4501  sub _tree_construction_main ($) {
4501                  next B;                  next B;
4502                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4503                  !!!cp ('t117');                  !!!cp ('t117');
4504                  !!!parse-error (type => 'in noscript:noscript', token => $token);                  !!!parse-error (type => 'in noscript', text => 'noscript',
4505                                    token => $token);
4506                  ## Ignore the token                  ## Ignore the token
4507                  !!!nack ('t117.1');                  !!!nack ('t117.1');
4508                  !!!next-token;                  !!!next-token;
# Line 4398  sub _tree_construction_main ($) { Line 4516  sub _tree_construction_main ($) {
4516                  !!!cp ('t119');                  !!!cp ('t119');
4517                  ## As if </noscript>                  ## As if </noscript>
4518                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4519                  !!!parse-error (type => 'in noscript:script', token => $token);                  !!!parse-error (type => 'in noscript', text => 'script',
4520                                    token => $token);
4521                                
4522                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
4523                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
4524                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4525                  !!!cp ('t120');                  !!!cp ('t120');
4526                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'after head',
4527                                    text => $token->{tag_name}, token => $token);
4528                  push @{$self->{open_elements}},                  push @{$self->{open_elements}},
4529                      [$self->{head_element}, $el_category->{head}];                      [$self->{head_element}, $el_category->{head}];
4530                } else {                } else {
# Line 4422  sub _tree_construction_main ($) { Line 4542  sub _tree_construction_main ($) {
4542                  !!!cp ('t122');                  !!!cp ('t122');
4543                  ## As if </noscript>                  ## As if </noscript>
4544                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4545                  !!!parse-error (type => 'in noscript:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'in noscript',
4546                                    text => $token->{tag_name}, token => $token);
4547                                    
4548                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
4549                  ## As if </head>                  ## As if </head>
# Line 4461  sub _tree_construction_main ($) { Line 4582  sub _tree_construction_main ($) {
4582                !!!cp ('t129');                !!!cp ('t129');
4583                ## As if </noscript>                ## As if </noscript>
4584                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
4585                !!!parse-error (type => 'in noscript:/'.$token->{tag_name}, token => $token);                !!!parse-error (type => 'in noscript:/',
4586                                  text => $token->{tag_name}, token => $token);
4587                                
4588                ## Reprocess in the "in head" insertion mode...                ## Reprocess in the "in head" insertion mode...
4589                ## As if </head>                ## As if </head>
# Line 4504  sub _tree_construction_main ($) { Line 4626  sub _tree_construction_main ($) {
4626                  !!!cp ('t133');                  !!!cp ('t133');
4627                  ## As if </noscript>                  ## As if </noscript>
4628                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4629                  !!!parse-error (type => 'in noscript:/head', token => $token);                  !!!parse-error (type => 'in noscript:/',
4630                                    text => 'head', token => $token);
4631                                    
4632                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
4633                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
# Line 4519  sub _tree_construction_main ($) { Line 4642  sub _tree_construction_main ($) {
4642                  next B;                  next B;
4643                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4644                  !!!cp ('t134.1');                  !!!cp ('t134.1');
4645                  !!!parse-error (type => 'unmatched end tag:head', token => $token);                  !!!parse-error (type => 'unmatched end tag', text => 'head',
4646                                    token => $token);
4647                  ## Ignore the token                  ## Ignore the token
4648                  !!!next-token;                  !!!next-token;
4649                  next B;                  next B;
# Line 4536  sub _tree_construction_main ($) { Line 4660  sub _tree_construction_main ($) {
4660                } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM or                } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM or
4661                         $self->{insertion_mode} == AFTER_HEAD_IM) {                         $self->{insertion_mode} == AFTER_HEAD_IM) {
4662                  !!!cp ('t137');                  !!!cp ('t137');
4663                  !!!parse-error (type => 'unmatched end tag:noscript', token => $token);                  !!!parse-error (type => 'unmatched end tag',
4664                                    text => 'noscript', token => $token);
4665                  ## Ignore the token ## ISSUE: An issue in the spec.                  ## Ignore the token ## ISSUE: An issue in the spec.
4666                  !!!next-token;                  !!!next-token;
4667                  next B;                  next B;
# Line 4551  sub _tree_construction_main ($) { Line 4676  sub _tree_construction_main ($) {
4676                    $self->{insertion_mode} == IN_HEAD_IM or                    $self->{insertion_mode} == IN_HEAD_IM or
4677                    $self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                    $self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4678                  !!!cp ('t140');                  !!!cp ('t140');
4679                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag',
4680                                    text => $token->{tag_name}, token => $token);
4681                  ## Ignore the token                  ## Ignore the token
4682                  !!!next-token;                  !!!next-token;
4683                  next B;                  next B;
4684                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4685                  !!!cp ('t140.1');                  !!!cp ('t140.1');
4686                  !!!parse-error (type => 'unmatched end tag:' . $token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag',
4687                                    text => $token->{tag_name}, token => $token);
4688                  ## Ignore the token                  ## Ignore the token
4689                  !!!next-token;                  !!!next-token;
4690                  next B;                  next B;
# Line 4566  sub _tree_construction_main ($) { Line 4693  sub _tree_construction_main ($) {
4693                }                }
4694              } elsif ($token->{tag_name} eq 'p') {              } elsif ($token->{tag_name} eq 'p') {
4695                !!!cp ('t142');                !!!cp ('t142');
4696                !!!parse-error (type => 'unmatched end tag:p', token => $token);                !!!parse-error (type => 'unmatched end tag',
4697                                  text => $token->{tag_name}, token => $token);
4698                ## Ignore the token                ## Ignore the token
4699                !!!next-token;                !!!next-token;
4700                next B;                next B;
# Line 4589  sub _tree_construction_main ($) { Line 4717  sub _tree_construction_main ($) {
4717                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4718                  !!!cp ('t143.3');                  !!!cp ('t143.3');
4719                  ## ISSUE: Two parse errors for <head><noscript></br>                  ## ISSUE: Two parse errors for <head><noscript></br>
4720                  !!!parse-error (type => 'unmatched end tag:br', token => $token);                  !!!parse-error (type => 'unmatched end tag',
4721                                    text => 'br', token => $token);
4722                  ## As if </noscript>                  ## As if </noscript>
4723                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4724                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
# Line 4608  sub _tree_construction_main ($) { Line 4737  sub _tree_construction_main ($) {
4737                }                }
4738    
4739                ## ISSUE: does not agree with IE7 - it doesn't ignore </br>.                ## ISSUE: does not agree with IE7 - it doesn't ignore </br>.
4740                !!!parse-error (type => 'unmatched end tag:br', token => $token);                !!!parse-error (type => 'unmatched end tag',
4741                                  text => 'br', token => $token);
4742                ## Ignore the token                ## Ignore the token
4743                !!!next-token;                !!!next-token;
4744                next B;                next B;
4745              } else {              } else {
4746                !!!cp ('t145');                !!!cp ('t145');
4747                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                !!!parse-error (type => 'unmatched end tag',
4748                                  text => $token->{tag_name}, token => $token);
4749                ## Ignore the token                ## Ignore the token
4750                !!!next-token;                !!!next-token;
4751                next B;                next B;
# Line 4624  sub _tree_construction_main ($) { Line 4755  sub _tree_construction_main ($) {
4755                !!!cp ('t146');                !!!cp ('t146');
4756                ## As if </noscript>                ## As if </noscript>
4757                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
4758                !!!parse-error (type => 'in noscript:/'.$token->{tag_name}, token => $token);                !!!parse-error (type => 'in noscript:/',
4759                                  text => $token->{tag_name}, token => $token);
4760                                
4761                ## Reprocess in the "in head" insertion mode...                ## Reprocess in the "in head" insertion mode...
4762                ## As if </head>                ## As if </head>
# Line 4640  sub _tree_construction_main ($) { Line 4772  sub _tree_construction_main ($) {
4772              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4773  ## ISSUE: This case cannot be reached?  ## ISSUE: This case cannot be reached?
4774                !!!cp ('t148');                !!!cp ('t148');
4775                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                !!!parse-error (type => 'unmatched end tag',
4776                                  text => $token->{tag_name}, token => $token);
4777                ## Ignore the token ## ISSUE: An issue in the spec.                ## Ignore the token ## ISSUE: An issue in the spec.
4778                !!!next-token;                !!!next-token;
4779                next B;                next B;
# Line 4751  sub _tree_construction_main ($) { Line 4884  sub _tree_construction_main ($) {
4884    
4885                  !!!cp ('t153');                  !!!cp ('t153');
4886                  !!!parse-error (type => 'start tag not allowed',                  !!!parse-error (type => 'start tag not allowed',
4887                      value => $token->{tag_name}, token => $token);                      text => $token->{tag_name}, token => $token);
4888                  ## Ignore the token                  ## Ignore the token
4889                  !!!nack ('t153.1');                  !!!nack ('t153.1');
4890                  !!!next-token;                  !!!next-token;
4891                  next B;                  next B;
4892                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {
4893                  !!!parse-error (type => 'not closed:caption', token => $token);                  !!!parse-error (type => 'not closed', text => 'caption',
4894                                    token => $token);
4895                                    
4896                  ## NOTE: As if </caption>.                  ## NOTE: As if </caption>.
4897                  ## have a table element in table scope                  ## have a table element in table scope
# Line 4777  sub _tree_construction_main ($) { Line 4911  sub _tree_construction_main ($) {
4911    
4912                    !!!cp ('t157');                    !!!cp ('t157');
4913                    !!!parse-error (type => 'start tag not allowed',                    !!!parse-error (type => 'start tag not allowed',
4914                                    value => $token->{tag_name}, token => $token);                                    text => $token->{tag_name}, token => $token);
4915                    ## Ignore the token                    ## Ignore the token
4916                    !!!nack ('t157.1');                    !!!nack ('t157.1');
4917                    !!!next-token;                    !!!next-token;
# Line 4794  sub _tree_construction_main ($) { Line 4928  sub _tree_construction_main ($) {
4928                  unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {                  unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {
4929                    !!!cp ('t159');                    !!!cp ('t159');
4930                    !!!parse-error (type => 'not closed',                    !!!parse-error (type => 'not closed',
4931                                    value => $self->{open_elements}->[-1]->[0]                                    text => $self->{open_elements}->[-1]->[0]
4932                                        ->manakai_local_name,                                        ->manakai_local_name,
4933                                    token => $token);                                    token => $token);
4934                  } else {                  } else {
# Line 4836  sub _tree_construction_main ($) { Line 4970  sub _tree_construction_main ($) {
4970                  } # INSCOPE                  } # INSCOPE
4971                    unless (defined $i) {                    unless (defined $i) {
4972                      !!!cp ('t165');                      !!!cp ('t165');
4973                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                      !!!parse-error (type => 'unmatched end tag',
4974                                        text => $token->{tag_name},
4975                                        token => $token);
4976                      ## Ignore the token                      ## Ignore the token
4977                      !!!next-token;                      !!!next-token;
4978                      next B;                      next B;
# Line 4853  sub _tree_construction_main ($) { Line 4989  sub _tree_construction_main ($) {
4989                          ne $token->{tag_name}) {                          ne $token->{tag_name}) {
4990                    !!!cp ('t167');                    !!!cp ('t167');
4991                    !!!parse-error (type => 'not closed',                    !!!parse-error (type => 'not closed',
4992                                    value => $self->{open_elements}->[-1]->[0]                                    text => $self->{open_elements}->[-1]->[0]
4993                                        ->manakai_local_name,                                        ->manakai_local_name,
4994                                    token => $token);                                    token => $token);
4995                  } else {                  } else {
# Line 4870  sub _tree_construction_main ($) { Line 5006  sub _tree_construction_main ($) {
5006                  next B;                  next B;
5007                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {
5008                  !!!cp ('t169');                  !!!cp ('t169');
5009                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag',
5010                                    text => $token->{tag_name}, token => $token);
5011                  ## Ignore the token                  ## Ignore the token
5012                  !!!next-token;                  !!!next-token;
5013                  next B;                  next B;
# Line 4897  sub _tree_construction_main ($) { Line 5034  sub _tree_construction_main ($) {
5034    
5035                    !!!cp ('t173');                    !!!cp ('t173');
5036                    !!!parse-error (type => 'unmatched end tag',                    !!!parse-error (type => 'unmatched end tag',
5037                                    value => $token->{tag_name}, token => $token);                                    text => $token->{tag_name}, token => $token);
5038                    ## Ignore the token                    ## Ignore the token
5039                    !!!next-token;                    !!!next-token;
5040                    next B;                    next B;
# Line 4913  sub _tree_construction_main ($) { Line 5050  sub _tree_construction_main ($) {
5050                  unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {                  unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {
5051                    !!!cp ('t175');                    !!!cp ('t175');
5052                    !!!parse-error (type => 'not closed',                    !!!parse-error (type => 'not closed',
5053                                    value => $self->{open_elements}->[-1]->[0]                                    text => $self->{open_elements}->[-1]->[0]
5054                                        ->manakai_local_name,                                        ->manakai_local_name,
5055                                    token => $token);                                    token => $token);
5056                  } else {                  } else {
# Line 4930  sub _tree_construction_main ($) { Line 5067  sub _tree_construction_main ($) {
5067                  next B;                  next B;
5068                } elsif ($self->{insertion_mode} == IN_CELL_IM) {                } elsif ($self->{insertion_mode} == IN_CELL_IM) {
5069                  !!!cp ('t177');                  !!!cp ('t177');
5070                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag',
5071                                    text => $token->{tag_name}, token => $token);
5072                  ## Ignore the token                  ## Ignore the token
5073                  !!!next-token;                  !!!next-token;
5074                  next B;                  next B;
# Line 4973  sub _tree_construction_main ($) { Line 5111  sub _tree_construction_main ($) {
5111    
5112                  !!!cp ('t182');                  !!!cp ('t182');
5113                  !!!parse-error (type => 'unmatched end tag',                  !!!parse-error (type => 'unmatched end tag',
5114                      value => $token->{tag_name}, token => $token);                      text => $token->{tag_name}, token => $token);
5115                  ## Ignore the token                  ## Ignore the token
5116                  !!!next-token;                  !!!next-token;
5117                  next B;                  next B;
5118                } # INSCOPE                } # INSCOPE
5119              } elsif ($token->{tag_name} eq 'table' and              } elsif ($token->{tag_name} eq 'table' and
5120                       $self->{insertion_mode} == IN_CAPTION_IM) {                       $self->{insertion_mode} == IN_CAPTION_IM) {
5121                !!!parse-error (type => 'not closed:caption', token => $token);                !!!parse-error (type => 'not closed', text => 'caption',
5122                                  token => $token);
5123    
5124                ## As if </caption>                ## As if </caption>
5125                ## have a table element in table scope                ## have a table element in table scope
# Line 4998  sub _tree_construction_main ($) { Line 5137  sub _tree_construction_main ($) {
5137                } # INSCOPE                } # INSCOPE
5138                unless (defined $i) {                unless (defined $i) {
5139                  !!!cp ('t186');                  !!!cp ('t186');
5140                  !!!parse-error (type => 'unmatched end tag:caption', token => $token);                  !!!parse-error (type => 'unmatched end tag',
5141                                    text => 'caption', token => $token);
5142                  ## Ignore the token                  ## Ignore the token
5143                  !!!next-token;                  !!!next-token;
5144                  next B;                  next B;
# Line 5013  sub _tree_construction_main ($) { Line 5153  sub _tree_construction_main ($) {
5153                unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {                unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {
5154                  !!!cp ('t188');                  !!!cp ('t188');
5155                  !!!parse-error (type => 'not closed',                  !!!parse-error (type => 'not closed',
5156                                  value => $self->{open_elements}->[-1]->[0]                                  text => $self->{open_elements}->[-1]->[0]
5157                                      ->manakai_local_name,                                      ->manakai_local_name,
5158                                  token => $token);                                  token => $token);
5159                } else {                } else {
# Line 5033  sub _tree_construction_main ($) { Line 5173  sub _tree_construction_main ($) {
5173                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
5174                if ($self->{insertion_mode} & BODY_TABLE_IMS) {                if ($self->{insertion_mode} & BODY_TABLE_IMS) {
5175                  !!!cp ('t190');                  !!!cp ('t190');
5176                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag',
5177                                    text => $token->{tag_name}, token => $token);
5178                  ## Ignore the token                  ## Ignore the token
5179                  !!!next-token;                  !!!next-token;
5180                  next B;                  next B;
# Line 5047  sub _tree_construction_main ($) { Line 5188  sub _tree_construction_main ($) {
5188                       }->{$token->{tag_name}} and                       }->{$token->{tag_name}} and
5189                       $self->{insertion_mode} == IN_CAPTION_IM) {                       $self->{insertion_mode} == IN_CAPTION_IM) {
5190                !!!cp ('t192');                !!!cp ('t192');
5191                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                !!!parse-error (type => 'unmatched end tag',
5192                                  text => $token->{tag_name}, token => $token);
5193                ## Ignore the token                ## Ignore the token
5194                !!!next-token;                !!!next-token;
5195                next B;                next B;
# Line 5087  sub _tree_construction_main ($) { Line 5229  sub _tree_construction_main ($) {
5229            }            }
5230          }          }
5231    
5232              !!!parse-error (type => 'in table:#character', token => $token);          !!!parse-error (type => 'in table:#text', token => $token);
5233    
5234              ## As if in body, but insert into foster parent element              ## As if in body, but insert into foster parent element
5235              ## ISSUE: Spec says that "whenever a node would be inserted              ## ISSUE: Spec says that "whenever a node would be inserted
# Line 5138  sub _tree_construction_main ($) { Line 5280  sub _tree_construction_main ($) {
5280          !!!next-token;          !!!next-token;
5281          next B;          next B;
5282        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
5283              if ({          if ({
5284                   tr => ($self->{insertion_mode} != IN_ROW_IM),               tr => ($self->{insertion_mode} != IN_ROW_IM),
5285                   th => 1, td => 1,               th => 1, td => 1,
5286                  }->{$token->{tag_name}}) {              }->{$token->{tag_name}}) {
5287                if ($self->{insertion_mode} == IN_TABLE_IM) {            if ($self->{insertion_mode} == IN_TABLE_IM) {
5288                  ## Clear back to table context              ## Clear back to table context
5289                  while (not ($self->{open_elements}->[-1]->[1]              while (not ($self->{open_elements}->[-1]->[1]
5290                                  & TABLE_SCOPING_EL)) {                              & TABLE_SCOPING_EL)) {
5291                    !!!cp ('t201');                !!!cp ('t201');
5292                    pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5293                  }              }
5294                                
5295                  !!!insert-element ('tbody',, $token);              !!!insert-element ('tbody',, $token);
5296                  $self->{insertion_mode} = IN_TABLE_BODY_IM;              $self->{insertion_mode} = IN_TABLE_BODY_IM;
5297                  ## reprocess in the "in table body" insertion mode...              ## reprocess in the "in table body" insertion mode...
5298                }            }
5299              
5300                if ($self->{insertion_mode} == IN_TABLE_BODY_IM) {            if ($self->{insertion_mode} == IN_TABLE_BODY_IM) {
5301                  unless ($token->{tag_name} eq 'tr') {              unless ($token->{tag_name} eq 'tr') {
5302                    !!!cp ('t202');                !!!cp ('t202');
5303                    !!!parse-error (type => 'missing start tag:tr', token => $token);                !!!parse-error (type => 'missing start tag:tr', token => $token);
5304                  }              }
5305                                    
5306                  ## Clear back to table body context              ## Clear back to table body context
5307                  while (not ($self->{open_elements}->[-1]->[1]              while (not ($self->{open_elements}->[-1]->[1]
5308                                  & TABLE_ROWS_SCOPING_EL)) {                              & TABLE_ROWS_SCOPING_EL)) {
5309                    !!!cp ('t203');                !!!cp ('t203');
5310                    ## ISSUE: Can this case be reached?                ## ISSUE: Can this case be reached?
5311                    pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5312                  }              }
5313                                    
5314                  $self->{insertion_mode} = IN_ROW_IM;                  $self->{insertion_mode} = IN_ROW_IM;
5315                  if ($token->{tag_name} eq 'tr') {                  if ($token->{tag_name} eq 'tr') {
# Line 5223  sub _tree_construction_main ($) { Line 5365  sub _tree_construction_main ($) {
5365                  unless (defined $i) {                  unless (defined $i) {
5366                    !!!cp ('t210');                    !!!cp ('t210');
5367  ## TODO: This type is wrong.  ## TODO: This type is wrong.
5368                    !!!parse-error (type => 'unmacthed end tag:'.$token->{tag_name}, token => $token);                    !!!parse-error (type => 'unmacthed end tag',
5369                                      text => $token->{tag_name}, token => $token);
5370                    ## Ignore the token                    ## Ignore the token
5371                    !!!nack ('t210.1');                    !!!nack ('t210.1');
5372                    !!!next-token;                    !!!next-token;
# Line 5267  sub _tree_construction_main ($) { Line 5410  sub _tree_construction_main ($) {
5410                  } # INSCOPE                  } # INSCOPE
5411                  unless (defined $i) {                  unless (defined $i) {
5412                    !!!cp ('t216');                    !!!cp ('t216');
5413  ## TODO: This erorr type ios wrong.  ## TODO: This erorr type is wrong.
5414                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                    !!!parse-error (type => 'unmatched end tag',
5415                                      text => $token->{tag_name}, token => $token);
5416                    ## Ignore the token                    ## Ignore the token
5417                    !!!nack ('t216.1');                    !!!nack ('t216.1');
5418                    !!!next-token;                    !!!next-token;
# Line 5343  sub _tree_construction_main ($) { Line 5487  sub _tree_construction_main ($) {
5487                }                }
5488              } elsif ($token->{tag_name} eq 'table') {              } elsif ($token->{tag_name} eq 'table') {
5489                !!!parse-error (type => 'not closed',                !!!parse-error (type => 'not closed',
5490                                value => $self->{open_elements}->[-1]->[0]                                text => $self->{open_elements}->[-1]->[0]
5491                                    ->manakai_local_name,                                    ->manakai_local_name,
5492                                token => $token);                                token => $token);
5493    
# Line 5364  sub _tree_construction_main ($) { Line 5508  sub _tree_construction_main ($) {
5508                unless (defined $i) {                unless (defined $i) {
5509                  !!!cp ('t223');                  !!!cp ('t223');
5510  ## TODO: The following is wrong, maybe.  ## TODO: The following is wrong, maybe.
5511                  !!!parse-error (type => 'unmatched end tag:table', token => $token);                  !!!parse-error (type => 'unmatched end tag', text => 'table',
5512                                    token => $token);
5513                  ## Ignore tokens </table><table>                  ## Ignore tokens </table><table>
5514                  !!!nack ('t223.1');                  !!!nack ('t223.1');
5515                  !!!next-token;                  !!!next-token;
5516                  next B;                  next B;
5517                }                }
5518                                
5519  ## TODO: Followings are removed from the latest spec.  ## TODO: Followings are removed from the latest spec.
5520                ## generate implied end tags                ## generate implied end tags
5521                while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {                while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
5522                  !!!cp ('t224');                  !!!cp ('t224');
# Line 5382  sub _tree_construction_main ($) { Line 5527  sub _tree_construction_main ($) {
5527                  !!!cp ('t225');                  !!!cp ('t225');
5528                  ## NOTE: |<table><tr><table>|                  ## NOTE: |<table><tr><table>|
5529                  !!!parse-error (type => 'not closed',                  !!!parse-error (type => 'not closed',
5530                                  value => $self->{open_elements}->[-1]->[0]                                  text => $self->{open_elements}->[-1]->[0]
5531                                      ->manakai_local_name,                                      ->manakai_local_name,
5532                                  token => $token);                                  token => $token);
5533                } else {                } else {
# Line 5423  sub _tree_construction_main ($) { Line 5568  sub _tree_construction_main ($) {
5568                my $type = lc $token->{attributes}->{type}->{value};                my $type = lc $token->{attributes}->{type}->{value};
5569                if ($type eq 'hidden') {                if ($type eq 'hidden') {
5570                  !!!cp ('t227.3');                  !!!cp ('t227.3');
5571                  !!!parse-error (type => 'in table:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'in table',
5572                                    text => $token->{tag_name}, token => $token);
5573    
5574                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5575    
# Line 5451  sub _tree_construction_main ($) { Line 5597  sub _tree_construction_main ($) {
5597            #            #
5598          }          }
5599    
5600          !!!parse-error (type => 'in table:'.$token->{tag_name}, token => $token);          !!!parse-error (type => 'in table', text => $token->{tag_name},
5601                            token => $token);
5602    
5603          $insert = $insert_to_foster;          $insert = $insert_to_foster;
5604          #          #
# Line 5473  sub _tree_construction_main ($) { Line 5620  sub _tree_construction_main ($) {
5620                } # INSCOPE                } # INSCOPE
5621                unless (defined $i) {                unless (defined $i) {
5622                  !!!cp ('t230');                  !!!cp ('t230');
5623                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag',
5624                                    text => $token->{tag_name}, token => $token);
5625                  ## Ignore the token                  ## Ignore the token
5626                  !!!nack ('t230.1');                  !!!nack ('t230.1');
5627                  !!!next-token;                  !!!next-token;
# Line 5514  sub _tree_construction_main ($) { Line 5662  sub _tree_construction_main ($) {
5662                  unless (defined $i) {                  unless (defined $i) {
5663                    !!!cp ('t235');                    !!!cp ('t235');
5664  ## TODO: The following is wrong.  ## TODO: The following is wrong.
5665                    !!!parse-error (type => 'unmatched end tag:'.$token->{type}, token => $token);                    !!!parse-error (type => 'unmatched end tag',
5666                                      text => $token->{type}, token => $token);
5667                    ## Ignore the token                    ## Ignore the token
5668                    !!!nack ('t236.1');                    !!!nack ('t236.1');
5669                    !!!next-token;                    !!!next-token;
# Line 5550  sub _tree_construction_main ($) { Line 5699  sub _tree_construction_main ($) {
5699                  } # INSCOPE                  } # INSCOPE
5700                  unless (defined $i) {                  unless (defined $i) {
5701                    !!!cp ('t239');                    !!!cp ('t239');
5702                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                    !!!parse-error (type => 'unmatched end tag',
5703                                      text => $token->{tag_name}, token => $token);
5704                    ## Ignore the token                    ## Ignore the token
5705                    !!!nack ('t239.1');                    !!!nack ('t239.1');
5706                    !!!next-token;                    !!!next-token;
# Line 5596  sub _tree_construction_main ($) { Line 5746  sub _tree_construction_main ($) {
5746                } # INSCOPE                } # INSCOPE
5747                unless (defined $i) {                unless (defined $i) {
5748                  !!!cp ('t243');                  !!!cp ('t243');
5749                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag',
5750                                    text => $token->{tag_name}, token => $token);
5751                  ## Ignore the token                  ## Ignore the token
5752                  !!!nack ('t243.1');                  !!!nack ('t243.1');
5753                  !!!next-token;                  !!!next-token;
# Line 5630  sub _tree_construction_main ($) { Line 5781  sub _tree_construction_main ($) {
5781                  } # INSCOPE                  } # INSCOPE
5782                    unless (defined $i) {                    unless (defined $i) {
5783                      !!!cp ('t249');                      !!!cp ('t249');
5784                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                      !!!parse-error (type => 'unmatched end tag',
5785                                        text => $token->{tag_name}, token => $token);
5786                      ## Ignore the token                      ## Ignore the token
5787                      !!!nack ('t249.1');                      !!!nack ('t249.1');
5788                      !!!next-token;                      !!!next-token;
# Line 5653  sub _tree_construction_main ($) { Line 5805  sub _tree_construction_main ($) {
5805                  } # INSCOPE                  } # INSCOPE
5806                    unless (defined $i) {                    unless (defined $i) {
5807                      !!!cp ('t252');                      !!!cp ('t252');
5808                      !!!parse-error (type => 'unmatched end tag:tr', token => $token);                      !!!parse-error (type => 'unmatched end tag',
5809                                        text => 'tr', token => $token);
5810                      ## Ignore the token                      ## Ignore the token
5811                      !!!nack ('t252.1');                      !!!nack ('t252.1');
5812                      !!!next-token;                      !!!next-token;
# Line 5688  sub _tree_construction_main ($) { Line 5841  sub _tree_construction_main ($) {
5841                } # INSCOPE                } # INSCOPE
5842                unless (defined $i) {                unless (defined $i) {
5843                  !!!cp ('t256');                  !!!cp ('t256');
5844                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag',
5845                                    text => $token->{tag_name}, token => $token);
5846                  ## Ignore the token                  ## Ignore the token
5847                  !!!nack ('t256.1');                  !!!nack ('t256.1');
5848                  !!!next-token;                  !!!next-token;
# Line 5715  sub _tree_construction_main ($) { Line 5869  sub _tree_construction_main ($) {
5869                        tbody => 1, tfoot => 1, thead => 1, # $self->{insertion_mode} == IN_TABLE_IM                        tbody => 1, tfoot => 1, thead => 1, # $self->{insertion_mode} == IN_TABLE_IM
5870                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
5871            !!!cp ('t258');            !!!cp ('t258');
5872            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag',
5873                              text => $token->{tag_name}, token => $token);
5874            ## Ignore the token            ## Ignore the token
5875            !!!nack ('t258.1');            !!!nack ('t258.1');
5876             !!!next-token;             !!!next-token;
5877            next B;            next B;
5878          } else {          } else {
5879            !!!cp ('t259');            !!!cp ('t259');
5880            !!!parse-error (type => 'in table:/'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'in table:/',
5881                              text => $token->{tag_name}, token => $token);
5882    
5883            $insert = $insert_to_foster;            $insert = $insert_to_foster;
5884            #            #
# Line 5772  sub _tree_construction_main ($) { Line 5928  sub _tree_construction_main ($) {
5928              if ($token->{tag_name} eq 'colgroup') {              if ($token->{tag_name} eq 'colgroup') {
5929                if ($self->{open_elements}->[-1]->[1] & HTML_EL) {                if ($self->{open_elements}->[-1]->[1] & HTML_EL) {
5930                  !!!cp ('t264');                  !!!cp ('t264');
5931                  !!!parse-error (type => 'unmatched end tag:colgroup', token => $token);                  !!!parse-error (type => 'unmatched end tag',
5932                                    text => 'colgroup', token => $token);
5933                  ## Ignore the token                  ## Ignore the token
5934                  !!!next-token;                  !!!next-token;
5935                  next B;                  next B;
# Line 5785  sub _tree_construction_main ($) { Line 5942  sub _tree_construction_main ($) {
5942                }                }
5943              } elsif ($token->{tag_name} eq 'col') {              } elsif ($token->{tag_name} eq 'col') {
5944                !!!cp ('t266');                !!!cp ('t266');
5945                !!!parse-error (type => 'unmatched end tag:col', token => $token);                !!!parse-error (type => 'unmatched end tag',
5946                                  text => 'col', token => $token);
5947                ## Ignore the token                ## Ignore the token
5948                !!!next-token;                !!!next-token;
5949                next B;                next B;
# Line 5815  sub _tree_construction_main ($) { Line 5973  sub _tree_construction_main ($) {
5973            if ($self->{open_elements}->[-1]->[1] & HTML_EL) {            if ($self->{open_elements}->[-1]->[1] & HTML_EL) {
5974              !!!cp ('t269');              !!!cp ('t269');
5975  ## TODO: Wrong error type?  ## TODO: Wrong error type?
5976              !!!parse-error (type => 'unmatched end tag:colgroup', token => $token);              !!!parse-error (type => 'unmatched end tag',
5977                                text => 'colgroup', token => $token);
5978              ## Ignore the token              ## Ignore the token
5979              !!!nack ('t269.1');              !!!nack ('t269.1');
5980              !!!next-token;              !!!next-token;
# Line 5869  sub _tree_construction_main ($) { Line 6028  sub _tree_construction_main ($) {
6028            !!!nack ('t277.1');            !!!nack ('t277.1');
6029            !!!next-token;            !!!next-token;
6030            next B;            next B;
6031          } elsif ($token->{tag_name} eq 'select' or          } elsif ({
6032                   $token->{tag_name} eq 'input' or                     select => 1, input => 1, textarea => 1,
6033                     }->{$token->{tag_name}} or
6034                   ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and                   ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and
6035                    {                    {
6036                     caption => 1, table => 1,                     caption => 1, table => 1,
# Line 5878  sub _tree_construction_main ($) { Line 6038  sub _tree_construction_main ($) {
6038                     tr => 1, td => 1, th => 1,                     tr => 1, td => 1, th => 1,
6039                    }->{$token->{tag_name}})) {                    }->{$token->{tag_name}})) {
6040            ## TODO: The type below is not good - <select> is replaced by </select>            ## TODO: The type below is not good - <select> is replaced by </select>
6041            !!!parse-error (type => 'not closed:select', token => $token);            !!!parse-error (type => 'not closed', text => 'select',
6042                              token => $token);
6043            ## NOTE: As if the token were </select> (<select> case) or            ## NOTE: As if the token were </select> (<select> case) or
6044            ## as if there were </select> (otherwise).            ## as if there were </select> (otherwise).
6045            ## have an element in table scope            ## have an element in table scope
# Line 5896  sub _tree_construction_main ($) { Line 6057  sub _tree_construction_main ($) {
6057            } # INSCOPE            } # INSCOPE
6058            unless (defined $i) {            unless (defined $i) {
6059              !!!cp ('t280');              !!!cp ('t280');
6060              !!!parse-error (type => 'unmatched end tag:select', token => $token);              !!!parse-error (type => 'unmatched end tag',
6061                                text => 'select', token => $token);
6062              ## Ignore the token              ## Ignore the token
6063              !!!nack ('t280.1');              !!!nack ('t280.1');
6064              !!!next-token;              !!!next-token;
# Line 5920  sub _tree_construction_main ($) { Line 6082  sub _tree_construction_main ($) {
6082            }            }
6083          } else {          } else {
6084            !!!cp ('t282');            !!!cp ('t282');
6085            !!!parse-error (type => 'in select:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'in select',
6086                              text => $token->{tag_name}, token => $token);
6087            ## Ignore the token            ## Ignore the token
6088            !!!nack ('t282.1');            !!!nack ('t282.1');
6089            !!!next-token;            !!!next-token;
# Line 5938  sub _tree_construction_main ($) { Line 6101  sub _tree_construction_main ($) {
6101              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
6102            } else {            } else {
6103              !!!cp ('t285');              !!!cp ('t285');
6104              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'unmatched end tag',
6105                                text => $token->{tag_name}, token => $token);
6106              ## Ignore the token              ## Ignore the token
6107            }            }
6108            !!!nack ('t285.1');            !!!nack ('t285.1');
# Line 5950  sub _tree_construction_main ($) { Line 6114  sub _tree_construction_main ($) {
6114              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
6115            } else {            } else {
6116              !!!cp ('t287');              !!!cp ('t287');
6117              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'unmatched end tag',
6118                                text => $token->{tag_name}, token => $token);
6119              ## Ignore the token              ## Ignore the token
6120            }            }
6121            !!!nack ('t287.1');            !!!nack ('t287.1');
# Line 5972  sub _tree_construction_main ($) { Line 6137  sub _tree_construction_main ($) {
6137            } # INSCOPE            } # INSCOPE
6138            unless (defined $i) {            unless (defined $i) {
6139              !!!cp ('t290');              !!!cp ('t290');
6140              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'unmatched end tag',
6141                                text => $token->{tag_name}, token => $token);
6142              ## Ignore the token              ## Ignore the token
6143              !!!nack ('t290.1');              !!!nack ('t290.1');
6144              !!!next-token;              !!!next-token;
# Line 5993  sub _tree_construction_main ($) { Line 6159  sub _tree_construction_main ($) {
6159                    tfoot => 1, thead => 1, tr => 1, td => 1, th => 1,                    tfoot => 1, thead => 1, tr => 1, td => 1, th => 1,
6160                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
6161  ## TODO: The following is wrong?  ## TODO: The following is wrong?
6162            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag',
6163                              text => $token->{tag_name}, token => $token);
6164                                
6165            ## have an element in table scope            ## have an element in table scope
6166            my $i;            my $i;
# Line 6034  sub _tree_construction_main ($) { Line 6201  sub _tree_construction_main ($) {
6201            unless (defined $i) {            unless (defined $i) {
6202              !!!cp ('t297');              !!!cp ('t297');
6203  ## TODO: The following error type is correct?  ## TODO: The following error type is correct?
6204              !!!parse-error (type => 'unmatched end tag:select', token => $token);              !!!parse-error (type => 'unmatched end tag',
6205                                text => 'select', token => $token);
6206              ## Ignore the </select> token              ## Ignore the </select> token
6207              !!!nack ('t297.1');              !!!nack ('t297.1');
6208              !!!next-token; ## TODO: ok?              !!!next-token; ## TODO: ok?
# Line 6051  sub _tree_construction_main ($) { Line 6219  sub _tree_construction_main ($) {
6219            next B;            next B;
6220          } else {          } else {
6221            !!!cp ('t299');            !!!cp ('t299');
6222            !!!parse-error (type => 'in select:/'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'in select:/',
6223                              text => $token->{tag_name}, token => $token);
6224            ## Ignore the token            ## Ignore the token
6225            !!!nack ('t299.3');            !!!nack ('t299.3');
6226            !!!next-token;            !!!next-token;
# Line 6089  sub _tree_construction_main ($) { Line 6258  sub _tree_construction_main ($) {
6258                    
6259          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
6260            !!!cp ('t301');            !!!cp ('t301');
6261            !!!parse-error (type => 'after html:#character', token => $token);            !!!parse-error (type => 'after html:#text', token => $token);
6262    
6263            ## Reprocess in the "after body" insertion mode.            ## Reprocess in the "after body" insertion mode.
6264          } else {          } else {
# Line 6097  sub _tree_construction_main ($) { Line 6266  sub _tree_construction_main ($) {
6266          }          }
6267                    
6268          ## "after body" insertion mode          ## "after body" insertion mode
6269          !!!parse-error (type => 'after body:#character', token => $token);          !!!parse-error (type => 'after body:#text', token => $token);
6270    
6271          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
6272          ## reprocess          ## reprocess
# Line 6105  sub _tree_construction_main ($) { Line 6274  sub _tree_construction_main ($) {
6274        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
6275          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
6276            !!!cp ('t303');            !!!cp ('t303');
6277            !!!parse-error (type => 'after html:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'after html',
6278                              text => $token->{tag_name}, token => $token);
6279                        
6280            ## Reprocess in the "after body" insertion mode.            ## Reprocess in the "after body" insertion mode.
6281          } else {          } else {
# Line 6113  sub _tree_construction_main ($) { Line 6283  sub _tree_construction_main ($) {
6283          }          }
6284    
6285          ## "after body" insertion mode          ## "after body" insertion mode
6286          !!!parse-error (type => 'after body:'.$token->{tag_name}, token => $token);          !!!parse-error (type => 'after body',
6287                            text => $token->{tag_name}, token => $token);
6288    
6289          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
6290          !!!ack-later;          !!!ack-later;
# Line 6122  sub _tree_construction_main ($) { Line 6293  sub _tree_construction_main ($) {
6293        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
6294          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
6295            !!!cp ('t305');            !!!cp ('t305');
6296            !!!parse-error (type => 'after html:/'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'after html:/',
6297                              text => $token->{tag_name}, token => $token);
6298                        
6299            $self->{insertion_mode} = AFTER_BODY_IM;            $self->{insertion_mode} = AFTER_BODY_IM;
6300            ## Reprocess in the "after body" insertion mode.            ## Reprocess in the "after body" insertion mode.
# Line 6134  sub _tree_construction_main ($) { Line 6306  sub _tree_construction_main ($) {
6306          if ($token->{tag_name} eq 'html') {          if ($token->{tag_name} eq 'html') {
6307            if (defined $self->{inner_html_node}) {            if (defined $self->{inner_html_node}) {
6308              !!!cp ('t307');              !!!cp ('t307');
6309              !!!parse-error (type => 'unmatched end tag:html', token => $token);              !!!parse-error (type => 'unmatched end tag',
6310                                text => 'html', token => $token);
6311              ## Ignore the token              ## Ignore the token
6312              !!!next-token;              !!!next-token;
6313              next B;              next B;
# Line 6146  sub _tree_construction_main ($) { Line 6319  sub _tree_construction_main ($) {
6319            }            }
6320          } else {          } else {
6321            !!!cp ('t309');            !!!cp ('t309');
6322            !!!parse-error (type => 'after body:/'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'after body:/',
6323                              text => $token->{tag_name}, token => $token);
6324    
6325            $self->{insertion_mode} = IN_BODY_IM;            $self->{insertion_mode} = IN_BODY_IM;
6326            ## reprocess            ## reprocess
# Line 6174  sub _tree_construction_main ($) { Line 6348  sub _tree_construction_main ($) {
6348          if ($token->{data} =~ s/^[^\x09\x0A\x0B\x0C\x20]+//) {          if ($token->{data} =~ s/^[^\x09\x0A\x0B\x0C\x20]+//) {
6349            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
6350              !!!cp ('t311');              !!!cp ('t311');
6351              !!!parse-error (type => 'in frameset:#character', token => $token);              !!!parse-error (type => 'in frameset:#text', token => $token);
6352            } elsif ($self->{insertion_mode} == AFTER_FRAMESET_IM) {            } elsif ($self->{insertion_mode} == AFTER_FRAMESET_IM) {
6353              !!!cp ('t312');              !!!cp ('t312');
6354              !!!parse-error (type => 'after frameset:#character', token => $token);              !!!parse-error (type => 'after frameset:#text', token => $token);
6355            } else { # "after html frameset"            } else { # "after after frameset"
6356              !!!cp ('t313');              !!!cp ('t313');
6357              !!!parse-error (type => 'after html:#character', token => $token);              !!!parse-error (type => 'after html:#text', token => $token);
   
             $self->{insertion_mode} = AFTER_FRAMESET_IM;  
             ## Reprocess in the "after frameset" insertion mode.  
             !!!parse-error (type => 'after frameset:#character', token => $token);  
6358            }            }
6359                        
6360            ## Ignore the token.            ## Ignore the token.
# Line 6200  sub _tree_construction_main ($) { Line 6370  sub _tree_construction_main ($) {
6370                    
6371          die qq[$0: Character "$token->{data}"];          die qq[$0: Character "$token->{data}"];
6372        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
         if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {  
           !!!cp ('t316');  
           !!!parse-error (type => 'after html:'.$token->{tag_name}, token => $token);  
   
           $self->{insertion_mode} = AFTER_FRAMESET_IM;  
           ## Process in the "after frameset" insertion mode.  
         } else {  
           !!!cp ('t317');  
         }  
   
6373          if ($token->{tag_name} eq 'frameset' and          if ($token->{tag_name} eq 'frameset' and
6374              $self->{insertion_mode} == IN_FRAMESET_IM) {              $self->{insertion_mode} == IN_FRAMESET_IM) {
6375            !!!cp ('t318');            !!!cp ('t318');
# Line 6227  sub _tree_construction_main ($) { Line 6387  sub _tree_construction_main ($) {
6387            next B;            next B;
6388          } elsif ($token->{tag_name} eq 'noframes') {          } elsif ($token->{tag_name} eq 'noframes') {
6389            !!!cp ('t320');            !!!cp ('t320');
6390            ## NOTE: As if in body.            ## NOTE: As if in head.
6391            $parse_rcdata->(CDATA_CONTENT_MODEL);            $parse_rcdata->(CDATA_CONTENT_MODEL);
6392            next B;            next B;
6393    
6394              ## NOTE: |<!DOCTYPE HTML><frameset></frameset></html><noframes></noframes>|
6395              ## has no parse error.
6396          } else {          } else {
6397            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
6398              !!!cp ('t321');              !!!cp ('t321');
6399              !!!parse-error (type => 'in frameset:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'in frameset',
6400            } else {                              text => $token->{tag_name}, token => $token);
6401              } elsif ($self->{insertion_mode} == AFTER_FRAMESET_IM) {
6402              !!!cp ('t322');              !!!cp ('t322');
6403              !!!parse-error (type => 'after frameset:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'after frameset',
6404                                text => $token->{tag_name}, token => $token);
6405              } else { # "after after frameset"
6406                !!!cp ('t322.2');
6407                !!!parse-error (type => 'after after frameset',
6408                                text => $token->{tag_name}, token => $token);
6409            }            }
6410            ## Ignore the token            ## Ignore the token
6411            !!!nack ('t322.1');            !!!nack ('t322.1');
# Line 6244  sub _tree_construction_main ($) { Line 6413  sub _tree_construction_main ($) {
6413            next B;            next B;
6414          }          }
6415        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
         if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {  
           !!!cp ('t323');  
           !!!parse-error (type => 'after html:/'.$token->{tag_name}, token => $token);  
   
           $self->{insertion_mode} = AFTER_FRAMESET_IM;  
           ## Process in the "after frameset" insertion mode.  
         } else {  
           !!!cp ('t324');  
         }  
   
6416          if ($token->{tag_name} eq 'frameset' and          if ($token->{tag_name} eq 'frameset' and
6417              $self->{insertion_mode} == IN_FRAMESET_IM) {              $self->{insertion_mode} == IN_FRAMESET_IM) {
6418            if ($self->{open_elements}->[-1]->[1] & HTML_EL and            if ($self->{open_elements}->[-1]->[1] & HTML_EL and
6419                @{$self->{open_elements}} == 1) {                @{$self->{open_elements}} == 1) {
6420              !!!cp ('t325');              !!!cp ('t325');
6421              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'unmatched end tag',
6422                                text => $token->{tag_name}, token => $token);
6423              ## Ignore the token              ## Ignore the token
6424              !!!next-token;              !!!next-token;
6425            } else {            } else {
# Line 6285  sub _tree_construction_main ($) { Line 6445  sub _tree_construction_main ($) {
6445          } else {          } else {
6446            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
6447              !!!cp ('t330');              !!!cp ('t330');
6448              !!!parse-error (type => 'in frameset:/'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'in frameset:/',
6449            } else {                              text => $token->{tag_name}, token => $token);
6450              } elsif ($self->{insertion_mode} == AFTER_FRAMESET_IM) {
6451                !!!cp ('t330.1');
6452                !!!parse-error (type => 'after frameset:/',
6453                                text => $token->{tag_name}, token => $token);
6454              } else { # "after after html"
6455              !!!cp ('t331');              !!!cp ('t331');
6456              !!!parse-error (type => 'after frameset:/'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'after after frameset:/',
6457                                text => $token->{tag_name}, token => $token);
6458            }            }
6459            ## Ignore the token            ## Ignore the token
6460            !!!next-token;            !!!next-token;
# Line 6396  sub _tree_construction_main ($) { Line 6562  sub _tree_construction_main ($) {
6562          $parse_rcdata->(RCDATA_CONTENT_MODEL);          $parse_rcdata->(RCDATA_CONTENT_MODEL);
6563          next B;          next B;
6564        } elsif ($token->{tag_name} eq 'body') {        } elsif ($token->{tag_name} eq 'body') {
6565          !!!parse-error (type => 'in body:body', token => $token);          !!!parse-error (type => 'in body', text => 'body', token => $token);
6566                                
6567          if (@{$self->{open_elements}} == 1 or          if (@{$self->{open_elements}} == 1 or
6568              not ($self->{open_elements}->[1]->[1] & BODY_EL)) {              not ($self->{open_elements}->[1]->[1] & BODY_EL)) {
# Line 6516  sub _tree_construction_main ($) { Line 6682  sub _tree_construction_main ($) {
6682              if ($i != -1) {              if ($i != -1) {
6683                !!!cp ('t355');                !!!cp ('t355');
6684                !!!parse-error (type => 'not closed',                !!!parse-error (type => 'not closed',
6685                                value => $self->{open_elements}->[-1]->[0]                                text => $self->{open_elements}->[-1]->[0]
6686                                    ->manakai_local_name,                                    ->manakai_local_name,
6687                                token => $token);                                token => $token);
6688              } else {              } else {
# Line 6670  sub _tree_construction_main ($) { Line 6836  sub _tree_construction_main ($) {
6836                  xmp => 1,                  xmp => 1,
6837                  iframe => 1,                  iframe => 1,
6838                  noembed => 1,                  noembed => 1,
6839                  noframes => 1,                  noframes => 1, ## NOTE: This is an "as if in head" code clone.
6840                  noscript => 0, ## TODO: 1 if scripting is enabled                  noscript => 0, ## TODO: 1 if scripting is enabled
6841                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
6842          if ($token->{tag_name} eq 'xmp') {          if ($token->{tag_name} eq 'xmp') {
# Line 6692  sub _tree_construction_main ($) { Line 6858  sub _tree_construction_main ($) {
6858            !!!next-token;            !!!next-token;
6859            next B;            next B;
6860          } else {          } else {
6861              !!!ack ('t391.1');
6862    
6863            my $at = $token->{attributes};            my $at = $token->{attributes};
6864            my $form_attrs;            my $form_attrs;
6865            $form_attrs->{action} = $at->{action} if $at->{action};            $form_attrs->{action} = $at->{action} if $at->{action};
# Line 6735  sub _tree_construction_main ($) { Line 6903  sub _tree_construction_main ($) {
6903                           line => $token->{line}, column => $token->{column}},                           line => $token->{line}, column => $token->{column}},
6904                          {type => END_TAG_TOKEN, tag_name => 'form',                          {type => END_TAG_TOKEN, tag_name => 'form',
6905                           line => $token->{line}, column => $token->{column}};                           line => $token->{line}, column => $token->{column}};
           !!!nack ('t391.1'); ## NOTE: Not acknowledged.  
6906            !!!back-token (@tokens);            !!!back-token (@tokens);
6907            !!!next-token;            !!!next-token;
6908            next B;            next B;
# Line 6783  sub _tree_construction_main ($) { Line 6950  sub _tree_construction_main ($) {
6950            ## Ignore the token            ## Ignore the token
6951          } else {          } else {
6952            !!!cp ('t398');            !!!cp ('t398');
6953            !!!parse-error (type => 'in RCDATA:#'.$token->{type}, token => $token);            !!!parse-error (type => 'in RCDATA:#eof', token => $token);
6954          }          }
6955          !!!next-token;          !!!next-token;
6956          next B;          next B;
6957          } elsif ($token->{tag_name} eq 'rt' or
6958                   $token->{tag_name} eq 'rp') {
6959            ## has a |ruby| element in scope
6960            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6961              my $node = $self->{open_elements}->[$_];
6962              if ($node->[1] & RUBY_EL) {
6963                !!!cp ('t398.1');
6964                ## generate implied end tags
6965                while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
6966                  !!!cp ('t398.2');
6967                  pop @{$self->{open_elements}};
6968                }
6969                unless ($self->{open_elements}->[-1]->[1] & RUBY_EL) {
6970                  !!!cp ('t398.3');
6971                  !!!parse-error (type => 'not closed',
6972                                  text => $self->{open_elements}->[-1]->[0]
6973                                      ->manakai_local_name,
6974                                  token => $token);
6975                  pop @{$self->{open_elements}}
6976                      while not $self->{open_elements}->[-1]->[1] & RUBY_EL;
6977                }
6978                last INSCOPE;
6979              } elsif ($node->[1] & SCOPING_EL) {
6980                !!!cp ('t398.4');
6981                last INSCOPE;
6982              }
6983            } # INSCOPE
6984    
6985            !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6986    
6987            !!!nack ('t398.5');
6988            !!!next-token;
6989            redo B;
6990        } elsif ($token->{tag_name} eq 'math' or        } elsif ($token->{tag_name} eq 'math' or
6991                 $token->{tag_name} eq 'svg') {                 $token->{tag_name} eq 'svg') {
6992          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
6993    
6994            ## "Adjust MathML attributes" ('math' only) - done in insert-element-f
6995    
6996          ## "adjust SVG attributes" ('svg' only) - done in insert-element-f          ## "adjust SVG attributes" ('svg' only) - done in insert-element-f
6997    
6998          ## "adjust foreign attributes" - done in insert-element-f          ## "adjust foreign attributes" - done in insert-element-f
# Line 6817  sub _tree_construction_main ($) { Line 7019  sub _tree_construction_main ($) {
7019                  thead => 1, tr => 1,                  thead => 1, tr => 1,
7020                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7021          !!!cp ('t401');          !!!cp ('t401');
7022          !!!parse-error (type => 'in body:'.$token->{tag_name}, token => $token);          !!!parse-error (type => 'in body',
7023                            text => $token->{tag_name}, token => $token);
7024          ## Ignore the token          ## Ignore the token
7025          !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.          !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.
7026          !!!next-token;          !!!next-token;
# Line 6902  sub _tree_construction_main ($) { Line 7105  sub _tree_construction_main ($) {
7105            }            }
7106    
7107            !!!parse-error (type => 'start tag not allowed',            !!!parse-error (type => 'start tag not allowed',
7108                            value => $token->{tag_name}, token => $token);                            text => $token->{tag_name}, token => $token);
7109            ## NOTE: Ignore the token.            ## NOTE: Ignore the token.
7110            !!!next-token;            !!!next-token;
7111            next B;            next B;
# Line 6912  sub _tree_construction_main ($) { Line 7115  sub _tree_construction_main ($) {
7115            unless ($_->[1] & ALL_END_TAG_OPTIONAL_EL) {            unless ($_->[1] & ALL_END_TAG_OPTIONAL_EL) {
7116              !!!cp ('t403');              !!!cp ('t403');
7117              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
7118                              value => $_->[0]->manakai_local_name,                              text => $_->[0]->manakai_local_name,
7119                              token => $token);                              token => $token);
7120              last;              last;
7121            } else {            } else {
# Line 6932  sub _tree_construction_main ($) { Line 7135  sub _tree_construction_main ($) {
7135            unless ($self->{open_elements}->[-1]->[1] & BODY_EL) {            unless ($self->{open_elements}->[-1]->[1] & BODY_EL) {
7136              !!!cp ('t406');              !!!cp ('t406');
7137              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
7138                              value => $self->{open_elements}->[1]->[0]                              text => $self->{open_elements}->[1]->[0]
7139                                  ->manakai_local_name,                                  ->manakai_local_name,
7140                              token => $token);                              token => $token);
7141            } else {            } else {
# Line 6943  sub _tree_construction_main ($) { Line 7146  sub _tree_construction_main ($) {
7146            next B;            next B;
7147          } else {          } else {
7148            !!!cp ('t408');            !!!cp ('t408');
7149            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag',
7150                              text => $token->{tag_name}, token => $token);
7151            ## Ignore the token            ## Ignore the token
7152            !!!next-token;            !!!next-token;
7153            next B;            next B;
# Line 6971  sub _tree_construction_main ($) { Line 7175  sub _tree_construction_main ($) {
7175    
7176          unless (defined $i) { # has an element in scope          unless (defined $i) { # has an element in scope
7177            !!!cp ('t413');            !!!cp ('t413');
7178            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag',
7179                              text => $token->{tag_name}, token => $token);
7180              ## NOTE: Ignore the token.
7181          } else {          } else {
7182            ## Step 1. generate implied end tags            ## Step 1. generate implied end tags
7183            while ({            while ({
7184                      ## END_TAG_OPTIONAL_EL
7185                    dd => ($token->{tag_name} ne 'dd'),                    dd => ($token->{tag_name} ne 'dd'),
7186                    dt => ($token->{tag_name} ne 'dt'),                    dt => ($token->{tag_name} ne 'dt'),
7187                    li => ($token->{tag_name} ne 'li'),                    li => ($token->{tag_name} ne 'li'),
7188                    p => 1,                    p => 1,
7189                      rt => 1,
7190                      rp => 1,
7191                   }->{$self->{open_elements}->[-1]->[0]->manakai_local_name}) {                   }->{$self->{open_elements}->[-1]->[0]->manakai_local_name}) {
7192              !!!cp ('t409');              !!!cp ('t409');
7193              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
# Line 6989  sub _tree_construction_main ($) { Line 7198  sub _tree_construction_main ($) {
7198                    ne $token->{tag_name}) {                    ne $token->{tag_name}) {
7199              !!!cp ('t412');              !!!cp ('t412');
7200              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
7201                              value => $self->{open_elements}->[-1]->[0]                              text => $self->{open_elements}->[-1]->[0]
7202                                  ->manakai_local_name,                                  ->manakai_local_name,
7203                              token => $token);                              token => $token);
7204            } else {            } else {
# Line 7026  sub _tree_construction_main ($) { Line 7235  sub _tree_construction_main ($) {
7235    
7236          unless (defined $i) { # has an element in scope          unless (defined $i) { # has an element in scope
7237            !!!cp ('t421');            !!!cp ('t421');
7238            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag',
7239                              text => $token->{tag_name}, token => $token);
7240              ## NOTE: Ignore the token.
7241          } else {          } else {
7242            ## Step 1. generate implied end tags            ## Step 1. generate implied end tags
7243            while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {            while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
# Line 7039  sub _tree_construction_main ($) { Line 7250  sub _tree_construction_main ($) {
7250                    ne $token->{tag_name}) {                    ne $token->{tag_name}) {
7251              !!!cp ('t417.1');              !!!cp ('t417.1');
7252              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
7253                              value => $self->{open_elements}->[-1]->[0]                              text => $self->{open_elements}->[-1]->[0]
7254                                  ->manakai_local_name,                                  ->manakai_local_name,
7255                              token => $token);                              token => $token);
7256            } else {            } else {
# Line 7071  sub _tree_construction_main ($) { Line 7282  sub _tree_construction_main ($) {
7282    
7283          unless (defined $i) { # has an element in scope          unless (defined $i) { # has an element in scope
7284            !!!cp ('t425.1');            !!!cp ('t425.1');
7285            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag',
7286                              text => $token->{tag_name}, token => $token);
7287              ## NOTE: Ignore the token.
7288          } else {          } else {
7289            ## Step 1. generate implied end tags            ## Step 1. generate implied end tags
7290            while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {            while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
# Line 7083  sub _tree_construction_main ($) { Line 7296  sub _tree_construction_main ($) {
7296            if ($self->{open_elements}->[-1]->[0]->manakai_local_name            if ($self->{open_elements}->[-1]->[0]->manakai_local_name
7297                    ne $token->{tag_name}) {                    ne $token->{tag_name}) {
7298              !!!cp ('t425');              !!!cp ('t425');
7299              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'unmatched end tag',
7300                                text => $token->{tag_name}, token => $token);
7301            } else {            } else {
7302              !!!cp ('t426');              !!!cp ('t426');
7303            }            }
# Line 7114  sub _tree_construction_main ($) { Line 7328  sub _tree_construction_main ($) {
7328                    ne $token->{tag_name}) {                    ne $token->{tag_name}) {
7329              !!!cp ('t412.1');              !!!cp ('t412.1');
7330              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
7331                              value => $self->{open_elements}->[-1]->[0]                              text => $self->{open_elements}->[-1]->[0]
7332                                  ->manakai_local_name,                                  ->manakai_local_name,
7333                              token => $token);                              token => $token);
7334            } else {            } else {
# Line 7124  sub _tree_construction_main ($) { Line 7338  sub _tree_construction_main ($) {
7338            splice @{$self->{open_elements}}, $i;            splice @{$self->{open_elements}}, $i;
7339          } else {          } else {
7340            !!!cp ('t413.1');            !!!cp ('t413.1');
7341            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag',
7342                              text => $token->{tag_name}, token => $token);
7343    
7344            !!!cp ('t415.1');            !!!cp ('t415.1');
7345            ## As if <p>, then reprocess the current token            ## As if <p>, then reprocess the current token
# Line 7147  sub _tree_construction_main ($) { Line 7362  sub _tree_construction_main ($) {
7362          next B;          next B;
7363        } elsif ($token->{tag_name} eq 'br') {        } elsif ($token->{tag_name} eq 'br') {
7364          !!!cp ('t428');          !!!cp ('t428');
7365          !!!parse-error (type => 'unmatched end tag:br', token => $token);          !!!parse-error (type => 'unmatched end tag',
7366                            text => 'br', token => $token);
7367    
7368          ## As if <br>          ## As if <br>
7369          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
# Line 7172  sub _tree_construction_main ($) { Line 7388  sub _tree_construction_main ($) {
7388                  noscript => 0, ## TODO: if scripting is enabled                  noscript => 0, ## TODO: if scripting is enabled
7389                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7390          !!!cp ('t429');          !!!cp ('t429');
7391          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);          !!!parse-error (type => 'unmatched end tag',
7392                            text => $token->{tag_name}, token => $token);
7393          ## Ignore the token          ## Ignore the token
7394          !!!next-token;          !!!next-token;
7395          next B;          next B;
# Line 7191  sub _tree_construction_main ($) { Line 7408  sub _tree_construction_main ($) {
7408              ## generate implied end tags              ## generate implied end tags
7409              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
7410                !!!cp ('t430');                !!!cp ('t430');
7411                ## ISSUE: Can this case be reached?                ## NOTE: |<ruby><rt></ruby>|.
7412                  ## ISSUE: <ruby><rt></rt> will also take this code path,
7413                  ## which seems wrong.
7414                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
7415                  $node_i++;
7416              }              }
7417                    
7418              ## Step 2              ## Step 2
# Line 7201  sub _tree_construction_main ($) { Line 7421  sub _tree_construction_main ($) {
7421                !!!cp ('t431');                !!!cp ('t431');
7422                ## NOTE: <x><y></x>                ## NOTE: <x><y></x>
7423                !!!parse-error (type => 'not closed',                !!!parse-error (type => 'not closed',
7424                                value => $self->{open_elements}->[-1]->[0]                                text => $self->{open_elements}->[-1]->[0]
7425                                    ->manakai_local_name,                                    ->manakai_local_name,
7426                                token => $token);                                token => $token);
7427              } else {              } else {
# Line 7209  sub _tree_construction_main ($) { Line 7429  sub _tree_construction_main ($) {
7429              }              }
7430                            
7431              ## Step 3              ## Step 3
7432              splice @{$self->{open_elements}}, $node_i;              splice @{$self->{open_elements}}, $node_i if $node_i < 0;
7433    
7434              !!!next-token;              !!!next-token;
7435              last S2;              last S2;
# Line 7220  sub _tree_construction_main ($) { Line 7440  sub _tree_construction_main ($) {
7440                  ($node->[1] & SPECIAL_EL or                  ($node->[1] & SPECIAL_EL or
7441                   $node->[1] & SCOPING_EL)) {                   $node->[1] & SCOPING_EL)) {
7442                !!!cp ('t433');                !!!cp ('t433');
7443                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                !!!parse-error (type => 'unmatched end tag',
7444                                  text => $token->{tag_name}, token => $token);
7445                ## Ignore the token                ## Ignore the token
7446                !!!next-token;                !!!next-token;
7447                last S2;                last S2;
# Line 7266  sub _tree_construction_main ($) { Line 7487  sub _tree_construction_main ($) {
7487    ## TODO: script stuffs    ## TODO: script stuffs
7488  } # _tree_construct_main  } # _tree_construct_main
7489    
7490  sub set_inner_html ($$$) {  sub set_inner_html ($$$;$) {
7491    my $class = shift;    my $class = shift;
7492    my $node = shift;    my $node = shift;
7493    my $s = \$_[0];    my $s = \$_[0];
7494    my $onerror = $_[1];    my $onerror = $_[1];
7495      my $get_wrapper = $_[2] || sub ($) { return $_[0] };
7496    
7497    ## ISSUE: Should {confident} be true?    ## ISSUE: Should {confident} be true?
7498    
# Line 7289  sub set_inner_html ($$$) { Line 7511  sub set_inner_html ($$$) {
7511      }      }
7512    
7513      ## Step 3, 4, 5 # MUST      ## Step 3, 4, 5 # MUST
7514      $class->parse_string ($$s => $node, $onerror);      $class->parse_char_string ($$s => $node, $onerror, $get_wrapper);
7515    } elsif ($nt == 1) {    } elsif ($nt == 1) {
7516      ## TODO: If non-html element      ## TODO: If non-html element
7517    
7518      ## NOTE: Most of this code is copied from |parse_string|      ## NOTE: Most of this code is copied from |parse_string|
7519    
7520    ## TODO: Support for $get_wrapper
7521    
7522      ## Step 1 # MUST      ## Step 1 # MUST
7523      my $this_doc = $node->owner_document;      my $this_doc = $node->owner_document;
7524      my $doc = $this_doc->implementation->create_document;      my $doc = $this_doc->implementation->create_document;
# Line 7356  sub set_inner_html ($$$) { Line 7580  sub set_inner_html ($$$) {
7580                  0x10FFFE => 1, 0x10FFFF => 1,                  0x10FFFE => 1, 0x10FFFF => 1,
7581                 }->{$self->{next_char}}) {                 }->{$self->{next_char}}) {
7582          !!!cp ('i4.1');          !!!cp ('i4.1');
7583          !!!parse-error (type => 'control char', level => $self->{must_level});          if ($self->{next_char} < 0x10000) {
7584  ## TODO: error type documentation            !!!parse-error (type => 'control char',
7585                              text => (sprintf 'U+%04X', $self->{next_char}));
7586            } else {
7587              !!!parse-error (type => 'control char',
7588                              text => (sprintf 'U-%08X', $self->{next_char}));
7589            }
7590        }        }
7591      };      };
7592      $p->{prev_char} = [-1, -1, -1];      $p->{prev_char} = [-1, -1, -1];

Legend:
Removed from v.1.145  
changed lines
  Added in v.1.163

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24