/[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.124 by wakaba, Sun Apr 6 10:34:11 2008 UTC revision 1.141 by wakaba, Sat May 24 10:18:26 2008 UTC
# Line 8  use Error qw(:try); Line 8  use Error qw(:try);
8  ## doc.write ('');  ## doc.write ('');
9  ## alert (doc.compatMode);  ## alert (doc.compatMode);
10    
 ## TODO: Control charcters and noncharacters are not allowed (HTML5 revision 1263)  
11  ## TODO: 1252 parse error (revision 1264)  ## TODO: 1252 parse error (revision 1264)
12  ## TODO: 8859-11 = 874 (revision 1271)  ## TODO: 8859-11 = 874 (revision 1271)
13    
14    require IO::Handle;
15    
16    my $HTML_NS = q<http://www.w3.org/1999/xhtml>;
17    my $MML_NS = q<http://www.w3.org/1998/Math/MathML>;
18    my $SVG_NS = q<http://www.w3.org/2000/svg>;
19    my $XLINK_NS = q<http://www.w3.org/1999/xlink>;
20    my $XML_NS = q<http://www.w3.org/XML/1998/namespace>;
21    my $XMLNS_NS = q<http://www.w3.org/2000/xmlns/>;
22    
23  sub A_EL () { 0b1 }  sub A_EL () { 0b1 }
24  sub ADDRESS_EL () { 0b10 }  sub ADDRESS_EL () { 0b10 }
25  sub BODY_EL () { 0b100 }  sub BODY_EL () { 0b100 }
# Line 37  sub TABLE_ROW_EL () { 0b1000000000000000 Line 45  sub TABLE_ROW_EL () { 0b1000000000000000
45  sub TABLE_ROW_GROUP_EL () { 0b10000000000000000000000 }  sub TABLE_ROW_GROUP_EL () { 0b10000000000000000000000 }
46  sub MISC_SCOPING_EL () { 0b100000000000000000000000 }  sub MISC_SCOPING_EL () { 0b100000000000000000000000 }
47  sub MISC_SPECIAL_EL () { 0b1000000000000000000000000 }  sub MISC_SPECIAL_EL () { 0b1000000000000000000000000 }
48    sub FOREIGN_EL () { 0b10000000000000000000000000 }
49    sub FOREIGN_FLOW_CONTENT_EL () { 0b100000000000000000000000000 }
50    sub MML_AXML_EL () { 0b1000000000000000000000000000 }
51    
52  sub TABLE_ROWS_EL () {  sub TABLE_ROWS_EL () {
53    TABLE_EL |    TABLE_EL |
# Line 185  my $el_category = { Line 196  my $el_category = {
196    wbr => MISC_SPECIAL_EL,    wbr => MISC_SPECIAL_EL,
197  };  };
198    
199  my $permitted_slash_tag_name = {  my $el_category_f = {
200    base => 1,    $MML_NS => {
201    link => 1,      'annotation-xml' => MML_AXML_EL,
202    meta => 1,      mi => FOREIGN_FLOW_CONTENT_EL,
203    hr => 1,      mo => FOREIGN_FLOW_CONTENT_EL,
204    br => 1,      mn => FOREIGN_FLOW_CONTENT_EL,
205    img => 1,      ms => FOREIGN_FLOW_CONTENT_EL,
206    embed => 1,      mtext => FOREIGN_FLOW_CONTENT_EL,
207    param => 1,    },
208    area => 1,    $SVG_NS => {
209    col => 1,      foreignObject => FOREIGN_FLOW_CONTENT_EL,
210    input => 1,      desc => FOREIGN_FLOW_CONTENT_EL,
211        title => FOREIGN_FLOW_CONTENT_EL,
212      },
213      ## NOTE: In addition, FOREIGN_EL is set to non-HTML elements.
214    };
215    
216    my $svg_attr_name = {
217      attributetype => 'attributeType',
218      basefrequency => 'baseFrequency',
219      baseprofile => 'baseProfile',
220      calcmode => 'calcMode',
221      clippathunits => 'clipPathUnits',
222      contentscripttype => 'contentScriptType',
223      contentstyletype => 'contentStyleType',
224      diffuseconstant => 'diffuseConstant',
225      edgemode => 'edgeMode',
226      externalresourcesrequired => 'externalResourcesRequired',
227      fecolormatrix => 'feColorMatrix',
228      fecomposite => 'feComposite',
229      fegaussianblur => 'feGaussianBlur',
230      femorphology => 'feMorphology',
231      fetile => 'feTile',
232      filterres => 'filterRes',
233      filterunits => 'filterUnits',
234      glyphref => 'glyphRef',
235      gradienttransform => 'gradientTransform',
236      gradientunits => 'gradientUnits',
237      kernelmatrix => 'kernelMatrix',
238      kernelunitlength => 'kernelUnitLength',
239      keypoints => 'keyPoints',
240      keysplines => 'keySplines',
241      keytimes => 'keyTimes',
242      lengthadjust => 'lengthAdjust',
243      limitingconeangle => 'limitingConeAngle',
244      markerheight => 'markerHeight',
245      markerunits => 'markerUnits',
246      markerwidth => 'markerWidth',
247      maskcontentunits => 'maskContentUnits',
248      maskunits => 'maskUnits',
249      numoctaves => 'numOctaves',
250      pathlength => 'pathLength',
251      patterncontentunits => 'patternContentUnits',
252      patterntransform => 'patternTransform',
253      patternunits => 'patternUnits',
254      pointsatx => 'pointsAtX',
255      pointsaty => 'pointsAtY',
256      pointsatz => 'pointsAtZ',
257      preservealpha => 'preserveAlpha',
258      preserveaspectratio => 'preserveAspectRatio',
259      primitiveunits => 'primitiveUnits',
260      refx => 'refX',
261      refy => 'refY',
262      repeatcount => 'repeatCount',
263      repeatdur => 'repeatDur',
264      requiredextensions => 'requiredExtensions',
265      specularconstant => 'specularConstant',
266      specularexponent => 'specularExponent',
267      spreadmethod => 'spreadMethod',
268      startoffset => 'startOffset',
269      stddeviation => 'stdDeviation',
270      stitchtiles => 'stitchTiles',
271      surfacescale => 'surfaceScale',
272      systemlanguage => 'systemLanguage',
273      tablevalues => 'tableValues',
274      targetx => 'targetX',
275      targety => 'targetY',
276      textlength => 'textLength',
277      viewbox => 'viewBox',
278      viewtarget => 'viewTarget',
279      xchannelselector => 'xChannelSelector',
280      ychannelselector => 'yChannelSelector',
281      zoomandpan => 'zoomAndPan',
282  };  };
283    
284    my $foreign_attr_xname = {
285      'xlink:actuate' => [$XLINK_NS, ['xlink', 'actuate']],
286      'xlink:arcrole' => [$XLINK_NS, ['xlink', 'arcrole']],
287      'xlink:href' => [$XLINK_NS, ['xlink', 'href']],
288      'xlink:role' => [$XLINK_NS, ['xlink', 'role']],
289      'xlink:show' => [$XLINK_NS, ['xlink', 'show']],
290      'xlink:title' => [$XLINK_NS, ['xlink', 'title']],
291      'xlink:type' => [$XLINK_NS, ['xlink', 'type']],
292      'xml:base' => [$XML_NS, ['xml', 'base']],
293      'xml:lang' => [$XML_NS, ['xml', 'lang']],
294      'xml:space' => [$XML_NS, ['xml', 'space']],
295      'xmlns' => [$XMLNS_NS, [undef, 'xmlns']],
296      'xmlns:xlink' => [$XMLNS_NS, ['xmlns', 'xlink']],
297    };
298    
299    ## ISSUE: xmlns:xlink="non-xlink-ns" is not an error.
300    
301  my $c1_entity_char = {  my $c1_entity_char = {
302    0x80 => 0x20AC,    0x80 => 0x20AC,
303    0x81 => 0xFFFD,    0x81 => 0xFFFD,
# Line 235  my $c1_entity_char = { Line 334  my $c1_entity_char = {
334  }; # $c1_entity_char  }; # $c1_entity_char
335    
336  sub parse_byte_string ($$$$;$) {  sub parse_byte_string ($$$$;$) {
337      my $self = shift;
338      my $charset_name = shift;
339      open my $input, '<', ref $_[0] ? $_[0] : \($_[0]);
340      return $self->parse_byte_stream ($charset_name, $input, @_[1..$#_]);
341    } # parse_byte_string
342    
343    sub parse_byte_stream ($$$$;$) {
344    my $self = ref $_[0] ? shift : shift->new;    my $self = ref $_[0] ? shift : shift->new;
345    my $charset = shift;    my $charset_name = shift;
346    my $bytes_s = ref $_[0] ? $_[0] : \($_[0]);    my $byte_stream = $_[0];
   my $s;  
     
   if (defined $charset) {  
     require Encode; ## TODO: decode(utf8) don't delete BOM  
     $s = \ (Encode::decode ($charset, $$bytes_s));  
     $self->{input_encoding} = lc $charset; ## TODO: normalize name  
     $self->{confident} = 1;  
   } else {  
     ## TODO: Implement HTML5 detection algorithm  
     require Whatpm::Charset::UniversalCharDet;  
     $charset = Whatpm::Charset::UniversalCharDet->detect_byte_string  
         (substr ($$bytes_s, 0, 1024));  
     $charset ||= 'windows-1252';  
     $s = \ (Encode::decode ($charset, $$bytes_s));  
     $self->{input_encoding} = $charset;  
     $self->{confident} = 0;  
   }  
347    
348    $self->{change_encoding} = sub {    my $onerror = $_[2] || sub {
349      my $self = shift;      my (%opt) = @_;
350      my $charset = lc shift;      warn "Parse error ($opt{type})\n";
351      my $token = shift;    };
352      ## TODO: if $charset is supported    $self->{parse_error} = $onerror; # updated later by parse_char_string
353      ## TODO: normalize charset name  
354      ## HTML5 encoding sniffing algorithm
355      require Message::Charset::Info;
356      my $charset;
357      my $buffer;
358      my ($char_stream, $e_status);
359    
360      ## "Change the encoding" algorithm:    SNIFFING: {
361    
362      ## Step 1          ## Step 1
363      if ($charset eq 'utf-16') { ## ISSUE: UTF-16BE -> UTF-8? UTF-16LE -> UTF-8?      if (defined $charset_name) {
364        $charset = 'utf-8';        $charset = Message::Charset::Info->get_by_iana_name ($charset_name);
365    
366          ## ISSUE: Unsupported encoding is not ignored according to the spec.
367          ($char_stream, $e_status) = $charset->get_decode_handle
368              ($byte_stream, allow_error_reporting => 1,
369               allow_fallback => 1);
370          if ($char_stream) {
371            $self->{confident} = 1;
372            last SNIFFING;
373          } else {
374            ## TODO: unsupported error
375          }
376      }      }
377    
378      ## Step 2      ## Step 2
379      if (defined $self->{input_encoding} and      my $byte_buffer = '';
380          $self->{input_encoding} eq $charset) {      for (1..1024) {
381          my $char = $byte_stream->getc;
382          last unless defined $char;
383          $byte_buffer .= $char;
384        } ## TODO: timeout
385    
386        ## Step 3
387        if ($byte_buffer =~ /^\xFE\xFF/) {
388          $charset = Message::Charset::Info->get_by_iana_name ('utf-16be');
389          ($char_stream, $e_status) = $charset->get_decode_handle
390              ($byte_stream, allow_error_reporting => 1,
391               allow_fallback => 1, byte_buffer => \$byte_buffer);
392        $self->{confident} = 1;        $self->{confident} = 1;
393        return;        last SNIFFING;
394        } elsif ($byte_buffer =~ /^\xFF\xFE/) {
395          $charset = Message::Charset::Info->get_by_iana_name ('utf-16le');
396          ($char_stream, $e_status) = $charset->get_decode_handle
397              ($byte_stream, allow_error_reporting => 1,
398               allow_fallback => 1, byte_buffer => \$byte_buffer);
399          $self->{confident} = 1;
400          last SNIFFING;
401        } elsif ($byte_buffer =~ /^\xEF\xBB\xBF/) {
402          $charset = Message::Charset::Info->get_by_iana_name ('utf-8');
403          ($char_stream, $e_status) = $charset->get_decode_handle
404              ($byte_stream, allow_error_reporting => 1,
405               allow_fallback => 1, byte_buffer => \$byte_buffer);
406          $self->{confident} = 1;
407          last SNIFFING;
408      }      }
409    
410      !!!parse-error (type => 'charset label detected:'.$self->{input_encoding}.      ## Step 4
411          ':'.$charset, level => 'w', token => $token);      ## TODO: <meta charset>
412    
413      ## Step 3      ## Step 5
414      # if (can) {      ## TODO: from history
       ## change the encoding on the fly.  
       #$self->{confident} = 1;  
       #return;  
     # }  
415    
416      ## Step 4      ## Step 6
417      throw Whatpm::HTML::RestartParser (charset => $charset);      require Whatpm::Charset::UniversalCharDet;
418        $charset_name = Whatpm::Charset::UniversalCharDet->detect_byte_string
419            ($byte_buffer);
420        if (defined $charset_name) {
421          $charset = Message::Charset::Info->get_by_iana_name ($charset_name);
422    
423          ## ISSUE: Unsupported encoding is not ignored according to the spec.
424          require Whatpm::Charset::DecodeHandle;
425          $buffer = Whatpm::Charset::DecodeHandle::ByteBuffer->new
426              ($byte_stream);
427          ($char_stream, $e_status) = $charset->get_decode_handle
428              ($buffer, allow_error_reporting => 1,
429               allow_fallback => 1, byte_buffer => \$byte_buffer);
430          if ($char_stream) {
431            $buffer->{buffer} = $byte_buffer;
432            !!!parse-error (type => 'sniffing:chardet', ## TODO: type name
433                            value => $charset_name,
434                            level => $self->{info_level},
435                            line => 1, column => 1);
436            $self->{confident} = 0;
437            last SNIFFING;
438          }
439        }
440    
441        ## Step 7: default
442        ## TODO: Make this configurable.
443        $charset = Message::Charset::Info->get_by_iana_name ('windows-1252');
444            ## NOTE: We choose |windows-1252| here, since |utf-8| should be
445            ## detectable in the step 6.
446        require Whatpm::Charset::DecodeHandle;
447        $buffer = Whatpm::Charset::DecodeHandle::ByteBuffer->new
448            ($byte_stream);
449        ($char_stream, $e_status)
450            = $charset->get_decode_handle ($buffer,
451                                           allow_error_reporting => 1,
452                                           allow_fallback => 1,
453                                           byte_buffer => \$byte_buffer);
454        $buffer->{buffer} = $byte_buffer;
455        !!!parse-error (type => 'sniffing:default', ## TODO: type name
456                        value => 'windows-1252',
457                        level => $self->{info_level},
458                        line => 1, column => 1);
459        $self->{confident} = 0;
460      } # SNIFFING
461    
462      $self->{input_encoding} = $charset->get_iana_name;
463      if ($e_status & Message::Charset::Info::FALLBACK_ENCODING_IMPL ()) {
464        !!!parse-error (type => 'chardecode:fallback', ## TODO: type name
465                        value => $self->{input_encoding},
466                        level => $self->{unsupported_level},
467                        line => 1, column => 1);
468      } elsif (not ($e_status &
469                    Message::Charset::Info::ERROR_REPORTING_ENCODING_IMPL())) {
470        !!!parse-error (type => 'chardecode:no error', ## TODO: type name
471                        value => $self->{input_encoding},
472                        level => $self->{unsupported_level},
473                        line => 1, column => 1);
474      }
475    
476      $self->{change_encoding} = sub {
477        my $self = shift;
478        $charset_name = shift;
479        my $token = shift;
480    
481        $charset = Message::Charset::Info->get_by_iana_name ($charset_name);
482        ($char_stream, $e_status) = $charset->get_decode_handle
483            ($byte_stream, allow_error_reporting => 1, allow_fallback => 1,
484             byte_buffer => \ $buffer->{buffer});
485        
486        if ($char_stream) { # if supported
487          ## "Change the encoding" algorithm:
488    
489          ## Step 1    
490          if ($charset->{iana_names}->{'utf-16'}) { ## ISSUE: UTF-16BE -> UTF-8? UTF-16LE -> UTF-8?
491            $charset = Message::Charset::Info->get_by_iana_name ('utf-8');
492            ($char_stream, $e_status) = $charset->get_decode_handle
493                ($byte_stream,
494                 byte_buffer => \ $buffer->{buffer});
495          }
496          $charset_name = $charset->get_iana_name;
497          
498          ## Step 2
499          if (defined $self->{input_encoding} and
500              $self->{input_encoding} eq $charset_name) {
501            !!!parse-error (type => 'charset label:matching', ## TODO: type
502                            value => $charset_name,
503                            level => $self->{info_level});
504            $self->{confident} = 1;
505            return;
506          }
507    
508          !!!parse-error (type => 'charset label detected:'.$self->{input_encoding}.
509              ':'.$charset_name, level => 'w', token => $token);
510          
511          ## Step 3
512          # if (can) {
513            ## change the encoding on the fly.
514            #$self->{confident} = 1;
515            #return;
516          # }
517          
518          ## Step 4
519          throw Whatpm::HTML::RestartParser ();
520        }
521    }; # $self->{change_encoding}    }; # $self->{change_encoding}
522    
523      my $char_onerror = sub {
524        my (undef, $type, %opt) = @_;
525        !!!parse-error (%opt, type => $type,
526                        line => $self->{line}, column => $self->{column} + 1);
527        if ($opt{octets}) {
528          ${$opt{octets}} = "\x{FFFD}"; # relacement character
529        }
530      };
531      $char_stream->onerror ($char_onerror);
532    
533    my @args = @_; shift @args; # $s    my @args = @_; shift @args; # $s
534    my $return;    my $return;
535    try {    try {
536      $return = $self->parse_char_string ($s, @args);        $return = $self->parse_char_stream ($char_stream, @args);  
537    } catch Whatpm::HTML::RestartParser with {    } catch Whatpm::HTML::RestartParser with {
538      my $charset = shift->{charset};      ## NOTE: Invoked after {change_encoding}.
539      $s = \ (Encode::decode ($charset, $$bytes_s));      
540      $self->{input_encoding} = $charset; ## TODO: normalize      $self->{input_encoding} = $charset->get_iana_name;
541        if ($e_status & Message::Charset::Info::FALLBACK_ENCODING_IMPL ()) {
542          !!!parse-error (type => 'chardecode:fallback', ## TODO: type name
543                          value => $self->{input_encoding},
544                          level => $self->{unsupported_level},
545                          line => 1, column => 1);
546        } elsif (not ($e_status &
547                      Message::Charset::Info::ERROR_REPORTING_ENCODING_IMPL())) {
548          !!!parse-error (type => 'chardecode:no error', ## TODO: type name
549                          value => $self->{input_encoding},
550                          level => $self->{unsupported_level},
551                          line => 1, column => 1);
552        }
553      $self->{confident} = 1;      $self->{confident} = 1;
554      $return = $self->parse_char_string ($s, @args);      $char_stream->onerror ($char_onerror);
555        $return = $self->parse_char_stream ($char_stream, @args);
556    };    };
557    return $return;    return $return;
558  } # parse_byte_string  } # parse_byte_stream
559    
560  ## NOTE: HTML5 spec says that the encoding layer MUST NOT strip BOM  ## NOTE: HTML5 spec says that the encoding layer MUST NOT strip BOM
561  ## and the HTML layer MUST ignore it.  However, we does strip BOM in  ## and the HTML layer MUST ignore it.  However, we does strip BOM in
# Line 314  sub parse_byte_string ($$$$;$) { Line 566  sub parse_byte_string ($$$$;$) {
566  ## 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
567  ## strip the BOM and never strip any ZWNBSP.  ## strip the BOM and never strip any ZWNBSP.
568    
569  *parse_char_string = \&parse_string;  sub parse_char_string ($$$;$) {
570      my $self = shift;
571      require utf8;
572      my $s = ref $_[0] ? $_[0] : \($_[0]);
573      open my $input, '<' . (utf8::is_utf8 ($$s) ? ':utf8' : ''), $s;
574      return $self->parse_char_stream ($input, @_[1..$#_]);
575    } # parse_char_string
576    *parse_string = \&parse_char_string;
577    
578  sub parse_string ($$$;$) {  sub parse_char_stream ($$$;$) {
579    my $self = ref $_[0] ? shift : shift->new;    my $self = ref $_[0] ? shift : shift->new;
580    my $s = ref $_[0] ? $_[0] : \($_[0]);    my $input = $_[0];
581    $self->{document} = $_[1];    $self->{document} = $_[1];
582    @{$self->{document}->child_nodes} = ();    @{$self->{document}->child_nodes} = ();
583    
# Line 337  sub parse_string ($$$;$) { Line 596  sub parse_string ($$$;$) {
596      pop @{$self->{prev_char}};      pop @{$self->{prev_char}};
597      unshift @{$self->{prev_char}}, $self->{next_char};      unshift @{$self->{prev_char}}, $self->{next_char};
598    
599      $self->{next_char} = -1 and return if $i >= length $$s;      my $char;
600      $self->{next_char} = ord substr $$s, $i++, 1;      if (defined $self->{next_next_char}) {
601          $char = $self->{next_next_char};
602          delete $self->{next_next_char};
603        } else {
604          $char = $input->getc;
605        }
606        $self->{next_char} = -1 and return unless defined $char;
607        $self->{next_char} = ord $char;
608    
609      ($self->{line_prev}, $self->{column_prev})      ($self->{line_prev}, $self->{column_prev})
610          = ($self->{line}, $self->{column});          = ($self->{line}, $self->{column});
611      $self->{column}++;      $self->{column}++;
612            
613      if ($self->{next_char} == 0x000A) { # LF      if ($self->{next_char} == 0x000A) { # LF
614          !!!cp ('j1');
615        $self->{line}++;        $self->{line}++;
616        $self->{column} = 0;        $self->{column} = 0;
617      } elsif ($self->{next_char} == 0x000D) { # CR      } elsif ($self->{next_char} == 0x000D) { # CR
618        $i++ if substr ($$s, $i, 1) eq "\x0A";        !!!cp ('j2');
619          my $next = $input->getc;
620          if (defined $next and $next ne "\x0A") {
621            $self->{next_next_char} = $next;
622          }
623        $self->{next_char} = 0x000A; # LF # MUST        $self->{next_char} = 0x000A; # LF # MUST
624        $self->{line}++;        $self->{line}++;
625        $self->{column} = 0;        $self->{column} = 0;
626      } elsif ($self->{next_char} > 0x10FFFF) {      } elsif ($self->{next_char} > 0x10FFFF) {
627          !!!cp ('j3');
628        $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST        $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST
629      } elsif ($self->{next_char} == 0x0000) { # NULL      } elsif ($self->{next_char} == 0x0000) { # NULL
630          !!!cp ('j4');
631        !!!parse-error (type => 'NULL');        !!!parse-error (type => 'NULL');
632        $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST        $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST
633        } elsif ($self->{next_char} <= 0x0008 or
634                 (0x000E <= $self->{next_char} and $self->{next_char} <= 0x001F) or
635                 (0x007F <= $self->{next_char} and $self->{next_char} <= 0x009F) or
636                 (0xD800 <= $self->{next_char} and $self->{next_char} <= 0xDFFF) or
637                 (0xFDD0 <= $self->{next_char} and $self->{next_char} <= 0xFDDF) or
638                 {
639                  0xFFFE => 1, 0xFFFF => 1, 0x1FFFE => 1, 0x1FFFF => 1,
640                  0x2FFFE => 1, 0x2FFFF => 1, 0x3FFFE => 1, 0x3FFFF => 1,
641                  0x4FFFE => 1, 0x4FFFF => 1, 0x5FFFE => 1, 0x5FFFF => 1,
642                  0x6FFFE => 1, 0x6FFFF => 1, 0x7FFFE => 1, 0x7FFFF => 1,
643                  0x8FFFE => 1, 0x8FFFF => 1, 0x9FFFE => 1, 0x9FFFF => 1,
644                  0xAFFFE => 1, 0xAFFFF => 1, 0xBFFFE => 1, 0xBFFFF => 1,
645                  0xCFFFE => 1, 0xCFFFF => 1, 0xDFFFE => 1, 0xDFFFF => 1,
646                  0xEFFFE => 1, 0xEFFFF => 1, 0xFFFFE => 1, 0xFFFFF => 1,
647                  0x10FFFE => 1, 0x10FFFF => 1,
648                 }->{$self->{next_char}}) {
649          !!!cp ('j5');
650          !!!parse-error (type => 'control char', level => $self->{must_level});
651    ## TODO: error type documentation
652      }      }
653    };    };
654    $self->{prev_char} = [-1, -1, -1];    $self->{prev_char} = [-1, -1, -1];
# Line 380  sub parse_string ($$$;$) { Line 672  sub parse_string ($$$;$) {
672    delete $self->{parse_error}; # remove loop    delete $self->{parse_error}; # remove loop
673    
674    return $self->{document};    return $self->{document};
675  } # parse_string  } # parse_char_stream
676    
677  sub new ($) {  sub new ($) {
678    my $class = shift;    my $class = shift;
679    my $self = bless {}, $class;    my $self = bless {
680        must_level => 'm',
681        should_level => 's',
682        good_level => 'w',
683        warn_level => 'w',
684        info_level => 'i',
685        unsupported_level => 'u',
686      }, $class;
687    $self->{set_next_char} = sub {    $self->{set_next_char} = sub {
688      $self->{next_char} = -1;      $self->{next_char} = -1;
689    };    };
# Line 446  sub DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUO Line 745  sub DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUO
745  sub AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE () { 31 }  sub AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE () { 31 }
746  sub BOGUS_DOCTYPE_STATE () { 32 }  sub BOGUS_DOCTYPE_STATE () { 32 }
747  sub AFTER_ATTRIBUTE_VALUE_QUOTED_STATE () { 33 }  sub AFTER_ATTRIBUTE_VALUE_QUOTED_STATE () { 33 }
748    sub SELF_CLOSING_START_TAG_STATE () { 34 }
749    sub CDATA_BLOCK_STATE () { 35 }
750    
751  sub DOCTYPE_TOKEN () { 1 }  sub DOCTYPE_TOKEN () { 1 }
752  sub COMMENT_TOKEN () { 2 }  sub COMMENT_TOKEN () { 2 }
# Line 463  sub ROW_IMS ()        { 0b10000000 } Line 764  sub ROW_IMS ()        { 0b10000000 }
764  sub BODY_AFTER_IMS () { 0b100000000 }  sub BODY_AFTER_IMS () { 0b100000000 }
765  sub FRAME_IMS ()      { 0b1000000000 }  sub FRAME_IMS ()      { 0b1000000000 }
766  sub SELECT_IMS ()     { 0b10000000000 }  sub SELECT_IMS ()     { 0b10000000000 }
767    sub IN_FOREIGN_CONTENT_IM () { 0b100000000000 }
768        ## NOTE: "in foreign content" insertion mode is special; it is combined
769        ## with the secondary insertion mode.  In this parser, they are stored
770        ## together in the bit-or'ed form.
771    
772  ## NOTE: "initial" and "before html" insertion modes have no constants.  ## NOTE: "initial" and "before html" insertion modes have no constants.
773    
# Line 499  sub _initialize_tokenizer ($) { Line 804  sub _initialize_tokenizer ($) {
804    undef $self->{current_attribute};    undef $self->{current_attribute};
805    undef $self->{last_emitted_start_tag_name};    undef $self->{last_emitted_start_tag_name};
806    undef $self->{last_attribute_value_state};    undef $self->{last_attribute_value_state};
807      delete $self->{self_closing};
808    $self->{char} = [];    $self->{char} = [];
809    # $self->{next_char}    # $self->{next_char}
810    !!!next-input-character;    !!!next-input-character;
# Line 519  sub _initialize_tokenizer ($) { Line 825  sub _initialize_tokenizer ($) {
825  ##        ->{value}  ##        ->{value}
826  ##        ->{has_reference} == 1 or 0  ##        ->{has_reference} == 1 or 0
827  ##   ->{data} (COMMENT_TOKEN, CHARACTER_TOKEN)  ##   ->{data} (COMMENT_TOKEN, CHARACTER_TOKEN)
828    ## NOTE: The "self-closing flag" is hold as |$self->{self_closing}|.
829    ##     |->{self_closing}| is used to save the value of |$self->{self_closing}|
830    ##     while the token is pushed back to the stack.
831    
832    ## ISSUE: "When a DOCTYPE token is created, its
833    ## <i>self-closing flag</i> must be unset (its other state is that it
834    ## be set), and its attributes list must be empty.": Wrong subject?
835    
836  ## Emitted token MUST immediately be handled by the tree construction state.  ## Emitted token MUST immediately be handled by the tree construction state.
837    
# Line 545  sub _initialize_tokenizer ($) { Line 858  sub _initialize_tokenizer ($) {
858    
859  sub _get_next_token ($) {  sub _get_next_token ($) {
860    my $self = shift;    my $self = shift;
861    
862      if ($self->{self_closing}) {
863        !!!parse-error (type => 'nestc', token => $self->{current_token});
864        ## NOTE: The |self_closing| flag is only set by start tag token.
865        ## In addition, when a start tag token is emitted, it is always set to
866        ## |current_token|.
867        delete $self->{self_closing};
868      }
869    
870    if (@{$self->{token}}) {    if (@{$self->{token}}) {
871        $self->{self_closing} = $self->{token}->[0]->{self_closing};
872      return shift @{$self->{token}};      return shift @{$self->{token}};
873    }    }
874    
# Line 725  sub _get_next_token ($) { Line 1048  sub _get_next_token ($) {
1048            redo A;            redo A;
1049          } else {          } else {
1050            !!!cp (23);            !!!cp (23);
1051            !!!parse-error (type => 'bare stago');            !!!parse-error (type => 'bare stago',
1052                              line => $self->{line_prev},
1053                              column => $self->{column_prev});
1054            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
1055            ## reconsume            ## reconsume
1056    
# Line 916  sub _get_next_token ($) { Line 1241  sub _get_next_token ($) {
1241    
1242          redo A;          redo A;
1243        } elsif ($self->{next_char} == 0x002F) { # /        } elsif ($self->{next_char} == 0x002F) { # /
1244            !!!cp (42);
1245            $self->{state} = SELF_CLOSING_START_TAG_STATE;
1246          !!!next-input-character;          !!!next-input-character;
         if ($self->{next_char} == 0x003E and # >  
             $self->{current_token}->{type} == START_TAG_TOKEN and  
             $permitted_slash_tag_name->{$self->{current_token}->{tag_name}}) {  
           # permitted slash  
           !!!cp (42);  
           #  
         } else {  
           !!!cp (43);  
           !!!parse-error (type => 'nestc');  
         }  
         $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;  
         # next-input-character is already done  
1247          redo A;          redo A;
1248        } else {        } else {
1249          !!!cp (44);          !!!cp (44);
# Line 980  sub _get_next_token ($) { Line 1295  sub _get_next_token ($) {
1295          !!!next-input-character;          !!!next-input-character;
1296          redo A;          redo A;
1297        } elsif ($self->{next_char} == 0x002F) { # /        } elsif ($self->{next_char} == 0x002F) { # /
1298            !!!cp (50);
1299            $self->{state} = SELF_CLOSING_START_TAG_STATE;
1300          !!!next-input-character;          !!!next-input-character;
         if ($self->{next_char} == 0x003E and # >  
             $self->{current_token}->{type} == START_TAG_TOKEN and  
             $permitted_slash_tag_name->{$self->{current_token}->{tag_name}}) {  
           # permitted slash  
           !!!cp (50);  
           #  
         } else {  
           !!!cp (51);  
           !!!parse-error (type => 'nestc');  
         }  
         ## Stay in the state  
         # next-input-character is already done  
1301          redo A;          redo A;
1302        } elsif ($self->{next_char} == -1) {        } elsif ($self->{next_char} == -1) {
1303          !!!parse-error (type => 'unclosed tag');          !!!parse-error (type => 'unclosed tag');
# Line 1093  sub _get_next_token ($) { Line 1398  sub _get_next_token ($) {
1398          !!!next-input-character;          !!!next-input-character;
1399          redo A;          redo A;
1400        } elsif ($self->{next_char} == 0x002F) { # /        } elsif ($self->{next_char} == 0x002F) { # /
1401            !!!cp (64);
1402          $before_leave->();          $before_leave->();
1403            $self->{state} = SELF_CLOSING_START_TAG_STATE;
1404          !!!next-input-character;          !!!next-input-character;
         if ($self->{next_char} == 0x003E and # >  
             $self->{current_token}->{type} == START_TAG_TOKEN and  
             $permitted_slash_tag_name->{$self->{current_token}->{tag_name}}) {  
           # permitted slash  
           !!!cp (64);  
           #  
         } else {  
           !!!cp (65);  
           !!!parse-error (type => 'nestc');  
         }  
         $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;  
         # next-input-character is already done  
1405          redo A;          redo A;
1406        } elsif ($self->{next_char} == -1) {        } elsif ($self->{next_char} == -1) {
1407          !!!parse-error (type => 'unclosed tag');          !!!parse-error (type => 'unclosed tag');
# Line 1193  sub _get_next_token ($) { Line 1488  sub _get_next_token ($) {
1488          !!!next-input-character;          !!!next-input-character;
1489          redo A;          redo A;
1490        } elsif ($self->{next_char} == 0x002F) { # /        } elsif ($self->{next_char} == 0x002F) { # /
1491            !!!cp (77);
1492            $self->{state} = SELF_CLOSING_START_TAG_STATE;
1493          !!!next-input-character;          !!!next-input-character;
         if ($self->{next_char} == 0x003E and # >  
             $self->{current_token}->{type} == START_TAG_TOKEN and  
             $permitted_slash_tag_name->{$self->{current_token}->{tag_name}}) {  
           # permitted slash  
           !!!cp (77);  
           #  
         } else {  
           !!!cp (78);  
           !!!parse-error (type => 'nestc');  
           ## TODO: Different error type for <aa / bb> than <aa/>  
         }  
         $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;  
         # next-input-character is already done  
1494          redo A;          redo A;
1495        } elsif ($self->{next_char} == -1) {        } elsif ($self->{next_char} == -1) {
1496          !!!parse-error (type => 'unclosed tag');          !!!parse-error (type => 'unclosed tag');
# Line 1539  sub _get_next_token ($) { Line 1823  sub _get_next_token ($) {
1823    
1824          redo A;          redo A;
1825        } elsif ($self->{next_char} == 0x002F) { # /        } elsif ($self->{next_char} == 0x002F) { # /
1826            !!!cp (122);
1827            $self->{state} = SELF_CLOSING_START_TAG_STATE;
1828          !!!next-input-character;          !!!next-input-character;
1829          if ($self->{next_char} == 0x003E and # >          redo A;
1830              $self->{current_token}->{type} == START_TAG_TOKEN and        } elsif ($self->{next_char} == -1) {
1831              $permitted_slash_tag_name->{$self->{current_token}->{tag_name}}) {          !!!parse-error (type => 'unclosed tag');
1832            # permitted slash          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
1833            !!!cp (122);            !!!cp (122.3);
1834            #            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
1835            } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
1836              if ($self->{current_token}->{attributes}) {
1837                !!!cp (122.1);
1838                !!!parse-error (type => 'end tag attribute');
1839              } else {
1840                ## NOTE: This state should never be reached.
1841                !!!cp (122.2);
1842              }
1843          } else {          } else {
1844            !!!cp (123);            die "$0: $self->{current_token}->{type}: Unknown token type";
           !!!parse-error (type => 'nestc');  
1845          }          }
1846          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;          $self->{state} = DATA_STATE;
1847          # next-input-character is already done          ## Reconsume.
1848            !!!emit ($self->{current_token}); # start tag or end tag
1849          redo A;          redo A;
1850        } else {        } else {
1851          !!!cp (124);          !!!cp ('124.1');
1852          !!!parse-error (type => 'no space between attributes');          !!!parse-error (type => 'no space between attributes');
1853          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;
1854          ## reconsume          ## reconsume
1855          redo A;          redo A;
1856        }        }
1857        } elsif ($self->{state} == SELF_CLOSING_START_TAG_STATE) {
1858          if ($self->{next_char} == 0x003E) { # >
1859            if ($self->{current_token}->{type} == END_TAG_TOKEN) {
1860              !!!cp ('124.2');
1861              !!!parse-error (type => 'nestc', token => $self->{current_token});
1862              ## TODO: Different type than slash in start tag
1863              $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
1864              if ($self->{current_token}->{attributes}) {
1865                !!!cp ('124.4');
1866                !!!parse-error (type => 'end tag attribute');
1867              } else {
1868                !!!cp ('124.5');
1869              }
1870              ## TODO: Test |<title></title/>|
1871            } else {
1872              !!!cp ('124.3');
1873              $self->{self_closing} = 1;
1874            }
1875    
1876            $self->{state} = DATA_STATE;
1877            !!!next-input-character;
1878    
1879            !!!emit ($self->{current_token}); # start tag or end tag
1880    
1881            redo A;
1882          } elsif ($self->{next_char} == -1) {
1883            !!!parse-error (type => 'unclosed tag');
1884            if ($self->{current_token}->{type} == START_TAG_TOKEN) {
1885              !!!cp (124.7);
1886              $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
1887            } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
1888              if ($self->{current_token}->{attributes}) {
1889                !!!cp (124.5);
1890                !!!parse-error (type => 'end tag attribute');
1891              } else {
1892                ## NOTE: This state should never be reached.
1893                !!!cp (124.6);
1894              }
1895            } else {
1896              die "$0: $self->{current_token}->{type}: Unknown token type";
1897            }
1898            $self->{state} = DATA_STATE;
1899            ## Reconsume.
1900            !!!emit ($self->{current_token}); # start tag or end tag
1901            redo A;
1902          } else {
1903            !!!cp ('124.4');
1904            !!!parse-error (type => 'nestc');
1905            ## TODO: This error type is wrong.
1906            $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;
1907            ## Reconsume.
1908            redo A;
1909          }
1910      } elsif ($self->{state} == BOGUS_COMMENT_STATE) {      } elsif ($self->{state} == BOGUS_COMMENT_STATE) {
1911        ## (only happen if PCDATA state)        ## (only happen if PCDATA state)
1912                
# Line 1667  sub _get_next_token ($) { Line 2014  sub _get_next_token ($) {
2014          } else {          } else {
2015            !!!cp (135);            !!!cp (135);
2016          }          }
2017          } elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM and
2018                   $self->{open_elements}->[-1]->[1] & FOREIGN_EL and
2019                   $self->{next_char} == 0x005B) { # [
2020            !!!next-input-character;
2021            push @next_char, $self->{next_char};
2022            if ($self->{next_char} == 0x0043) { # C
2023              !!!next-input-character;
2024              push @next_char, $self->{next_char};
2025              if ($self->{next_char} == 0x0044) { # D
2026                !!!next-input-character;
2027                push @next_char, $self->{next_char};
2028                if ($self->{next_char} == 0x0041) { # A
2029                  !!!next-input-character;
2030                  push @next_char, $self->{next_char};
2031                  if ($self->{next_char} == 0x0054) { # T
2032                    !!!next-input-character;
2033                    push @next_char, $self->{next_char};
2034                    if ($self->{next_char} == 0x0041) { # A
2035                      !!!next-input-character;
2036                      push @next_char, $self->{next_char};
2037                      if ($self->{next_char} == 0x005B) { # [
2038                        !!!cp (135.1);
2039                        $self->{state} = CDATA_BLOCK_STATE;
2040                        !!!next-input-character;
2041                        redo A;
2042                      } else {
2043                        !!!cp (135.2);
2044                      }
2045                    } else {
2046                      !!!cp (135.3);
2047                    }
2048                  } else {
2049                    !!!cp (135.4);                
2050                  }
2051                } else {
2052                  !!!cp (135.5);
2053                }
2054              } else {
2055                !!!cp (135.6);
2056              }
2057            } else {
2058              !!!cp (135.7);
2059            }
2060        } else {        } else {
2061          !!!cp (136);          !!!cp (136);
2062        }        }
# Line 2391  sub _get_next_token ($) { Line 2781  sub _get_next_token ($) {
2781          !!!next-input-character;          !!!next-input-character;
2782          redo A;          redo A;
2783        }        }
2784        } elsif ($self->{state} == CDATA_BLOCK_STATE) {
2785          my $s = '';
2786          
2787          my ($l, $c) = ($self->{line}, $self->{column});
2788    
2789          CS: while ($self->{next_char} != -1) {
2790            if ($self->{next_char} == 0x005D) { # ]
2791              !!!next-input-character;
2792              if ($self->{next_char} == 0x005D) { # ]
2793                !!!next-input-character;
2794                MDC: {
2795                  if ($self->{next_char} == 0x003E) { # >
2796                    !!!cp (221.1);
2797                    !!!next-input-character;
2798                    last CS;
2799                  } elsif ($self->{next_char} == 0x005D) { # ]
2800                    !!!cp (221.2);
2801                    $s .= ']';
2802                    !!!next-input-character;
2803                    redo MDC;
2804                  } else {
2805                    !!!cp (221.3);
2806                    $s .= ']]';
2807                    #
2808                  }
2809                } # MDC
2810              } else {
2811                !!!cp (221.4);
2812                $s .= ']';
2813                #
2814              }
2815            } else {
2816              !!!cp (221.5);
2817              #
2818            }
2819            $s .= chr $self->{next_char};
2820            !!!next-input-character;
2821          } # CS
2822    
2823          $self->{state} = DATA_STATE;
2824          ## next-input-character done or EOF, which is reconsumed.
2825    
2826          if (length $s) {
2827            !!!cp (221.6);
2828            !!!emit ({type => CHARACTER_TOKEN, data => $s,
2829                      line => $l, column => $c});
2830          } else {
2831            !!!cp (221.7);
2832          }
2833    
2834          redo A;
2835    
2836          ## ISSUE: "text tokens" in spec.
2837          ## TODO: Streaming support
2838      } else {      } else {
2839        die "$0: $self->{state}: Unknown state";        die "$0: $self->{state}: Unknown state";
2840      }      }
# Line 2541  sub _tokenize_attempt_to_consume_an_enti Line 2985  sub _tokenize_attempt_to_consume_an_enti
2985      require Whatpm::_NamedEntityList;      require Whatpm::_NamedEntityList;
2986      our $EntityChar;      our $EntityChar;
2987    
2988      while (length $entity_name < 10 and      while (length $entity_name < 30 and
2989             ## NOTE: Some number greater than the maximum length of entity name             ## NOTE: Some number greater than the maximum length of entity name
2990             ((0x0041 <= $self->{next_char} and # a             ((0x0041 <= $self->{next_char} and # a
2991               $self->{next_char} <= 0x005A) or # x               $self->{next_char} <= 0x005A) or # x
# Line 2821  sub _tree_construction_initial ($) { Line 3265  sub _tree_construction_initial ($) {
3265        $self->{document}->manakai_compat_mode ('quirks');        $self->{document}->manakai_compat_mode ('quirks');
3266        ## Go to the "before html" insertion mode.        ## Go to the "before html" insertion mode.
3267        ## reprocess        ## reprocess
3268          !!!ack-later;
3269        return;        return;
3270      } elsif ($token->{type} == CHARACTER_TOKEN) {      } elsif ($token->{type} == CHARACTER_TOKEN) {
3271        if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { # \x0D        if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { # \x0D
# Line 2901  sub _tree_construction_root_element ($) Line 3346  sub _tree_construction_root_element ($)
3346        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
3347          if ($token->{tag_name} eq 'html') {          if ($token->{tag_name} eq 'html') {
3348            my $root_element;            my $root_element;
3349            !!!create-element ($root_element, $token->{tag_name}, $token->{attributes}, $token);            !!!create-element ($root_element, $HTML_NS, $token->{tag_name}, $token->{attributes}, $token);
3350            $self->{document}->append_child ($root_element);            $self->{document}->append_child ($root_element);
3351            push @{$self->{open_elements}},            push @{$self->{open_elements}},
3352                [$root_element, $el_category->{html}];                [$root_element, $el_category->{html}];
# Line 2919  sub _tree_construction_root_element ($) Line 3364  sub _tree_construction_root_element ($)
3364              $self->{application_cache_selection}->(undef);              $self->{application_cache_selection}->(undef);
3365            }            }
3366    
3367              !!!nack ('t25c');
3368    
3369            !!!next-token;            !!!next-token;
3370            return; ## Go to the "before head" insertion mode.            return; ## Go to the "before head" insertion mode.
3371          } else {          } else {
# Line 2935  sub _tree_construction_root_element ($) Line 3382  sub _tree_construction_root_element ($)
3382          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
3383        }        }
3384    
3385      my $root_element; !!!create-element ($root_element, 'html',, $token);      my $root_element;
3386        !!!create-element ($root_element, $HTML_NS, 'html',, $token);
3387      $self->{document}->append_child ($root_element);      $self->{document}->append_child ($root_element);
3388      push @{$self->{open_elements}}, [$root_element, $el_category->{html}];      push @{$self->{open_elements}}, [$root_element, $el_category->{html}];
3389    
3390      $self->{application_cache_selection}->(undef);      $self->{application_cache_selection}->(undef);
3391    
3392      ## NOTE: Reprocess the token.      ## NOTE: Reprocess the token.
3393        !!!ack-later;
3394      return; ## Go to the "before head" insertion mode.      return; ## Go to the "before head" insertion mode.
3395    
3396      ## ISSUE: There is an issue in the spec      ## ISSUE: There is an issue in the spec
# Line 2965  sub _reset_insertion_mode ($) { Line 3414  sub _reset_insertion_mode ($) {
3414        if ($self->{open_elements}->[0]->[0] eq $node->[0]) {        if ($self->{open_elements}->[0]->[0] eq $node->[0]) {
3415          $last = 1;          $last = 1;
3416          if (defined $self->{inner_html_node}) {          if (defined $self->{inner_html_node}) {
3417            if ($self->{inner_html_node}->[1] & TABLE_CELL_EL) {            !!!cp ('t28');
3418              !!!cp ('t27');            $node = $self->{inner_html_node};
3419              #          } else {
3420            } else {            die "_reset_insertion_mode: t27";
             !!!cp ('t28');  
             $node = $self->{inner_html_node};  
           }  
3421          }          }
3422        }        }
3423              
3424        ## Step 4..13        ## Step 4..14
3425        my $new_mode = {        my $new_mode;
3426          if ($node->[1] & FOREIGN_EL) {
3427            !!!cp ('t28.1');
3428            ## NOTE: Strictly spaking, the line below only applies to MathML and
3429            ## SVG elements.  Currently the HTML syntax supports only MathML and
3430            ## SVG elements as foreigners.
3431            $new_mode = $self->{insertion_mode} | IN_FOREIGN_CONTENT_IM;
3432            ## ISSUE: What is set as the secondary insertion mode?
3433          } elsif ($node->[1] & TABLE_CELL_EL) {
3434            if ($last) {
3435              !!!cp ('t28.2');
3436              #
3437            } else {
3438              !!!cp ('t28.3');
3439              $new_mode = IN_CELL_IM;
3440            }
3441          } else {
3442            !!!cp ('t28.4');
3443            $new_mode = {
3444                        select => IN_SELECT_IM,                        select => IN_SELECT_IM,
3445                        ## NOTE: |option| and |optgroup| do not set                        ## NOTE: |option| and |optgroup| do not set
3446                        ## insertion mode to "in select" by themselves.                        ## insertion mode to "in select" by themselves.
                       td => IN_CELL_IM,  
                       th => IN_CELL_IM,  
3447                        tr => IN_ROW_IM,                        tr => IN_ROW_IM,
3448                        tbody => IN_TABLE_BODY_IM,                        tbody => IN_TABLE_BODY_IM,
3449                        thead => IN_TABLE_BODY_IM,                        thead => IN_TABLE_BODY_IM,
# Line 2993  sub _reset_insertion_mode ($) { Line 3455  sub _reset_insertion_mode ($) {
3455                        body => IN_BODY_IM,                        body => IN_BODY_IM,
3456                        frameset => IN_FRAMESET_IM,                        frameset => IN_FRAMESET_IM,
3457                       }->{$node->[0]->manakai_local_name};                       }->{$node->[0]->manakai_local_name};
3458                       ## TODO: Foreign namespace case OK?        }
3459        $self->{insertion_mode} = $new_mode and return if defined $new_mode;        $self->{insertion_mode} = $new_mode and return if defined $new_mode;
3460                
3461        ## Step 14        ## Step 15
3462        if ($node->[1] & HTML_EL) {        if ($node->[1] & HTML_EL) {
3463          unless (defined $self->{head_element}) {          unless (defined $self->{head_element}) {
3464            !!!cp ('t29');            !!!cp ('t29');
# Line 3011  sub _reset_insertion_mode ($) { Line 3473  sub _reset_insertion_mode ($) {
3473          !!!cp ('t31');          !!!cp ('t31');
3474        }        }
3475                
3476        ## Step 15        ## Step 16
3477        $self->{insertion_mode} = IN_BODY_IM and return if $last;        $self->{insertion_mode} = IN_BODY_IM and return if $last;
3478                
3479        ## Step 16        ## Step 17
3480        $i--;        $i--;
3481        $node = $self->{open_elements}->[$i];        $node = $self->{open_elements}->[$i];
3482                
3483        ## Step 17        ## Step 18
3484        redo S3;        redo S3;
3485      } # S3      } # S3
3486    
# Line 3130  sub _tree_construction_main ($) { Line 3592  sub _tree_construction_main ($) {
3592      ## Step 1      ## Step 1
3593      my $start_tag_name = $token->{tag_name};      my $start_tag_name = $token->{tag_name};
3594      my $el;      my $el;
3595      !!!create-element ($el, $start_tag_name, $token->{attributes}, $token);      !!!create-element ($el, $HTML_NS, $start_tag_name, $token->{attributes}, $token);
3596    
3597      ## Step 2      ## Step 2
3598      $insert->($el);      $insert->($el);
# Line 3141  sub _tree_construction_main ($) { Line 3603  sub _tree_construction_main ($) {
3603    
3604      ## Step 4      ## Step 4
3605      my $text = '';      my $text = '';
3606        !!!nack ('t40.1');
3607      !!!next-token;      !!!next-token;
3608      while ($token->{type} == CHARACTER_TOKEN) { # or until stop tokenizing      while ($token->{type} == CHARACTER_TOKEN) { # or until stop tokenizing
3609        !!!cp ('t40');        !!!cp ('t40');
# Line 3180  sub _tree_construction_main ($) { Line 3643  sub _tree_construction_main ($) {
3643    
3644    my $script_start_tag = sub () {    my $script_start_tag = sub () {
3645      my $script_el;      my $script_el;
3646      !!!create-element ($script_el, 'script', $token->{attributes}, $token);      !!!create-element ($script_el, $HTML_NS, 'script', $token->{attributes}, $token);
3647      ## TODO: mark as "parser-inserted"      ## TODO: mark as "parser-inserted"
3648    
3649      $self->{content_model} = CDATA_CONTENT_MODEL;      $self->{content_model} = CDATA_CONTENT_MODEL;
3650      delete $self->{escape}; # MUST      delete $self->{escape}; # MUST
3651            
3652      my $text = '';      my $text = '';
3653        !!!nack ('t45.1');
3654      !!!next-token;      !!!next-token;
3655      while ($token->{type} == CHARACTER_TOKEN) {      while ($token->{type} == CHARACTER_TOKEN) {
3656        !!!cp ('t45');        !!!cp ('t45');
# Line 3502  sub _tree_construction_main ($) { Line 3966  sub _tree_construction_main ($) {
3966      }      }
3967    }; # $insert_to_foster    }; # $insert_to_foster
3968    
3969    B: {    B: while (1) {
3970      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
3971        !!!cp ('t73');        !!!cp ('t73');
3972        !!!parse-error (type => 'DOCTYPE in the middle', token => $token);        !!!parse-error (type => 'DOCTYPE in the middle', token => $token);
3973        ## Ignore the token        ## Ignore the token
3974        ## Stay in the phase        ## Stay in the phase
3975        !!!next-token;        !!!next-token;
3976        redo B;        next B;
3977      } elsif ($token->{type} == START_TAG_TOKEN and      } elsif ($token->{type} == START_TAG_TOKEN and
3978               $token->{tag_name} eq 'html') {               $token->{tag_name} eq 'html') {
3979        if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {        if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
# Line 3535  sub _tree_construction_main ($) { Line 3999  sub _tree_construction_main ($) {
3999               $token->{attributes}->{$attr_name}->{value});               $token->{attributes}->{$attr_name}->{value});
4000          }          }
4001        }        }
4002          !!!nack ('t84.1');
4003        !!!next-token;        !!!next-token;
4004        redo B;        next B;
4005      } elsif ($token->{type} == COMMENT_TOKEN) {      } elsif ($token->{type} == COMMENT_TOKEN) {
4006        my $comment = $self->{document}->create_comment ($token->{data});        my $comment = $self->{document}->create_comment ($token->{data});
4007        if ($self->{insertion_mode} & AFTER_HTML_IMS) {        if ($self->{insertion_mode} & AFTER_HTML_IMS) {
# Line 3550  sub _tree_construction_main ($) { Line 4015  sub _tree_construction_main ($) {
4015          $self->{open_elements}->[-1]->[0]->append_child ($comment);          $self->{open_elements}->[-1]->[0]->append_child ($comment);
4016        }        }
4017        !!!next-token;        !!!next-token;
4018        redo B;        next B;
4019      } elsif ($self->{insertion_mode} & HEAD_IMS) {      } elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM) {
4020          if ($token->{type} == CHARACTER_TOKEN) {
4021            !!!cp ('t87.1');
4022            $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});
4023            !!!next-token;
4024            next B;
4025          } elsif ($token->{type} == START_TAG_TOKEN) {
4026            if ((not {mglyph => 1, malignmark => 1}->{$token->{tag_name}} and
4027                 $self->{open_elements}->[-1]->[1] & FOREIGN_FLOW_CONTENT_EL) or
4028                not ($self->{open_elements}->[-1]->[1] & FOREIGN_EL) or
4029                ($token->{tag_name} eq 'svg' and
4030                 $self->{open_elements}->[-1]->[1] & MML_AXML_EL)) {
4031              ## NOTE: "using the rules for secondary insertion mode"then"continue"
4032              !!!cp ('t87.2');
4033              #
4034            } elsif ({
4035                      b => 1, big => 1, blockquote => 1, body => 1, br => 1,
4036                      center => 1, code => 1, dd => 1, div => 1, dl => 1, em => 1,
4037                      embed => 1, font => 1, h1 => 1, h2 => 1, h3 => 1, ## No h4!
4038                      h5 => 1, h6 => 1, head => 1, hr => 1, i => 1, img => 1,
4039                      li => 1, menu => 1, meta => 1, nobr => 1, p => 1, pre => 1,
4040                      ruby => 1, s => 1, small => 1, span => 1, strong => 1,
4041                      sub => 1, sup => 1, table => 1, tt => 1, u => 1, ul => 1,
4042                      var => 1,
4043                     }->{$token->{tag_name}}) {
4044              !!!cp ('t87.2');
4045              !!!parse-error (type => 'not closed',
4046                              value => $self->{open_elements}->[-1]->[0]
4047                                  ->manakai_local_name,
4048                              token => $token);
4049    
4050              pop @{$self->{open_elements}}
4051                  while $self->{open_elements}->[-1]->[1] & FOREIGN_EL;
4052    
4053              $self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM;
4054              ## Reprocess.
4055              next B;
4056            } else {
4057              my $nsuri = $self->{open_elements}->[-1]->[0]->namespace_uri;
4058              my $tag_name = $token->{tag_name};
4059              if ($nsuri eq $SVG_NS) {
4060                $tag_name = {
4061                   altglyph => 'altGlyph',
4062                   altglyphdef => 'altGlyphDef',
4063                   altglyphitem => 'altGlyphItem',
4064                   animatecolor => 'animateColor',
4065                   animatemotion => 'animateMotion',
4066                   animatetransform => 'animateTransform',
4067                   clippath => 'clipPath',
4068                   feblend => 'feBlend',
4069                   fecolormatrix => 'feColorMatrix',
4070                   fecomponenttransfer => 'feComponentTransfer',
4071                   fecomposite => 'feComposite',
4072                   feconvolvematrix => 'feConvolveMatrix',
4073                   fediffuselighting => 'feDiffuseLighting',
4074                   fedisplacementmap => 'feDisplacementMap',
4075                   fedistantlight => 'feDistantLight',
4076                   feflood => 'feFlood',
4077                   fefunca => 'feFuncA',
4078                   fefuncb => 'feFuncB',
4079                   fefuncg => 'feFuncG',
4080                   fefuncr => 'feFuncR',
4081                   fegaussianblur => 'feGaussianBlur',
4082                   feimage => 'feImage',
4083                   femerge => 'feMerge',
4084                   femergenode => 'feMergeNode',
4085                   femorphology => 'feMorphology',
4086                   feoffset => 'feOffset',
4087                   fepointlight => 'fePointLight',
4088                   fespecularlighting => 'feSpecularLighting',
4089                   fespotlight => 'feSpotLight',
4090                   fetile => 'feTile',
4091                   feturbulence => 'feTurbulence',
4092                   foreignobject => 'foreignObject',
4093                   glyphref => 'glyphRef',
4094                   lineargradient => 'linearGradient',
4095                   radialgradient => 'radialGradient',
4096                   #solidcolor => 'solidColor', ## NOTE: Commented in spec (SVG1.2)
4097                   textpath => 'textPath',  
4098                }->{$tag_name} || $tag_name;
4099              }
4100    
4101              ## "adjust SVG attributes" (SVG only) - done in insert-element-f
4102    
4103              ## "adjust foreign attributes" - done in insert-element-f
4104    
4105              !!!insert-element-f ($nsuri, $tag_name, $token->{attributes}, $token);
4106    
4107              if ($self->{self_closing}) {
4108                pop @{$self->{open_elements}};
4109                !!!ack ('t87.3');
4110              } else {
4111                !!!cp ('t87.4');
4112              }
4113    
4114              !!!next-token;
4115              next B;
4116            }
4117          } elsif ($token->{type} == END_TAG_TOKEN) {
4118            ## NOTE: "using the rules for secondary insertion mode" then "continue"
4119            !!!cp ('t87.5');
4120            #
4121          } elsif ($token->{type} == END_OF_FILE_TOKEN) {
4122            ## NOTE: "using the rules for secondary insertion mode" then "continue"
4123            !!!cp ('t87.6');
4124            #
4125            ## TODO: ...
4126          } else {
4127            die "$0: $token->{type}: Unknown token type";        
4128          }
4129        }
4130    
4131        if ($self->{insertion_mode} & HEAD_IMS) {
4132        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
4133          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {
4134            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {
# Line 3561  sub _tree_construction_main ($) { Line 4138  sub _tree_construction_main ($) {
4138              !!!cp ('t88.1');              !!!cp ('t88.1');
4139              ## Ignore the token.              ## Ignore the token.
4140              !!!next-token;              !!!next-token;
4141              redo B;              next B;
4142            }            }
4143            unless (length $token->{data}) {            unless (length $token->{data}) {
4144              !!!cp ('t88');              !!!cp ('t88');
4145              !!!next-token;              !!!next-token;
4146              redo B;              next B;
4147            }            }
4148          }          }
4149    
4150          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4151            !!!cp ('t89');            !!!cp ('t89');
4152            ## As if <head>            ## As if <head>
4153            !!!create-element ($self->{head_element}, 'head',, $token);            !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
4154            $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});            $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
4155            push @{$self->{open_elements}},            push @{$self->{open_elements}},
4156                [$self->{head_element}, $el_category->{head}];                [$self->{head_element}, $el_category->{head}];
# Line 3607  sub _tree_construction_main ($) { Line 4184  sub _tree_construction_main ($) {
4184          !!!insert-element ('body',, $token);          !!!insert-element ('body',, $token);
4185          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
4186          ## reprocess          ## reprocess
4187          redo B;          next B;
4188        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
4189          if ($token->{tag_name} eq 'head') {          if ($token->{tag_name} eq 'head') {
4190            if ($self->{insertion_mode} == BEFORE_HEAD_IM) {            if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4191              !!!cp ('t93');              !!!cp ('t93');
4192              !!!create-element ($self->{head_element}, $token->{tag_name}, $token->{attributes}, $token);              !!!create-element ($self->{head_element}, $HTML_NS, $token->{tag_name}, $token->{attributes}, $token);
4193              $self->{open_elements}->[-1]->[0]->append_child              $self->{open_elements}->[-1]->[0]->append_child
4194                  ($self->{head_element});                  ($self->{head_element});
4195              push @{$self->{open_elements}},              push @{$self->{open_elements}},
4196                  [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4197              $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
4198                !!!nack ('t93.1');
4199              !!!next-token;              !!!next-token;
4200              redo B;              next B;
4201                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4202                  !!!cp ('t94');              !!!cp ('t93.2');
4203                  #              !!!parse-error (type => 'after head:head', token => $token); ## TODO: error type
4204                } else {              ## Ignore the token
4205                  !!!cp ('t95');              !!!nack ('t93.3');
4206                  !!!parse-error (type => 'in head:head', token => $token); # or in head noscript              !!!next-token;
4207                  ## Ignore the token              next B;
4208                  !!!next-token;            } else {
4209                  redo B;              !!!cp ('t95');
4210                }              !!!parse-error (type => 'in head:head', token => $token); # or in head noscript
4211              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {              ## Ignore the token
4212                !!!cp ('t96');              !!!nack ('t95.1');
4213                ## As if <head>              !!!next-token;
4214                !!!create-element ($self->{head_element}, 'head',, $token);              next B;
4215                $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});            }
4216                push @{$self->{open_elements}},          } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4217                    [$self->{head_element}, $el_category->{head}];            !!!cp ('t96');
4218              ## As if <head>
4219              !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
4220              $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
4221              push @{$self->{open_elements}},
4222                  [$self->{head_element}, $el_category->{head}];
4223    
4224                $self->{insertion_mode} = IN_HEAD_IM;            $self->{insertion_mode} = IN_HEAD_IM;
4225                ## Reprocess in the "in head" insertion mode...            ## Reprocess in the "in head" insertion mode...
4226              } else {          } else {
4227                !!!cp ('t97');            !!!cp ('t97');
4228              }          }
4229    
4230              if ($token->{tag_name} eq 'base') {              if ($token->{tag_name} eq 'base') {
4231                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
# Line 3670  sub _tree_construction_main ($) { Line 4253  sub _tree_construction_main ($) {
4253                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
4254                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
4255                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4256                  !!!nack ('t101.1');
4257                !!!next-token;                !!!next-token;
4258                redo B;                next B;
4259              } elsif ($token->{tag_name} eq 'link') {              } elsif ($token->{tag_name} eq 'link') {
4260                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
4261                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
# Line 3686  sub _tree_construction_main ($) { Line 4270  sub _tree_construction_main ($) {
4270                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
4271                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
4272                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4273                  !!!ack ('t103.1');
4274                !!!next-token;                !!!next-token;
4275                redo B;                next B;
4276              } elsif ($token->{tag_name} eq 'meta') {              } elsif ($token->{tag_name} eq 'meta') {
4277                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
4278                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
# Line 3702  sub _tree_construction_main ($) { Line 4287  sub _tree_construction_main ($) {
4287                my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.                my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
4288    
4289                unless ($self->{confident}) {                unless ($self->{confident}) {
4290                  if ($token->{attributes}->{charset}) { ## TODO: And if supported                  if ($token->{attributes}->{charset}) {
4291                    !!!cp ('t106');                    !!!cp ('t106');
4292                      ## NOTE: Whether the encoding is supported or not is handled
4293                      ## in the {change_encoding} callback.
4294                    $self->{change_encoding}                    $self->{change_encoding}
4295                        ->($self, $token->{attributes}->{charset}->{value},                        ->($self, $token->{attributes}->{charset}->{value},
4296                           $token);                           $token);
# Line 3713  sub _tree_construction_main ($) { Line 4300  sub _tree_construction_main ($) {
4300                                             $token->{attributes}->{charset}                                             $token->{attributes}->{charset}
4301                                                 ->{has_reference});                                                 ->{has_reference});
4302                  } elsif ($token->{attributes}->{content}) {                  } elsif ($token->{attributes}->{content}) {
                   ## ISSUE: Algorithm name in the spec was incorrect so that not linked to the definition.  
4303                    if ($token->{attributes}->{content}->{value}                    if ($token->{attributes}->{content}->{value}
4304                        =~ /\A[^;]*;[\x09-\x0D\x20]*[Cc][Hh][Aa][Rr][Ss][Ee][Tt]                        =~ /\A[^;]*;[\x09-\x0D\x20]*[Cc][Hh][Aa][Rr][Ss][Ee][Tt]
4305                            [\x09-\x0D\x20]*=                            [\x09-\x0D\x20]*=
4306                            [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                            [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
4307                            ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {                            ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {
4308                      !!!cp ('t107');                      !!!cp ('t107');
4309                        ## NOTE: Whether the encoding is supported or not is handled
4310                        ## in the {change_encoding} callback.
4311                      $self->{change_encoding}                      $self->{change_encoding}
4312                          ->($self, defined $1 ? $1 : defined $2 ? $2 : $3,                          ->($self, defined $1 ? $1 : defined $2 ? $2 : $3,
4313                             $token);                             $token);
# Line 3750  sub _tree_construction_main ($) { Line 4338  sub _tree_construction_main ($) {
4338    
4339                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
4340                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4341                  !!!ack ('t110.1');
4342                !!!next-token;                !!!next-token;
4343                redo B;                next B;
4344              } elsif ($token->{tag_name} eq 'title') {              } elsif ($token->{tag_name} eq 'title') {
4345                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4346                  !!!cp ('t111');                  !!!cp ('t111');
# Line 3776  sub _tree_construction_main ($) { Line 4365  sub _tree_construction_main ($) {
4365                $parse_rcdata->(RCDATA_CONTENT_MODEL);                $parse_rcdata->(RCDATA_CONTENT_MODEL);
4366                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
4367                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4368                redo B;                next B;
4369              } elsif ($token->{tag_name} eq 'style') {              } elsif ($token->{tag_name} eq 'style') {
4370                ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and                ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and
4371                ## insertion mode IN_HEAD_IM)                ## insertion mode IN_HEAD_IM)
# Line 3792  sub _tree_construction_main ($) { Line 4381  sub _tree_construction_main ($) {
4381                $parse_rcdata->(CDATA_CONTENT_MODEL);                $parse_rcdata->(CDATA_CONTENT_MODEL);
4382                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
4383                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4384                redo B;                next B;
4385              } elsif ($token->{tag_name} eq 'noscript') {              } elsif ($token->{tag_name} eq 'noscript') {
4386                if ($self->{insertion_mode} == IN_HEAD_IM) {                if ($self->{insertion_mode} == IN_HEAD_IM) {
4387                  !!!cp ('t116');                  !!!cp ('t116');
4388                  ## NOTE: and scripting is disalbed                  ## NOTE: and scripting is disalbed
4389                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4390                  $self->{insertion_mode} = IN_HEAD_NOSCRIPT_IM;                  $self->{insertion_mode} = IN_HEAD_NOSCRIPT_IM;
4391                    !!!nack ('t116.1');
4392                  !!!next-token;                  !!!next-token;
4393                  redo B;                  next B;
4394                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4395                  !!!cp ('t117');                  !!!cp ('t117');
4396                  !!!parse-error (type => 'in noscript:noscript', token => $token);                  !!!parse-error (type => 'in noscript:noscript', token => $token);
4397                  ## Ignore the token                  ## Ignore the token
4398                    !!!nack ('t117.1');
4399                  !!!next-token;                  !!!next-token;
4400                  redo B;                  next B;
4401                } else {                } else {
4402                  !!!cp ('t118');                  !!!cp ('t118');
4403                  #                  #
# Line 3833  sub _tree_construction_main ($) { Line 4424  sub _tree_construction_main ($) {
4424                $script_start_tag->();                $script_start_tag->();
4425                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
4426                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4427                redo B;                next B;
4428              } elsif ($token->{tag_name} eq 'body' or              } elsif ($token->{tag_name} eq 'body' or
4429                       $token->{tag_name} eq 'frameset') {                       $token->{tag_name} eq 'frameset') {
4430                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
# Line 3867  sub _tree_construction_main ($) { Line 4458  sub _tree_construction_main ($) {
4458                } else {                } else {
4459                  die "$0: tag name: $self->{tag_name}";                  die "$0: tag name: $self->{tag_name}";
4460                }                }
4461                  !!!nack ('t127.1');
4462                !!!next-token;                !!!next-token;
4463                redo B;                next B;
4464              } else {              } else {
4465                !!!cp ('t128');                !!!cp ('t128');
4466                #                #
# Line 3900  sub _tree_construction_main ($) { Line 4492  sub _tree_construction_main ($) {
4492              !!!insert-element ('body',, $token);              !!!insert-element ('body',, $token);
4493              $self->{insertion_mode} = IN_BODY_IM;              $self->{insertion_mode} = IN_BODY_IM;
4494              ## reprocess              ## reprocess
4495              redo B;              !!!ack-later;
4496                next B;
4497            } elsif ($token->{type} == END_TAG_TOKEN) {            } elsif ($token->{type} == END_TAG_TOKEN) {
4498              if ($token->{tag_name} eq 'head') {              if ($token->{tag_name} eq 'head') {
4499                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4500                  !!!cp ('t132');                  !!!cp ('t132');
4501                  ## As if <head>                  ## As if <head>
4502                  !!!create-element ($self->{head_element}, 'head',, $token);                  !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
4503                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
4504                  push @{$self->{open_elements}},                  push @{$self->{open_elements}},
4505                      [$self->{head_element}, $el_category->{head}];                      [$self->{head_element}, $el_category->{head}];
# Line 3915  sub _tree_construction_main ($) { Line 4508  sub _tree_construction_main ($) {
4508                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4509                  $self->{insertion_mode} = AFTER_HEAD_IM;                  $self->{insertion_mode} = AFTER_HEAD_IM;
4510                  !!!next-token;                  !!!next-token;
4511                  redo B;                  next B;
4512                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4513                  !!!cp ('t133');                  !!!cp ('t133');
4514                  ## As if </noscript>                  ## As if </noscript>
# Line 3926  sub _tree_construction_main ($) { Line 4519  sub _tree_construction_main ($) {
4519                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4520                  $self->{insertion_mode} = AFTER_HEAD_IM;                  $self->{insertion_mode} = AFTER_HEAD_IM;
4521                  !!!next-token;                  !!!next-token;
4522                  redo B;                  next B;
4523                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
4524                  !!!cp ('t134');                  !!!cp ('t134');
4525                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4526                  $self->{insertion_mode} = AFTER_HEAD_IM;                  $self->{insertion_mode} = AFTER_HEAD_IM;
4527                  !!!next-token;                  !!!next-token;
4528                  redo B;                  next B;
4529                  } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4530                    !!!cp ('t134.1');
4531                    !!!parse-error (type => 'unmatched end tag:head', token => $token);
4532                    ## Ignore the token
4533                    !!!next-token;
4534                    next B;
4535                } else {                } else {
4536                  !!!cp ('t135');                  die "$0: $self->{insertion_mode}: Unknown insertion mode";
                 #  
4537                }                }
4538              } elsif ($token->{tag_name} eq 'noscript') {              } elsif ($token->{tag_name} eq 'noscript') {
4539                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
# Line 3943  sub _tree_construction_main ($) { Line 4541  sub _tree_construction_main ($) {
4541                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4542                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
4543                  !!!next-token;                  !!!next-token;
4544                  redo B;                  next B;
4545                } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {                } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM or
4546                           $self->{insertion_mode} == AFTER_HEAD_IM) {
4547                  !!!cp ('t137');                  !!!cp ('t137');
4548                  !!!parse-error (type => 'unmatched end tag:noscript', token => $token);                  !!!parse-error (type => 'unmatched end tag:noscript', token => $token);
4549                  ## Ignore the token ## ISSUE: An issue in the spec.                  ## Ignore the token ## ISSUE: An issue in the spec.
4550                  !!!next-token;                  !!!next-token;
4551                  redo B;                  next B;
4552                } else {                } else {
4553                  !!!cp ('t138');                  !!!cp ('t138');
4554                  #                  #
# Line 3957  sub _tree_construction_main ($) { Line 4556  sub _tree_construction_main ($) {
4556              } elsif ({              } elsif ({
4557                        body => 1, html => 1,                        body => 1, html => 1,
4558                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
4559                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM or
4560                  !!!cp ('t139');                    $self->{insertion_mode} == IN_HEAD_IM or
4561                  ## As if <head>                    $self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
                 !!!create-element ($self->{head_element}, 'head',, $token);  
                 $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});  
                 push @{$self->{open_elements}},  
                     [$self->{head_element}, $el_category->{head}];  
   
                 $self->{insertion_mode} = IN_HEAD_IM;  
                 ## Reprocess in the "in head" insertion mode...  
               } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {  
4562                  !!!cp ('t140');                  !!!cp ('t140');
4563                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4564                  ## Ignore the token                  ## Ignore the token
4565                  !!!next-token;                  !!!next-token;
4566                  redo B;                  next B;
4567                  } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4568                    !!!cp ('t140.1');
4569                    !!!parse-error (type => 'unmatched end tag:' . $token->{tag_name}, token => $token);
4570                    ## Ignore the token
4571                    !!!next-token;
4572                    next B;
4573                } else {                } else {
4574                  !!!cp ('t141');                  die "$0: $self->{insertion_mode}: Unknown insertion mode";
4575                }                }
4576                              } elsif ($token->{tag_name} eq 'p') {
4577                #                !!!cp ('t142');
4578              } elsif ({                !!!parse-error (type => 'unmatched end tag:p', token => $token);
4579                        p => 1, br => 1,                ## Ignore the token
4580                       }->{$token->{tag_name}}) {                !!!next-token;
4581                  next B;
4582                } elsif ($token->{tag_name} eq 'br') {
4583                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4584                  !!!cp ('t142');                  !!!cp ('t142.2');
4585                  ## As if <head>                  ## (before head) as if <head>, (in head) as if </head>
4586                  !!!create-element ($self->{head_element}, 'head',, $token);                  !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
4587                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
4588                  push @{$self->{open_elements}},                  $self->{insertion_mode} = AFTER_HEAD_IM;
4589                      [$self->{head_element}, $el_category->{head}];    
4590                    ## Reprocess in the "after head" insertion mode...
4591                  } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
4592                    !!!cp ('t143.2');
4593                    ## As if </head>
4594                    pop @{$self->{open_elements}};
4595                    $self->{insertion_mode} = AFTER_HEAD_IM;
4596      
4597                    ## Reprocess in the "after head" insertion mode...
4598                  } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4599                    !!!cp ('t143.3');
4600                    ## ISSUE: Two parse errors for <head><noscript></br>
4601                    !!!parse-error (type => 'unmatched end tag:br', token => $token);
4602                    ## As if </noscript>
4603                    pop @{$self->{open_elements}};
4604                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
4605    
4606                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
4607                } else {                  ## As if </head>
4608                  !!!cp ('t143');                  pop @{$self->{open_elements}};
4609                }                  $self->{insertion_mode} = AFTER_HEAD_IM;
4610    
4611                #                  ## Reprocess in the "after head" insertion mode...
4612              } else {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4613                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                  !!!cp ('t143.4');
                 !!!cp ('t144');  
4614                  #                  #
4615                } else {                } else {
4616                  !!!cp ('t145');                  die "$0: $self->{insertion_mode}: Unknown insertion mode";
                 !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);  
                 ## Ignore the token  
                 !!!next-token;  
                 redo B;  
4617                }                }
4618    
4619                  ## ISSUE: does not agree with IE7 - it doesn't ignore </br>.
4620                  !!!parse-error (type => 'unmatched end tag:br', token => $token);
4621                  ## Ignore the token
4622                  !!!next-token;
4623                  next B;
4624                } else {
4625                  !!!cp ('t145');
4626                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4627                  ## Ignore the token
4628                  !!!next-token;
4629                  next B;
4630              }              }
4631    
4632              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
# Line 4032  sub _tree_construction_main ($) { Line 4652  sub _tree_construction_main ($) {
4652                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4653                ## Ignore the token ## ISSUE: An issue in the spec.                ## Ignore the token ## ISSUE: An issue in the spec.
4654                !!!next-token;                !!!next-token;
4655                redo B;                next B;
4656              } else {              } else {
4657                !!!cp ('t149');                !!!cp ('t149');
4658              }              }
# Line 4042  sub _tree_construction_main ($) { Line 4662  sub _tree_construction_main ($) {
4662              !!!insert-element ('body',, $token);              !!!insert-element ('body',, $token);
4663              $self->{insertion_mode} = IN_BODY_IM;              $self->{insertion_mode} = IN_BODY_IM;
4664              ## reprocess              ## reprocess
4665              redo B;              next B;
4666        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
4667          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4668            !!!cp ('t149.1');            !!!cp ('t149.1');
4669    
4670            ## NOTE: As if <head>            ## NOTE: As if <head>
4671            !!!create-element ($self->{head_element}, 'head',, $token);            !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
4672            $self->{open_elements}->[-1]->[0]->append_child            $self->{open_elements}->[-1]->[0]->append_child
4673                ($self->{head_element});                ($self->{head_element});
4674            #push @{$self->{open_elements}},            #push @{$self->{open_elements}},
# Line 4096  sub _tree_construction_main ($) { Line 4716  sub _tree_construction_main ($) {
4716          !!!insert-element ('body',, $token);          !!!insert-element ('body',, $token);
4717          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
4718          ## NOTE: Reprocess.          ## NOTE: Reprocess.
4719          redo B;          next B;
4720        } else {        } else {
4721          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
4722        }        }
# Line 4111  sub _tree_construction_main ($) { Line 4731  sub _tree_construction_main ($) {
4731              $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});              $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});
4732    
4733              !!!next-token;              !!!next-token;
4734              redo B;              next B;
4735            } elsif ($token->{type} == START_TAG_TOKEN) {            } elsif ($token->{type} == START_TAG_TOKEN) {
4736              if ({              if ({
4737                   caption => 1, col => 1, colgroup => 1, tbody => 1,                   caption => 1, col => 1, colgroup => 1, tbody => 1,
# Line 4125  sub _tree_construction_main ($) { Line 4745  sub _tree_construction_main ($) {
4745                      !!!cp ('t151');                      !!!cp ('t151');
4746    
4747                      ## Close the cell                      ## Close the cell
4748                      !!!back-token; # <?>                      !!!back-token; # <x>
4749                      $token = {type => END_TAG_TOKEN,                      $token = {type => END_TAG_TOKEN,
4750                                tag_name => $node->[0]->manakai_local_name,                                tag_name => $node->[0]->manakai_local_name,
4751                                line => $token->{line},                                line => $token->{line},
4752                                column => $token->{column}};                                column => $token->{column}};
4753                      redo B;                      next B;
4754                    } elsif ($node->[1] & TABLE_SCOPING_EL) {                    } elsif ($node->[1] & TABLE_SCOPING_EL) {
4755                      !!!cp ('t152');                      !!!cp ('t152');
4756                      ## ISSUE: This case can never be reached, maybe.                      ## ISSUE: This case can never be reached, maybe.
# Line 4142  sub _tree_construction_main ($) { Line 4762  sub _tree_construction_main ($) {
4762                  !!!parse-error (type => 'start tag not allowed',                  !!!parse-error (type => 'start tag not allowed',
4763                      value => $token->{tag_name}, token => $token);                      value => $token->{tag_name}, token => $token);
4764                  ## Ignore the token                  ## Ignore the token
4765                    !!!nack ('t153.1');
4766                  !!!next-token;                  !!!next-token;
4767                  redo B;                  next B;
4768                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {
4769                  !!!parse-error (type => 'not closed:caption', token => $token);                  !!!parse-error (type => 'not closed:caption', token => $token);
4770                                    
# Line 4167  sub _tree_construction_main ($) { Line 4788  sub _tree_construction_main ($) {
4788                    !!!parse-error (type => 'start tag not allowed',                    !!!parse-error (type => 'start tag not allowed',
4789                                    value => $token->{tag_name}, token => $token);                                    value => $token->{tag_name}, token => $token);
4790                    ## Ignore the token                    ## Ignore the token
4791                      !!!nack ('t157.1');
4792                    !!!next-token;                    !!!next-token;
4793                    redo B;                    next B;
4794                  } # INSCOPE                  } # INSCOPE
4795                                    
4796                  ## generate implied end tags                  ## generate implied end tags
# Line 4195  sub _tree_construction_main ($) { Line 4817  sub _tree_construction_main ($) {
4817                  $self->{insertion_mode} = IN_TABLE_IM;                  $self->{insertion_mode} = IN_TABLE_IM;
4818                                    
4819                  ## reprocess                  ## reprocess
4820                  redo B;                  !!!ack-later;
4821                    next B;
4822                } else {                } else {
4823                  !!!cp ('t161');                  !!!cp ('t161');
4824                  #                  #
# Line 4225  sub _tree_construction_main ($) { Line 4848  sub _tree_construction_main ($) {
4848                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4849                      ## Ignore the token                      ## Ignore the token
4850                      !!!next-token;                      !!!next-token;
4851                      redo B;                      next B;
4852                    }                    }
4853                                    
4854                  ## generate implied end tags                  ## generate implied end tags
# Line 4253  sub _tree_construction_main ($) { Line 4876  sub _tree_construction_main ($) {
4876                  $self->{insertion_mode} = IN_ROW_IM;                  $self->{insertion_mode} = IN_ROW_IM;
4877                                    
4878                  !!!next-token;                  !!!next-token;
4879                  redo B;                  next B;
4880                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {
4881                  !!!cp ('t169');                  !!!cp ('t169');
4882                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4883                  ## Ignore the token                  ## Ignore the token
4884                  !!!next-token;                  !!!next-token;
4885                  redo B;                  next B;
4886                } else {                } else {
4887                  !!!cp ('t170');                  !!!cp ('t170');
4888                  #                  #
# Line 4286  sub _tree_construction_main ($) { Line 4909  sub _tree_construction_main ($) {
4909                                    value => $token->{tag_name}, token => $token);                                    value => $token->{tag_name}, token => $token);
4910                    ## Ignore the token                    ## Ignore the token
4911                    !!!next-token;                    !!!next-token;
4912                    redo B;                    next B;
4913                  } # INSCOPE                  } # INSCOPE
4914                                    
4915                  ## generate implied end tags                  ## generate implied end tags
# Line 4313  sub _tree_construction_main ($) { Line 4936  sub _tree_construction_main ($) {
4936                  $self->{insertion_mode} = IN_TABLE_IM;                  $self->{insertion_mode} = IN_TABLE_IM;
4937                                    
4938                  !!!next-token;                  !!!next-token;
4939                  redo B;                  next B;
4940                } elsif ($self->{insertion_mode} == IN_CELL_IM) {                } elsif ($self->{insertion_mode} == IN_CELL_IM) {
4941                  !!!cp ('t177');                  !!!cp ('t177');
4942                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4943                  ## Ignore the token                  ## Ignore the token
4944                  !!!next-token;                  !!!next-token;
4945                  redo B;                  next B;
4946                } else {                } else {
4947                  !!!cp ('t178');                  !!!cp ('t178');
4948                  #                  #
# Line 4340  sub _tree_construction_main ($) { Line 4963  sub _tree_construction_main ($) {
4963                      $i = $_;                      $i = $_;
4964    
4965                      ## Close the cell                      ## Close the cell
4966                      !!!back-token; # </?>                      !!!back-token; # </x>
4967                      $token = {type => END_TAG_TOKEN, tag_name => $tn,                      $token = {type => END_TAG_TOKEN, tag_name => $tn,
4968                                line => $token->{line},                                line => $token->{line},
4969                                column => $token->{column}};                                column => $token->{column}};
4970                      redo B;                      next B;
4971                    } elsif ($node->[1] & TABLE_CELL_EL) {                    } elsif ($node->[1] & TABLE_CELL_EL) {
4972                      !!!cp ('t180');                      !!!cp ('t180');
4973                      $tn = $node->[0]->manakai_local_name;                      $tn = $node->[0]->manakai_local_name;
# Line 4362  sub _tree_construction_main ($) { Line 4985  sub _tree_construction_main ($) {
4985                      value => $token->{tag_name}, token => $token);                      value => $token->{tag_name}, token => $token);
4986                  ## Ignore the token                  ## Ignore the token
4987                  !!!next-token;                  !!!next-token;
4988                  redo B;                  next B;
4989                } # INSCOPE                } # INSCOPE
4990              } elsif ($token->{tag_name} eq 'table' and              } elsif ($token->{tag_name} eq 'table' and
4991                       $self->{insertion_mode} == IN_CAPTION_IM) {                       $self->{insertion_mode} == IN_CAPTION_IM) {
# Line 4387  sub _tree_construction_main ($) { Line 5010  sub _tree_construction_main ($) {
5010                  !!!parse-error (type => 'unmatched end tag:caption', token => $token);                  !!!parse-error (type => 'unmatched end tag:caption', token => $token);
5011                  ## Ignore the token                  ## Ignore the token
5012                  !!!next-token;                  !!!next-token;
5013                  redo B;                  next B;
5014                }                }
5015                                
5016                ## generate implied end tags                ## generate implied end tags
# Line 4413  sub _tree_construction_main ($) { Line 5036  sub _tree_construction_main ($) {
5036                $self->{insertion_mode} = IN_TABLE_IM;                $self->{insertion_mode} = IN_TABLE_IM;
5037    
5038                ## reprocess                ## reprocess
5039                redo B;                next B;
5040              } elsif ({              } elsif ({
5041                        body => 1, col => 1, colgroup => 1, html => 1,                        body => 1, col => 1, colgroup => 1, html => 1,
5042                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
# Line 4422  sub _tree_construction_main ($) { Line 5045  sub _tree_construction_main ($) {
5045                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5046                  ## Ignore the token                  ## Ignore the token
5047                  !!!next-token;                  !!!next-token;
5048                  redo B;                  next B;
5049                } else {                } else {
5050                  !!!cp ('t191');                  !!!cp ('t191');
5051                  #                  #
# Line 4436  sub _tree_construction_main ($) { Line 5059  sub _tree_construction_main ($) {
5059                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5060                ## Ignore the token                ## Ignore the token
5061                !!!next-token;                !!!next-token;
5062                redo B;                next B;
5063              } else {              } else {
5064                !!!cp ('t193');                !!!cp ('t193');
5065                #                #
# Line 4467  sub _tree_construction_main ($) { Line 5090  sub _tree_construction_main ($) {
5090            unless (length $token->{data}) {            unless (length $token->{data}) {
5091              !!!cp ('t194');              !!!cp ('t194');
5092              !!!next-token;              !!!next-token;
5093              redo B;              next B;
5094            } else {            } else {
5095              !!!cp ('t195');              !!!cp ('t195');
5096            }            }
# Line 4522  sub _tree_construction_main ($) { Line 5145  sub _tree_construction_main ($) {
5145          }          }
5146                            
5147          !!!next-token;          !!!next-token;
5148          redo B;          next B;
5149        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
5150              if ({              if ({
5151                   tr => ($self->{insertion_mode} != IN_ROW_IM),                   tr => ($self->{insertion_mode} != IN_ROW_IM),
# Line 4559  sub _tree_construction_main ($) { Line 5182  sub _tree_construction_main ($) {
5182                  if ($token->{tag_name} eq 'tr') {                  if ($token->{tag_name} eq 'tr') {
5183                    !!!cp ('t204');                    !!!cp ('t204');
5184                    !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                    !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5185                      !!!nack ('t204');
5186                    !!!next-token;                    !!!next-token;
5187                    redo B;                    next B;
5188                  } else {                  } else {
5189                    !!!cp ('t205');                    !!!cp ('t205');
5190                    !!!insert-element ('tr',, $token);                    !!!insert-element ('tr',, $token);
# Line 4582  sub _tree_construction_main ($) { Line 5206  sub _tree_construction_main ($) {
5206    
5207                push @$active_formatting_elements, ['#marker', ''];                push @$active_formatting_elements, ['#marker', ''];
5208                                
5209                  !!!nack ('t207.1');
5210                !!!next-token;                !!!next-token;
5211                redo B;                next B;
5212              } elsif ({              } elsif ({
5213                        caption => 1, col => 1, colgroup => 1,                        caption => 1, col => 1, colgroup => 1,
5214                        tbody => 1, tfoot => 1, thead => 1,                        tbody => 1, tfoot => 1, thead => 1,
# Line 4605  sub _tree_construction_main ($) { Line 5230  sub _tree_construction_main ($) {
5230                    }                    }
5231                  } # INSCOPE                  } # INSCOPE
5232                  unless (defined $i) {                  unless (defined $i) {
5233                   !!!cp ('t210');                    !!!cp ('t210');
5234  ## TODO: This type is wrong.  ## TODO: This type is wrong.
5235                   !!!parse-error (type => 'unmacthed end tag:'.$token->{tag_name}, token => $token);                    !!!parse-error (type => 'unmacthed end tag:'.$token->{tag_name}, token => $token);
5236                    ## Ignore the token                    ## Ignore the token
5237                      !!!nack ('t210.1');
5238                    !!!next-token;                    !!!next-token;
5239                    redo B;                    next B;
5240                  }                  }
5241                                    
5242                  ## Clear back to table row context                  ## Clear back to table row context
# Line 4626  sub _tree_construction_main ($) { Line 5252  sub _tree_construction_main ($) {
5252                  if ($token->{tag_name} eq 'tr') {                  if ($token->{tag_name} eq 'tr') {
5253                    !!!cp ('t212');                    !!!cp ('t212');
5254                    ## reprocess                    ## reprocess
5255                    redo B;                    !!!ack-later;
5256                      next B;
5257                  } else {                  } else {
5258                    !!!cp ('t213');                    !!!cp ('t213');
5259                    ## reprocess in the "in table body" insertion mode...                    ## reprocess in the "in table body" insertion mode...
# Line 4652  sub _tree_construction_main ($) { Line 5279  sub _tree_construction_main ($) {
5279  ## TODO: This erorr type ios wrong.  ## TODO: This erorr type ios wrong.
5280                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5281                    ## Ignore the token                    ## Ignore the token
5282                      !!!nack ('t216.1');
5283                    !!!next-token;                    !!!next-token;
5284                    redo B;                    next B;
5285                  }                  }
5286    
5287                  ## Clear back to table body context                  ## Clear back to table body context
# Line 4690  sub _tree_construction_main ($) { Line 5318  sub _tree_construction_main ($) {
5318                  !!!insert-element ('colgroup',, $token);                  !!!insert-element ('colgroup',, $token);
5319                  $self->{insertion_mode} = IN_COLUMN_GROUP_IM;                  $self->{insertion_mode} = IN_COLUMN_GROUP_IM;
5320                  ## reprocess                  ## reprocess
5321                  redo B;                  !!!ack-later;
5322                    next B;
5323                } elsif ({                } elsif ({
5324                          caption => 1,                          caption => 1,
5325                          colgroup => 1,                          colgroup => 1,
# Line 4716  sub _tree_construction_main ($) { Line 5345  sub _tree_construction_main ($) {
5345                                             thead => IN_TABLE_BODY_IM,                                             thead => IN_TABLE_BODY_IM,
5346                                            }->{$token->{tag_name}};                                            }->{$token->{tag_name}};
5347                  !!!next-token;                  !!!next-token;
5348                  redo B;                  !!!nack ('t220.1');
5349                    next B;
5350                } else {                } else {
5351                  die "$0: in table: <>: $token->{tag_name}";                  die "$0: in table: <>: $token->{tag_name}";
5352                }                }
# Line 4745  sub _tree_construction_main ($) { Line 5375  sub _tree_construction_main ($) {
5375  ## TODO: The following is wrong, maybe.  ## TODO: The following is wrong, maybe.
5376                  !!!parse-error (type => 'unmatched end tag:table', token => $token);                  !!!parse-error (type => 'unmatched end tag:table', token => $token);
5377                  ## Ignore tokens </table><table>                  ## Ignore tokens </table><table>
5378                    !!!nack ('t223.1');
5379                  !!!next-token;                  !!!next-token;
5380                  redo B;                  next B;
5381                }                }
5382                                
5383  ## TODO: Followings are removed from the latest spec.  ## TODO: Followings are removed from the latest spec.
# Line 4772  sub _tree_construction_main ($) { Line 5403  sub _tree_construction_main ($) {
5403    
5404                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
5405    
5406                ## reprocess            ## reprocess
5407                redo B;            !!!ack-later;
5408              next B;
5409          } elsif ($token->{tag_name} eq 'style') {          } elsif ($token->{tag_name} eq 'style') {
5410            if (not $open_tables->[-1]->[1]) { # tainted            if (not $open_tables->[-1]->[1]) { # tainted
5411              !!!cp ('t227.8');              !!!cp ('t227.8');
5412              ## NOTE: This is a "as if in head" code clone.              ## NOTE: This is a "as if in head" code clone.
5413              $parse_rcdata->(CDATA_CONTENT_MODEL);              $parse_rcdata->(CDATA_CONTENT_MODEL);
5414              redo B;              next B;
5415            } else {            } else {
5416              !!!cp ('t227.7');              !!!cp ('t227.7');
5417              #              #
# Line 4789  sub _tree_construction_main ($) { Line 5421  sub _tree_construction_main ($) {
5421              !!!cp ('t227.6');              !!!cp ('t227.6');
5422              ## NOTE: This is a "as if in head" code clone.              ## NOTE: This is a "as if in head" code clone.
5423              $script_start_tag->();              $script_start_tag->();
5424              redo B;              next B;
5425            } else {            } else {
5426              !!!cp ('t227.5');              !!!cp ('t227.5');
5427              #              #
# Line 4809  sub _tree_construction_main ($) { Line 5441  sub _tree_construction_main ($) {
5441                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
5442    
5443                  !!!next-token;                  !!!next-token;
5444                  redo B;                  !!!ack ('t227.2.1');
5445                    next B;
5446                } else {                } else {
5447                  !!!cp ('t227.2');                  !!!cp ('t227.2');
5448                  #                  #
# Line 4851  sub _tree_construction_main ($) { Line 5484  sub _tree_construction_main ($) {
5484                  !!!cp ('t230');                  !!!cp ('t230');
5485                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5486                  ## Ignore the token                  ## Ignore the token
5487                    !!!nack ('t230.1');
5488                  !!!next-token;                  !!!next-token;
5489                  redo B;                  next B;
5490                } else {                } else {
5491                  !!!cp ('t232');                  !!!cp ('t232');
5492                }                }
# Line 4868  sub _tree_construction_main ($) { Line 5502  sub _tree_construction_main ($) {
5502                pop @{$self->{open_elements}}; # tr                pop @{$self->{open_elements}}; # tr
5503                $self->{insertion_mode} = IN_TABLE_BODY_IM;                $self->{insertion_mode} = IN_TABLE_BODY_IM;
5504                !!!next-token;                !!!next-token;
5505                redo B;                !!!nack ('t231.1');
5506                  next B;
5507              } elsif ($token->{tag_name} eq 'table') {              } elsif ($token->{tag_name} eq 'table') {
5508                if ($self->{insertion_mode} == IN_ROW_IM) {                if ($self->{insertion_mode} == IN_ROW_IM) {
5509                  ## As if </tr>                  ## As if </tr>
# Line 4890  sub _tree_construction_main ($) { Line 5525  sub _tree_construction_main ($) {
5525  ## TODO: The following is wrong.  ## TODO: The following is wrong.
5526                    !!!parse-error (type => 'unmatched end tag:'.$token->{type}, token => $token);                    !!!parse-error (type => 'unmatched end tag:'.$token->{type}, token => $token);
5527                    ## Ignore the token                    ## Ignore the token
5528                      !!!nack ('t236.1');
5529                    !!!next-token;                    !!!next-token;
5530                    redo B;                    next B;
5531                  }                  }
5532                                    
5533                  ## Clear back to table row context                  ## Clear back to table row context
# Line 4925  sub _tree_construction_main ($) { Line 5561  sub _tree_construction_main ($) {
5561                    !!!cp ('t239');                    !!!cp ('t239');
5562                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5563                    ## Ignore the token                    ## Ignore the token
5564                      !!!nack ('t239.1');
5565                    !!!next-token;                    !!!next-token;
5566                    redo B;                    next B;
5567                  }                  }
5568                                    
5569                  ## Clear back to table body context                  ## Clear back to table body context
# Line 4970  sub _tree_construction_main ($) { Line 5607  sub _tree_construction_main ($) {
5607                  !!!cp ('t243');                  !!!cp ('t243');
5608                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5609                  ## Ignore the token                  ## Ignore the token
5610                    !!!nack ('t243.1');
5611                  !!!next-token;                  !!!next-token;
5612                  redo B;                  next B;
5613                }                }
5614                                    
5615                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
# Line 4980  sub _tree_construction_main ($) { Line 5618  sub _tree_construction_main ($) {
5618                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
5619                                
5620                !!!next-token;                !!!next-token;
5621                redo B;                next B;
5622              } elsif ({              } elsif ({
5623                        tbody => 1, tfoot => 1, thead => 1,                        tbody => 1, tfoot => 1, thead => 1,
5624                       }->{$token->{tag_name}} and                       }->{$token->{tag_name}} and
# Line 5003  sub _tree_construction_main ($) { Line 5641  sub _tree_construction_main ($) {
5641                      !!!cp ('t249');                      !!!cp ('t249');
5642                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5643                      ## Ignore the token                      ## Ignore the token
5644                        !!!nack ('t249.1');
5645                      !!!next-token;                      !!!next-token;
5646                      redo B;                      next B;
5647                    }                    }
5648                                    
5649                  ## As if </tr>                  ## As if </tr>
# Line 5025  sub _tree_construction_main ($) { Line 5664  sub _tree_construction_main ($) {
5664                      !!!cp ('t252');                      !!!cp ('t252');
5665                      !!!parse-error (type => 'unmatched end tag:tr', token => $token);                      !!!parse-error (type => 'unmatched end tag:tr', token => $token);
5666                      ## Ignore the token                      ## Ignore the token
5667                        !!!nack ('t252.1');
5668                      !!!next-token;                      !!!next-token;
5669                      redo B;                      next B;
5670                    }                    }
5671                                    
5672                  ## Clear back to table row context                  ## Clear back to table row context
# Line 5059  sub _tree_construction_main ($) { Line 5699  sub _tree_construction_main ($) {
5699                  !!!cp ('t256');                  !!!cp ('t256');
5700                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5701                  ## Ignore the token                  ## Ignore the token
5702                    !!!nack ('t256.1');
5703                  !!!next-token;                  !!!next-token;
5704                  redo B;                  next B;
5705                }                }
5706    
5707                ## Clear back to table body context                ## Clear back to table body context
# Line 5073  sub _tree_construction_main ($) { Line 5714  sub _tree_construction_main ($) {
5714    
5715                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5716                $self->{insertion_mode} = IN_TABLE_IM;                $self->{insertion_mode} = IN_TABLE_IM;
5717                  !!!nack ('t257.1');
5718                !!!next-token;                !!!next-token;
5719                redo B;                next B;
5720              } elsif ({              } elsif ({
5721                        body => 1, caption => 1, col => 1, colgroup => 1,                        body => 1, caption => 1, col => 1, colgroup => 1,
5722                        html => 1, td => 1, th => 1,                        html => 1, td => 1, th => 1,
5723                        tr => 1, # $self->{insertion_mode} == IN_ROW_IM                        tr => 1, # $self->{insertion_mode} == IN_ROW_IM
5724                        tbody => 1, tfoot => 1, thead => 1, # $self->{insertion_mode} == IN_TABLE_IM                        tbody => 1, tfoot => 1, thead => 1, # $self->{insertion_mode} == IN_TABLE_IM
5725                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
5726                !!!cp ('t258');            !!!cp ('t258');
5727                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5728                ## Ignore the token            ## Ignore the token
5729                !!!next-token;            !!!nack ('t258.1');
5730                redo B;             !!!next-token;
5731              next B;
5732          } else {          } else {
5733            !!!cp ('t259');            !!!cp ('t259');
5734            !!!parse-error (type => 'in table:/'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'in table:/'.$token->{tag_name}, token => $token);
# Line 5116  sub _tree_construction_main ($) { Line 5759  sub _tree_construction_main ($) {
5759                unless (length $token->{data}) {                unless (length $token->{data}) {
5760                  !!!cp ('t260');                  !!!cp ('t260');
5761                  !!!next-token;                  !!!next-token;
5762                  redo B;                  next B;
5763                }                }
5764              }              }
5765                            
# Line 5127  sub _tree_construction_main ($) { Line 5770  sub _tree_construction_main ($) {
5770                !!!cp ('t262');                !!!cp ('t262');
5771                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5772                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5773                  !!!ack ('t262.1');
5774                !!!next-token;                !!!next-token;
5775                redo B;                next B;
5776              } else {              } else {
5777                !!!cp ('t263');                !!!cp ('t263');
5778                #                #
# Line 5140  sub _tree_construction_main ($) { Line 5784  sub _tree_construction_main ($) {
5784                  !!!parse-error (type => 'unmatched end tag:colgroup', token => $token);                  !!!parse-error (type => 'unmatched end tag:colgroup', token => $token);
5785                  ## Ignore the token                  ## Ignore the token
5786                  !!!next-token;                  !!!next-token;
5787                  redo B;                  next B;
5788                } else {                } else {
5789                  !!!cp ('t265');                  !!!cp ('t265');
5790                  pop @{$self->{open_elements}}; # colgroup                  pop @{$self->{open_elements}}; # colgroup
5791                  $self->{insertion_mode} = IN_TABLE_IM;                  $self->{insertion_mode} = IN_TABLE_IM;
5792                  !!!next-token;                  !!!next-token;
5793                  redo B;                              next B;            
5794                }                }
5795              } elsif ($token->{tag_name} eq 'col') {              } elsif ($token->{tag_name} eq 'col') {
5796                !!!cp ('t266');                !!!cp ('t266');
5797                !!!parse-error (type => 'unmatched end tag:col', token => $token);                !!!parse-error (type => 'unmatched end tag:col', token => $token);
5798                ## Ignore the token                ## Ignore the token
5799                !!!next-token;                !!!next-token;
5800                redo B;                next B;
5801              } else {              } else {
5802                !!!cp ('t267');                !!!cp ('t267');
5803                #                #
# Line 5170  sub _tree_construction_main ($) { Line 5814  sub _tree_construction_main ($) {
5814            pop @{$self->{open_elements}}; # colgroup            pop @{$self->{open_elements}}; # colgroup
5815            $self->{insertion_mode} = IN_TABLE_IM;            $self->{insertion_mode} = IN_TABLE_IM;
5816            ## Reprocess.            ## Reprocess.
5817            redo B;            next B;
5818          }          }
5819        } else {        } else {
5820          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
# Line 5182  sub _tree_construction_main ($) { Line 5826  sub _tree_construction_main ($) {
5826  ## TODO: Wrong error type?  ## TODO: Wrong error type?
5827              !!!parse-error (type => 'unmatched end tag:colgroup', token => $token);              !!!parse-error (type => 'unmatched end tag:colgroup', token => $token);
5828              ## Ignore the token              ## Ignore the token
5829                !!!nack ('t269.1');
5830              !!!next-token;              !!!next-token;
5831              redo B;              next B;
5832            } else {            } else {
5833              !!!cp ('t270');              !!!cp ('t270');
5834              pop @{$self->{open_elements}}; # colgroup              pop @{$self->{open_elements}}; # colgroup
5835              $self->{insertion_mode} = IN_TABLE_IM;              $self->{insertion_mode} = IN_TABLE_IM;
5836                !!!ack-later;
5837              ## reprocess              ## reprocess
5838              redo B;              next B;
5839            }            }
5840      } elsif ($self->{insertion_mode} & SELECT_IMS) {      } elsif ($self->{insertion_mode} & SELECT_IMS) {
5841        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
5842          !!!cp ('t271');          !!!cp ('t271');
5843          $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});          $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});
5844          !!!next-token;          !!!next-token;
5845          redo B;          next B;
5846        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
5847          if ($token->{tag_name} eq 'option') {          if ($token->{tag_name} eq 'option') {
5848            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {
# Line 5208  sub _tree_construction_main ($) { Line 5854  sub _tree_construction_main ($) {
5854            }            }
5855    
5856            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5857              !!!nack ('t273.1');
5858            !!!next-token;            !!!next-token;
5859            redo B;            next B;
5860          } elsif ($token->{tag_name} eq 'optgroup') {          } elsif ($token->{tag_name} eq 'optgroup') {
5861            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {
5862              !!!cp ('t274');              !!!cp ('t274');
# Line 5228  sub _tree_construction_main ($) { Line 5875  sub _tree_construction_main ($) {
5875            }            }
5876    
5877            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5878              !!!nack ('t277.1');
5879            !!!next-token;            !!!next-token;
5880            redo B;            next B;
5881          } elsif ($token->{tag_name} eq 'select' or          } elsif ($token->{tag_name} eq 'select' or
5882                   $token->{tag_name} eq 'input' or                   $token->{tag_name} eq 'input' or
5883                   ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and                   ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and
# Line 5259  sub _tree_construction_main ($) { Line 5907  sub _tree_construction_main ($) {
5907              !!!cp ('t280');              !!!cp ('t280');
5908              !!!parse-error (type => 'unmatched end tag:select', token => $token);              !!!parse-error (type => 'unmatched end tag:select', token => $token);
5909              ## Ignore the token              ## Ignore the token
5910                !!!nack ('t280.1');
5911              !!!next-token;              !!!next-token;
5912              redo B;              next B;
5913            }            }
5914                                
5915            !!!cp ('t281');            !!!cp ('t281');
# Line 5269  sub _tree_construction_main ($) { Line 5918  sub _tree_construction_main ($) {
5918            $self->_reset_insertion_mode;            $self->_reset_insertion_mode;
5919    
5920            if ($token->{tag_name} eq 'select') {            if ($token->{tag_name} eq 'select') {
5921              !!!cp ('t281.2');              !!!nack ('t281.2');
5922              !!!next-token;              !!!next-token;
5923              redo B;              next B;
5924            } else {            } else {
5925              !!!cp ('t281.1');              !!!cp ('t281.1');
5926                !!!ack-later;
5927              ## Reprocess the token.              ## Reprocess the token.
5928              redo B;              next B;
5929            }            }
5930          } else {          } else {
5931            !!!cp ('t282');            !!!cp ('t282');
5932            !!!parse-error (type => 'in select:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'in select:'.$token->{tag_name}, token => $token);
5933            ## Ignore the token            ## Ignore the token
5934              !!!nack ('t282.1');
5935            !!!next-token;            !!!next-token;
5936            redo B;            next B;
5937          }          }
5938        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
5939          if ($token->{tag_name} eq 'optgroup') {          if ($token->{tag_name} eq 'optgroup') {
# Line 5299  sub _tree_construction_main ($) { Line 5950  sub _tree_construction_main ($) {
5950              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5951              ## Ignore the token              ## Ignore the token
5952            }            }
5953              !!!nack ('t285.1');
5954            !!!next-token;            !!!next-token;
5955            redo B;            next B;
5956          } elsif ($token->{tag_name} eq 'option') {          } elsif ($token->{tag_name} eq 'option') {
5957            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {
5958              !!!cp ('t286');              !!!cp ('t286');
# Line 5310  sub _tree_construction_main ($) { Line 5962  sub _tree_construction_main ($) {
5962              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5963              ## Ignore the token              ## Ignore the token
5964            }            }
5965              !!!nack ('t287.1');
5966            !!!next-token;            !!!next-token;
5967            redo B;            next B;
5968          } elsif ($token->{tag_name} eq 'select') {          } elsif ($token->{tag_name} eq 'select') {
5969            ## have an element in table scope            ## have an element in table scope
5970            my $i;            my $i;
# Line 5330  sub _tree_construction_main ($) { Line 5983  sub _tree_construction_main ($) {
5983              !!!cp ('t290');              !!!cp ('t290');
5984              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5985              ## Ignore the token              ## Ignore the token
5986                !!!nack ('t290.1');
5987              !!!next-token;              !!!next-token;
5988              redo B;              next B;
5989            }            }
5990                                
5991            !!!cp ('t291');            !!!cp ('t291');
# Line 5339  sub _tree_construction_main ($) { Line 5993  sub _tree_construction_main ($) {
5993    
5994            $self->_reset_insertion_mode;            $self->_reset_insertion_mode;
5995    
5996              !!!nack ('t291.1');
5997            !!!next-token;            !!!next-token;
5998            redo B;            next B;
5999          } elsif ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and          } elsif ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and
6000                   {                   {
6001                    caption => 1, table => 1, tbody => 1,                    caption => 1, table => 1, tbody => 1,
# Line 5365  sub _tree_construction_main ($) { Line 6020  sub _tree_construction_main ($) {
6020            unless (defined $i) {            unless (defined $i) {
6021              !!!cp ('t294');              !!!cp ('t294');
6022              ## Ignore the token              ## Ignore the token
6023                !!!nack ('t294.1');
6024              !!!next-token;              !!!next-token;
6025              redo B;              next B;
6026            }            }
6027                                
6028            ## As if </select>            ## As if </select>
# Line 5389  sub _tree_construction_main ($) { Line 6045  sub _tree_construction_main ($) {
6045  ## TODO: The following error type is correct?  ## TODO: The following error type is correct?
6046              !!!parse-error (type => 'unmatched end tag:select', token => $token);              !!!parse-error (type => 'unmatched end tag:select', token => $token);
6047              ## Ignore the </select> token              ## Ignore the </select> token
6048                !!!nack ('t297.1');
6049              !!!next-token; ## TODO: ok?              !!!next-token; ## TODO: ok?
6050              redo B;              next B;
6051            }            }
6052                                
6053            !!!cp ('t298');            !!!cp ('t298');
# Line 5398  sub _tree_construction_main ($) { Line 6055  sub _tree_construction_main ($) {
6055    
6056            $self->_reset_insertion_mode;            $self->_reset_insertion_mode;
6057    
6058              !!!ack-later;
6059            ## reprocess            ## reprocess
6060            redo B;            next B;
6061          } else {          } else {
6062            !!!cp ('t299');            !!!cp ('t299');
6063            !!!parse-error (type => 'in select:/'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'in select:/'.$token->{tag_name}, token => $token);
6064            ## Ignore the token            ## Ignore the token
6065              !!!nack ('t299.3');
6066            !!!next-token;            !!!next-token;
6067            redo B;            next B;
6068          }          }
6069        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
6070          unless ($self->{open_elements}->[-1]->[1] & HTML_EL and          unless ($self->{open_elements}->[-1]->[1] & HTML_EL and
# Line 5433  sub _tree_construction_main ($) { Line 6092  sub _tree_construction_main ($) {
6092            unless (length $token->{data}) {            unless (length $token->{data}) {
6093              !!!cp ('t300');              !!!cp ('t300');
6094              !!!next-token;              !!!next-token;
6095              redo B;              next B;
6096            }            }
6097          }          }
6098                    
# Line 5451  sub _tree_construction_main ($) { Line 6110  sub _tree_construction_main ($) {
6110    
6111          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
6112          ## reprocess          ## reprocess
6113          redo B;          next B;
6114        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
6115          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
6116            !!!cp ('t303');            !!!cp ('t303');
# Line 5466  sub _tree_construction_main ($) { Line 6125  sub _tree_construction_main ($) {
6125          !!!parse-error (type => 'after body:'.$token->{tag_name}, token => $token);          !!!parse-error (type => 'after body:'.$token->{tag_name}, token => $token);
6126    
6127          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
6128            !!!ack-later;
6129          ## reprocess          ## reprocess
6130          redo B;          next B;
6131        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
6132          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
6133            !!!cp ('t305');            !!!cp ('t305');
# Line 5486  sub _tree_construction_main ($) { Line 6146  sub _tree_construction_main ($) {
6146              !!!parse-error (type => 'unmatched end tag:html', token => $token);              !!!parse-error (type => 'unmatched end tag:html', token => $token);
6147              ## Ignore the token              ## Ignore the token
6148              !!!next-token;              !!!next-token;
6149              redo B;              next B;
6150            } else {            } else {
6151              !!!cp ('t308');              !!!cp ('t308');
6152              $self->{insertion_mode} = AFTER_HTML_BODY_IM;              $self->{insertion_mode} = AFTER_HTML_BODY_IM;
6153              !!!next-token;              !!!next-token;
6154              redo B;              next B;
6155            }            }
6156          } else {          } else {
6157            !!!cp ('t309');            !!!cp ('t309');
# Line 5499  sub _tree_construction_main ($) { Line 6159  sub _tree_construction_main ($) {
6159    
6160            $self->{insertion_mode} = IN_BODY_IM;            $self->{insertion_mode} = IN_BODY_IM;
6161            ## reprocess            ## reprocess
6162            redo B;            next B;
6163          }          }
6164        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
6165          !!!cp ('t309.2');          !!!cp ('t309.2');
# Line 5516  sub _tree_construction_main ($) { Line 6176  sub _tree_construction_main ($) {
6176            unless (length $token->{data}) {            unless (length $token->{data}) {
6177              !!!cp ('t310');              !!!cp ('t310');
6178              !!!next-token;              !!!next-token;
6179              redo B;              next B;
6180            }            }
6181          }          }
6182                    
# Line 5544  sub _tree_construction_main ($) { Line 6204  sub _tree_construction_main ($) {
6204              !!!cp ('t315');              !!!cp ('t315');
6205              !!!next-token;              !!!next-token;
6206            }            }
6207            redo B;            next B;
6208          }          }
6209                    
6210          die qq[$0: Character "$token->{data}"];          die qq[$0: Character "$token->{data}"];
# Line 5563  sub _tree_construction_main ($) { Line 6223  sub _tree_construction_main ($) {
6223              $self->{insertion_mode} == IN_FRAMESET_IM) {              $self->{insertion_mode} == IN_FRAMESET_IM) {
6224            !!!cp ('t318');            !!!cp ('t318');
6225            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
6226              !!!nack ('t318.1');
6227            !!!next-token;            !!!next-token;
6228            redo B;            next B;
6229          } elsif ($token->{tag_name} eq 'frame' and          } elsif ($token->{tag_name} eq 'frame' and
6230                   $self->{insertion_mode} == IN_FRAMESET_IM) {                   $self->{insertion_mode} == IN_FRAMESET_IM) {
6231            !!!cp ('t319');            !!!cp ('t319');
6232            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
6233            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
6234              !!!ack ('t319.1');
6235            !!!next-token;            !!!next-token;
6236            redo B;            next B;
6237          } elsif ($token->{tag_name} eq 'noframes') {          } elsif ($token->{tag_name} eq 'noframes') {
6238            !!!cp ('t320');            !!!cp ('t320');
6239            ## NOTE: As if in body.            ## NOTE: As if in body.
6240            $parse_rcdata->(CDATA_CONTENT_MODEL);            $parse_rcdata->(CDATA_CONTENT_MODEL);
6241            redo B;            next B;
6242          } else {          } else {
6243            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
6244              !!!cp ('t321');              !!!cp ('t321');
# Line 5586  sub _tree_construction_main ($) { Line 6248  sub _tree_construction_main ($) {
6248              !!!parse-error (type => 'after frameset:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'after frameset:'.$token->{tag_name}, token => $token);
6249            }            }
6250            ## Ignore the token            ## Ignore the token
6251              !!!nack ('t322.1');
6252            !!!next-token;            !!!next-token;
6253            redo B;            next B;
6254          }          }
6255        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
6256          if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {          if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {
# Line 5621  sub _tree_construction_main ($) { Line 6284  sub _tree_construction_main ($) {
6284            } else {            } else {
6285              !!!cp ('t328');              !!!cp ('t328');
6286            }            }
6287            redo B;            next B;
6288          } elsif ($token->{tag_name} eq 'html' and          } elsif ($token->{tag_name} eq 'html' and
6289                   $self->{insertion_mode} == AFTER_FRAMESET_IM) {                   $self->{insertion_mode} == AFTER_FRAMESET_IM) {
6290            !!!cp ('t329');            !!!cp ('t329');
6291            $self->{insertion_mode} = AFTER_HTML_FRAMESET_IM;            $self->{insertion_mode} = AFTER_HTML_FRAMESET_IM;
6292            !!!next-token;            !!!next-token;
6293            redo B;            next B;
6294          } else {          } else {
6295            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
6296              !!!cp ('t330');              !!!cp ('t330');
# Line 5638  sub _tree_construction_main ($) { Line 6301  sub _tree_construction_main ($) {
6301            }            }
6302            ## Ignore the token            ## Ignore the token
6303            !!!next-token;            !!!next-token;
6304            redo B;            next B;
6305          }          }
6306        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
6307          unless ($self->{open_elements}->[-1]->[1] & HTML_EL and          unless ($self->{open_elements}->[-1]->[1] & HTML_EL and
# Line 5666  sub _tree_construction_main ($) { Line 6329  sub _tree_construction_main ($) {
6329          !!!cp ('t332');          !!!cp ('t332');
6330          ## NOTE: This is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone
6331          $script_start_tag->();          $script_start_tag->();
6332          redo B;          next B;
6333        } elsif ($token->{tag_name} eq 'style') {        } elsif ($token->{tag_name} eq 'style') {
6334          !!!cp ('t333');          !!!cp ('t333');
6335          ## NOTE: This is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone
6336          $parse_rcdata->(CDATA_CONTENT_MODEL);          $parse_rcdata->(CDATA_CONTENT_MODEL);
6337          redo B;          next B;
6338        } elsif ({        } elsif ({
6339                  base => 1, link => 1,                  base => 1, link => 1,
6340                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 5679  sub _tree_construction_main ($) { Line 6342  sub _tree_construction_main ($) {
6342          ## NOTE: This is an "as if in head" code clone, only "-t" differs          ## NOTE: This is an "as if in head" code clone, only "-t" differs
6343          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6344          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
6345            !!!ack ('t334.1');
6346          !!!next-token;          !!!next-token;
6347          redo B;          next B;
6348        } elsif ($token->{tag_name} eq 'meta') {        } elsif ($token->{tag_name} eq 'meta') {
6349          ## NOTE: This is an "as if in head" code clone, only "-t" differs          ## NOTE: This is an "as if in head" code clone, only "-t" differs
6350          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6351          my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
6352    
6353          unless ($self->{confident}) {          unless ($self->{confident}) {
6354            if ($token->{attributes}->{charset}) { ## TODO: And if supported            if ($token->{attributes}->{charset}) {
6355              !!!cp ('t335');              !!!cp ('t335');
6356                ## NOTE: Whether the encoding is supported or not is handled
6357                ## in the {change_encoding} callback.
6358              $self->{change_encoding}              $self->{change_encoding}
6359                  ->($self, $token->{attributes}->{charset}->{value}, $token);                  ->($self, $token->{attributes}->{charset}->{value}, $token);
6360                            
# Line 5697  sub _tree_construction_main ($) { Line 6363  sub _tree_construction_main ($) {
6363                                       $token->{attributes}->{charset}                                       $token->{attributes}->{charset}
6364                                           ->{has_reference});                                           ->{has_reference});
6365            } elsif ($token->{attributes}->{content}) {            } elsif ($token->{attributes}->{content}) {
             ## ISSUE: Algorithm name in the spec was incorrect so that not linked to the definition.  
6366              if ($token->{attributes}->{content}->{value}              if ($token->{attributes}->{content}->{value}
6367                  =~ /\A[^;]*;[\x09-\x0D\x20]*[Cc][Hh][Aa][Rr][Ss][Ee][Tt]                  =~ /\A[^;]*;[\x09-\x0D\x20]*[Cc][Hh][Aa][Rr][Ss][Ee][Tt]
6368                      [\x09-\x0D\x20]*=                      [\x09-\x0D\x20]*=
6369                      [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                      [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
6370                      ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {                      ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {
6371                !!!cp ('t336');                !!!cp ('t336');
6372                  ## NOTE: Whether the encoding is supported or not is handled
6373                  ## in the {change_encoding} callback.
6374                $self->{change_encoding}                $self->{change_encoding}
6375                    ->($self, defined $1 ? $1 : defined $2 ? $2 : $3, $token);                    ->($self, defined $1 ? $1 : defined $2 ? $2 : $3, $token);
6376                $meta_el->[0]->get_attribute_node_ns (undef, 'content')                $meta_el->[0]->get_attribute_node_ns (undef, 'content')
# Line 5729  sub _tree_construction_main ($) { Line 6396  sub _tree_construction_main ($) {
6396            }            }
6397          }          }
6398    
6399            !!!ack ('t338.1');
6400          !!!next-token;          !!!next-token;
6401          redo B;          next B;
6402        } elsif ($token->{tag_name} eq 'title') {        } elsif ($token->{tag_name} eq 'title') {
6403          !!!cp ('t341');          !!!cp ('t341');
6404          ## NOTE: This is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone
6405          $parse_rcdata->(RCDATA_CONTENT_MODEL);          $parse_rcdata->(RCDATA_CONTENT_MODEL);
6406          redo B;          next B;
6407        } elsif ($token->{tag_name} eq 'body') {        } elsif ($token->{tag_name} eq 'body') {
6408          !!!parse-error (type => 'in body:body', token => $token);          !!!parse-error (type => 'in body:body', token => $token);
6409                                
# Line 5754  sub _tree_construction_main ($) { Line 6422  sub _tree_construction_main ($) {
6422              }              }
6423            }            }
6424          }          }
6425            !!!nack ('t343.1');
6426          !!!next-token;          !!!next-token;
6427          redo B;          next B;
6428        } elsif ({        } elsif ({
6429                  address => 1, blockquote => 1, center => 1, dir => 1,                  address => 1, blockquote => 1, center => 1, dir => 1,
6430                  div => 1, dl => 1, fieldset => 1,                  div => 1, dl => 1, fieldset => 1,
# Line 5770  sub _tree_construction_main ($) { Line 6439  sub _tree_construction_main ($) {
6439            !!!cp ('t350');            !!!cp ('t350');
6440            !!!parse-error (type => 'in form:form', token => $token);            !!!parse-error (type => 'in form:form', token => $token);
6441            ## Ignore the token            ## Ignore the token
6442              !!!nack ('t350.1');
6443            !!!next-token;            !!!next-token;
6444            redo B;            next B;
6445          }          }
6446    
6447          ## has a p element in scope          ## has a p element in scope
6448          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
6449            if ($_->[1] & P_EL) {            if ($_->[1] & P_EL) {
6450              !!!cp ('t344');              !!!cp ('t344');
6451              !!!back-token;              !!!back-token; # <form>
6452              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
6453                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
6454              redo B;              next B;
6455            } elsif ($_->[1] & SCOPING_EL) {            } elsif ($_->[1] & SCOPING_EL) {
6456              !!!cp ('t345');              !!!cp ('t345');
6457              last INSCOPE;              last INSCOPE;
# Line 5790  sub _tree_construction_main ($) { Line 6460  sub _tree_construction_main ($) {
6460                        
6461          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6462          if ($token->{tag_name} eq 'pre' or $token->{tag_name} eq 'listing') {          if ($token->{tag_name} eq 'pre' or $token->{tag_name} eq 'listing') {
6463              !!!nack ('t346.1');
6464            !!!next-token;            !!!next-token;
6465            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
6466              $token->{data} =~ s/^\x0A//;              $token->{data} =~ s/^\x0A//;
# Line 5806  sub _tree_construction_main ($) { Line 6477  sub _tree_construction_main ($) {
6477            !!!cp ('t347.1');            !!!cp ('t347.1');
6478            $self->{form_element} = $self->{open_elements}->[-1]->[0];            $self->{form_element} = $self->{open_elements}->[-1]->[0];
6479    
6480              !!!nack ('t347.2');
6481            !!!next-token;            !!!next-token;
6482          } elsif ($token->{tag_name} eq 'table') {          } elsif ($token->{tag_name} eq 'table') {
6483            !!!cp ('t382');            !!!cp ('t382');
# Line 5813  sub _tree_construction_main ($) { Line 6485  sub _tree_construction_main ($) {
6485                        
6486            $self->{insertion_mode} = IN_TABLE_IM;            $self->{insertion_mode} = IN_TABLE_IM;
6487    
6488              !!!nack ('t382.1');
6489            !!!next-token;            !!!next-token;
6490          } elsif ($token->{tag_name} eq 'hr') {          } elsif ($token->{tag_name} eq 'hr') {
6491            !!!cp ('t386');            !!!cp ('t386');
6492            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
6493                    
6494              !!!nack ('t386.1');
6495            !!!next-token;            !!!next-token;
6496          } else {          } else {
6497            !!!cp ('t347');            !!!nack ('t347.1');
6498            !!!next-token;            !!!next-token;
6499          }          }
6500          redo B;          next B;
6501        } elsif ({li => 1, dt => 1, dd => 1}->{$token->{tag_name}}) {        } elsif ({li => 1, dt => 1, dd => 1}->{$token->{tag_name}}) {
6502          ## has a p element in scope          ## has a p element in scope
6503          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
6504            if ($_->[1] & P_EL) {            if ($_->[1] & P_EL) {
6505              !!!cp ('t353');              !!!cp ('t353');
6506              !!!back-token;              !!!back-token; # <x>
6507              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
6508                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
6509              redo B;              next B;
6510            } elsif ($_->[1] & SCOPING_EL) {            } elsif ($_->[1] & SCOPING_EL) {
6511              !!!cp ('t354');              !!!cp ('t354');
6512              last INSCOPE;              last INSCOPE;
# Line 5882  sub _tree_construction_main ($) { Line 6556  sub _tree_construction_main ($) {
6556          } # LI          } # LI
6557                        
6558          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6559            !!!nack ('t359.1');
6560          !!!next-token;          !!!next-token;
6561          redo B;          next B;
6562        } elsif ($token->{tag_name} eq 'plaintext') {        } elsif ($token->{tag_name} eq 'plaintext') {
6563          ## has a p element in scope          ## has a p element in scope
6564          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
6565            if ($_->[1] & P_EL) {            if ($_->[1] & P_EL) {
6566              !!!cp ('t367');              !!!cp ('t367');
6567              !!!back-token;              !!!back-token; # <plaintext>
6568              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
6569                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
6570              redo B;              next B;
6571            } elsif ($_->[1] & SCOPING_EL) {            } elsif ($_->[1] & SCOPING_EL) {
6572              !!!cp ('t368');              !!!cp ('t368');
6573              last INSCOPE;              last INSCOPE;
# Line 5903  sub _tree_construction_main ($) { Line 6578  sub _tree_construction_main ($) {
6578                        
6579          $self->{content_model} = PLAINTEXT_CONTENT_MODEL;          $self->{content_model} = PLAINTEXT_CONTENT_MODEL;
6580                        
6581            !!!nack ('t368.1');
6582          !!!next-token;          !!!next-token;
6583          redo B;          next B;
6584        } elsif ($token->{tag_name} eq 'a') {        } elsif ($token->{tag_name} eq 'a') {
6585          AFE: for my $i (reverse 0..$#$active_formatting_elements) {          AFE: for my $i (reverse 0..$#$active_formatting_elements) {
6586            my $node = $active_formatting_elements->[$i];            my $node = $active_formatting_elements->[$i];
# Line 5912  sub _tree_construction_main ($) { Line 6588  sub _tree_construction_main ($) {
6588              !!!cp ('t371');              !!!cp ('t371');
6589              !!!parse-error (type => 'in a:a', token => $token);              !!!parse-error (type => 'in a:a', token => $token);
6590                            
6591              !!!back-token;              !!!back-token; # <a>
6592              $token = {type => END_TAG_TOKEN, tag_name => 'a',              $token = {type => END_TAG_TOKEN, tag_name => 'a',
6593                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
6594              $formatting_end_tag->($token);              $formatting_end_tag->($token);
# Line 5943  sub _tree_construction_main ($) { Line 6619  sub _tree_construction_main ($) {
6619          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6620          push @$active_formatting_elements, $self->{open_elements}->[-1];          push @$active_formatting_elements, $self->{open_elements}->[-1];
6621    
6622            !!!nack ('t374.1');
6623          !!!next-token;          !!!next-token;
6624          redo B;          next B;
6625        } elsif ($token->{tag_name} eq 'nobr') {        } elsif ($token->{tag_name} eq 'nobr') {
6626          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
6627    
# Line 5954  sub _tree_construction_main ($) { Line 6631  sub _tree_construction_main ($) {
6631            if ($node->[1] & NOBR_EL) {            if ($node->[1] & NOBR_EL) {
6632              !!!cp ('t376');              !!!cp ('t376');
6633              !!!parse-error (type => 'in nobr:nobr', token => $token);              !!!parse-error (type => 'in nobr:nobr', token => $token);
6634              !!!back-token;              !!!back-token; # <nobr>
6635              $token = {type => END_TAG_TOKEN, tag_name => 'nobr',              $token = {type => END_TAG_TOKEN, tag_name => 'nobr',
6636                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
6637              redo B;              next B;
6638            } elsif ($node->[1] & SCOPING_EL) {            } elsif ($node->[1] & SCOPING_EL) {
6639              !!!cp ('t377');              !!!cp ('t377');
6640              last INSCOPE;              last INSCOPE;
# Line 5967  sub _tree_construction_main ($) { Line 6644  sub _tree_construction_main ($) {
6644          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6645          push @$active_formatting_elements, $self->{open_elements}->[-1];          push @$active_formatting_elements, $self->{open_elements}->[-1];
6646                    
6647            !!!nack ('t377.1');
6648          !!!next-token;          !!!next-token;
6649          redo B;          next B;
6650        } elsif ($token->{tag_name} eq 'button') {        } elsif ($token->{tag_name} eq 'button') {
6651          ## has a button element in scope          ## has a button element in scope
6652          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
# Line 5976  sub _tree_construction_main ($) { Line 6654  sub _tree_construction_main ($) {
6654            if ($node->[1] & BUTTON_EL) {            if ($node->[1] & BUTTON_EL) {
6655              !!!cp ('t378');              !!!cp ('t378');
6656              !!!parse-error (type => 'in button:button', token => $token);              !!!parse-error (type => 'in button:button', token => $token);
6657              !!!back-token;              !!!back-token; # <button>
6658              $token = {type => END_TAG_TOKEN, tag_name => 'button',              $token = {type => END_TAG_TOKEN, tag_name => 'button',
6659                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
6660              redo B;              next B;
6661            } elsif ($node->[1] & SCOPING_EL) {            } elsif ($node->[1] & SCOPING_EL) {
6662              !!!cp ('t379');              !!!cp ('t379');
6663              last INSCOPE;              last INSCOPE;
# Line 5994  sub _tree_construction_main ($) { Line 6672  sub _tree_construction_main ($) {
6672    
6673          push @$active_formatting_elements, ['#marker', ''];          push @$active_formatting_elements, ['#marker', ''];
6674    
6675            !!!nack ('t379.1');
6676          !!!next-token;          !!!next-token;
6677          redo B;          next B;
6678        } elsif ({        } elsif ({
6679                  xmp => 1,                  xmp => 1,
6680                  iframe => 1,                  iframe => 1,
# Line 6011  sub _tree_construction_main ($) { Line 6690  sub _tree_construction_main ($) {
6690          }          }
6691          ## NOTE: There is an "as if in body" code clone.          ## NOTE: There is an "as if in body" code clone.
6692          $parse_rcdata->(CDATA_CONTENT_MODEL);          $parse_rcdata->(CDATA_CONTENT_MODEL);
6693          redo B;          next B;
6694        } elsif ($token->{tag_name} eq 'isindex') {        } elsif ($token->{tag_name} eq 'isindex') {
6695          !!!parse-error (type => 'isindex', token => $token);          !!!parse-error (type => 'isindex', token => $token);
6696                    
6697          if (defined $self->{form_element}) {          if (defined $self->{form_element}) {
6698            !!!cp ('t389');            !!!cp ('t389');
6699            ## Ignore the token            ## Ignore the token
6700              !!!nack ('t389'); ## NOTE: Not acknowledged.
6701            !!!next-token;            !!!next-token;
6702            redo B;            next B;
6703          } else {          } else {
6704            my $at = $token->{attributes};            my $at = $token->{attributes};
6705            my $form_attrs;            my $form_attrs;
# Line 6064  sub _tree_construction_main ($) { Line 6744  sub _tree_construction_main ($) {
6744                           line => $token->{line}, column => $token->{column}},                           line => $token->{line}, column => $token->{column}},
6745                          {type => END_TAG_TOKEN, tag_name => 'form',                          {type => END_TAG_TOKEN, tag_name => 'form',
6746                           line => $token->{line}, column => $token->{column}};                           line => $token->{line}, column => $token->{column}};
6747            $token = shift @tokens;            !!!nack ('t391.1'); ## NOTE: Not acknowledged.
6748            !!!back-token (@tokens);            !!!back-token (@tokens);
6749            redo B;            !!!next-token;
6750              next B;
6751          }          }
6752        } elsif ($token->{tag_name} eq 'textarea') {        } elsif ($token->{tag_name} eq 'textarea') {
6753          my $tag_name = $token->{tag_name};          my $tag_name = $token->{tag_name};
6754          my $el;          my $el;
6755          !!!create-element ($el, $token->{tag_name}, $token->{attributes}, $token);          !!!create-element ($el, $HTML_NS, $token->{tag_name}, $token->{attributes}, $token);
6756                    
6757          ## TODO: $self->{form_element} if defined          ## TODO: $self->{form_element} if defined
6758          $self->{content_model} = RCDATA_CONTENT_MODEL;          $self->{content_model} = RCDATA_CONTENT_MODEL;
# Line 6080  sub _tree_construction_main ($) { Line 6761  sub _tree_construction_main ($) {
6761          $insert->($el);          $insert->($el);
6762                    
6763          my $text = '';          my $text = '';
6764            !!!nack ('t392.1');
6765          !!!next-token;          !!!next-token;
6766          if ($token->{type} == CHARACTER_TOKEN) {          if ($token->{type} == CHARACTER_TOKEN) {
6767            $token->{data} =~ s/^\x0A//;            $token->{data} =~ s/^\x0A//;
# Line 6113  sub _tree_construction_main ($) { Line 6795  sub _tree_construction_main ($) {
6795            !!!parse-error (type => 'in RCDATA:#'.$token->{type}, token => $token);            !!!parse-error (type => 'in RCDATA:#'.$token->{type}, token => $token);
6796          }          }
6797          !!!next-token;          !!!next-token;
6798          redo B;          next B;
6799          } elsif ($token->{tag_name} eq 'math' or
6800                   $token->{tag_name} eq 'svg') {
6801            $reconstruct_active_formatting_elements->($insert_to_current);
6802    
6803            ## "adjust SVG attributes" ('svg' only) - done in insert-element-f
6804    
6805            ## "adjust foreign attributes" - done in insert-element-f
6806            
6807            !!!insert-element-f ($token->{tag_name} eq 'math' ? $MML_NS : $SVG_NS, $token->{tag_name}, $token->{attributes}, $token);
6808            
6809            if ($self->{self_closing}) {
6810              pop @{$self->{open_elements}};
6811              !!!ack ('t398.1');
6812            } else {
6813              !!!cp ('t398.2');
6814              $self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM;
6815              ## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion
6816              ## mode, "in body" (not "in foreign content") secondary insertion
6817              ## mode, maybe.
6818            }
6819    
6820            !!!next-token;
6821            next B;
6822        } elsif ({        } elsif ({
6823                  caption => 1, col => 1, colgroup => 1, frame => 1,                  caption => 1, col => 1, colgroup => 1, frame => 1,
6824                  frameset => 1, head => 1, option => 1, optgroup => 1,                  frameset => 1, head => 1, option => 1, optgroup => 1,
# Line 6123  sub _tree_construction_main ($) { Line 6828  sub _tree_construction_main ($) {
6828          !!!cp ('t401');          !!!cp ('t401');
6829          !!!parse-error (type => 'in body:'.$token->{tag_name}, token => $token);          !!!parse-error (type => 'in body:'.$token->{tag_name}, token => $token);
6830          ## Ignore the token          ## Ignore the token
6831            !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.
6832          !!!next-token;          !!!next-token;
6833          redo B;          next B;
6834                    
6835          ## ISSUE: An issue on HTML5 new elements in the spec.          ## ISSUE: An issue on HTML5 new elements in the spec.
6836        } else {        } else {
# Line 6146  sub _tree_construction_main ($) { Line 6852  sub _tree_construction_main ($) {
6852              }->{$token->{tag_name}}) {              }->{$token->{tag_name}}) {
6853            !!!cp ('t380');            !!!cp ('t380');
6854            push @$active_formatting_elements, ['#marker', ''];            push @$active_formatting_elements, ['#marker', ''];
6855              !!!nack ('t380.1');
6856          } elsif ({          } elsif ({
6857                    b => 1, big => 1, em => 1, font => 1, i => 1,                    b => 1, big => 1, em => 1, font => 1, i => 1,
6858                    s => 1, small => 1, strile => 1,                    s => 1, small => 1, strile => 1,
# Line 6153  sub _tree_construction_main ($) { Line 6860  sub _tree_construction_main ($) {
6860                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
6861            !!!cp ('t375');            !!!cp ('t375');
6862            push @$active_formatting_elements, $self->{open_elements}->[-1];            push @$active_formatting_elements, $self->{open_elements}->[-1];
6863              !!!nack ('t375.1');
6864          } elsif ($token->{tag_name} eq 'input') {          } elsif ($token->{tag_name} eq 'input') {
6865            !!!cp ('t388');            !!!cp ('t388');
6866            ## TODO: associate with $self->{form_element} if defined            ## TODO: associate with $self->{form_element} if defined
6867            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
6868              !!!ack ('t388.2');
6869          } elsif ({          } elsif ({
6870                    area => 1, basefont => 1, bgsound => 1, br => 1,                    area => 1, basefont => 1, bgsound => 1, br => 1,
6871                    embed => 1, img => 1, param => 1, spacer => 1, wbr => 1,                    embed => 1, img => 1, param => 1, spacer => 1, wbr => 1,
# Line 6164  sub _tree_construction_main ($) { Line 6873  sub _tree_construction_main ($) {
6873                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
6874            !!!cp ('t388.1');            !!!cp ('t388.1');
6875            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
6876              !!!ack ('t388.3');
6877          } elsif ($token->{tag_name} eq 'select') {          } elsif ($token->{tag_name} eq 'select') {
6878            ## TODO: associate with $self->{form_element} if defined            ## TODO: associate with $self->{form_element} if defined
6879                    
# Line 6176  sub _tree_construction_main ($) { Line 6886  sub _tree_construction_main ($) {
6886              !!!cp ('t400.2');              !!!cp ('t400.2');
6887              $self->{insertion_mode} = IN_SELECT_IM;              $self->{insertion_mode} = IN_SELECT_IM;
6888            }            }
6889              !!!nack ('t400.3');
6890          } else {          } else {
6891            !!!cp ('t402');            !!!nack ('t402');
6892          }          }
6893                    
6894          !!!next-token;          !!!next-token;
6895          redo B;          next B;
6896        }        }
6897      } elsif ($token->{type} == END_TAG_TOKEN) {      } elsif ($token->{type} == END_TAG_TOKEN) {
6898        if ($token->{tag_name} eq 'body') {        if ($token->{tag_name} eq 'body') {
# Line 6203  sub _tree_construction_main ($) { Line 6914  sub _tree_construction_main ($) {
6914                            value => $token->{tag_name}, token => $token);                            value => $token->{tag_name}, token => $token);
6915            ## NOTE: Ignore the token.            ## NOTE: Ignore the token.
6916            !!!next-token;            !!!next-token;
6917            redo B;            next B;
6918          } # INSCOPE          } # INSCOPE
6919    
6920          for (@{$self->{open_elements}}) {          for (@{$self->{open_elements}}) {
# Line 6220  sub _tree_construction_main ($) { Line 6931  sub _tree_construction_main ($) {
6931    
6932          $self->{insertion_mode} = AFTER_BODY_IM;          $self->{insertion_mode} = AFTER_BODY_IM;
6933          !!!next-token;          !!!next-token;
6934          redo B;          next B;
6935        } elsif ($token->{tag_name} eq 'html') {        } elsif ($token->{tag_name} eq 'html') {
6936          ## TODO: Update this code.  It seems that the code below is not          ## TODO: Update this code.  It seems that the code below is not
6937          ## up-to-date, though it has same effect as speced.          ## up-to-date, though it has same effect as speced.
# Line 6238  sub _tree_construction_main ($) { Line 6949  sub _tree_construction_main ($) {
6949            }            }
6950            $self->{insertion_mode} = AFTER_BODY_IM;            $self->{insertion_mode} = AFTER_BODY_IM;
6951            ## reprocess            ## reprocess
6952            redo B;            next B;
6953          } else {          } else {
6954            !!!cp ('t408');            !!!cp ('t408');
6955            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
6956            ## Ignore the token            ## Ignore the token
6957            !!!next-token;            !!!next-token;
6958            redo B;            next B;
6959          }          }
6960        } elsif ({        } elsif ({
6961                  address => 1, blockquote => 1, center => 1, dir => 1,                  address => 1, blockquote => 1, center => 1, dir => 1,
# Line 6304  sub _tree_construction_main ($) { Line 7015  sub _tree_construction_main ($) {
7015                }->{$token->{tag_name}};                }->{$token->{tag_name}};
7016          }          }
7017          !!!next-token;          !!!next-token;
7018          redo B;          next B;
7019        } elsif ($token->{tag_name} eq 'form') {        } elsif ($token->{tag_name} eq 'form') {
7020          undef $self->{form_element};          undef $self->{form_element};
7021    
# Line 6349  sub _tree_construction_main ($) { Line 7060  sub _tree_construction_main ($) {
7060          }          }
7061    
7062          !!!next-token;          !!!next-token;
7063          redo B;          next B;
7064        } elsif ({        } elsif ({
7065                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,
7066                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 6391  sub _tree_construction_main ($) { Line 7102  sub _tree_construction_main ($) {
7102          }          }
7103                    
7104          !!!next-token;          !!!next-token;
7105          redo B;          next B;
7106        } elsif ($token->{tag_name} eq 'p') {        } elsif ($token->{tag_name} eq 'p') {
7107          ## has an element in scope          ## has an element in scope
7108          my $i;          my $i;
# Line 6427  sub _tree_construction_main ($) { Line 7138  sub _tree_construction_main ($) {
7138            !!!cp ('t415.1');            !!!cp ('t415.1');
7139            ## As if <p>, then reprocess the current token            ## As if <p>, then reprocess the current token
7140            my $el;            my $el;
7141            !!!create-element ($el, 'p',, $token);            !!!create-element ($el, $HTML_NS, 'p',, $token);
7142            $insert->($el);            $insert->($el);
7143            ## NOTE: Not inserted into |$self->{open_elements}|.            ## NOTE: Not inserted into |$self->{open_elements}|.
7144          }          }
7145    
7146          !!!next-token;          !!!next-token;
7147          redo B;          next B;
7148        } elsif ({        } elsif ({
7149                  a => 1,                  a => 1,
7150                  b => 1, big => 1, em => 1, font => 1, i => 1,                  b => 1, big => 1, em => 1, font => 1, i => 1,
# Line 6442  sub _tree_construction_main ($) { Line 7153  sub _tree_construction_main ($) {
7153                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7154          !!!cp ('t427');          !!!cp ('t427');
7155          $formatting_end_tag->($token);          $formatting_end_tag->($token);
7156          redo B;          next B;
7157        } elsif ($token->{tag_name} eq 'br') {        } elsif ($token->{tag_name} eq 'br') {
7158          !!!cp ('t428');          !!!cp ('t428');
7159          !!!parse-error (type => 'unmatched end tag:br', token => $token);          !!!parse-error (type => 'unmatched end tag:br', token => $token);
# Line 6451  sub _tree_construction_main ($) { Line 7162  sub _tree_construction_main ($) {
7162          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
7163                    
7164          my $el;          my $el;
7165          !!!create-element ($el, 'br',, $token);          !!!create-element ($el, $HTML_NS, 'br',, $token);
7166          $insert->($el);          $insert->($el);
7167                    
7168          ## Ignore the token.          ## Ignore the token.
7169          !!!next-token;          !!!next-token;
7170          redo B;          next B;
7171        } elsif ({        } elsif ({
7172                  caption => 1, col => 1, colgroup => 1, frame => 1,                  caption => 1, col => 1, colgroup => 1, frame => 1,
7173                  frameset => 1, head => 1, option => 1, optgroup => 1,                  frameset => 1, head => 1, option => 1, optgroup => 1,
# Line 6473  sub _tree_construction_main ($) { Line 7184  sub _tree_construction_main ($) {
7184          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
7185          ## Ignore the token          ## Ignore the token
7186          !!!next-token;          !!!next-token;
7187          redo B;          next B;
7188                    
7189          ## ISSUE: Issue on HTML5 new elements in spec          ## ISSUE: Issue on HTML5 new elements in spec
7190                    
# Line 6534  sub _tree_construction_main ($) { Line 7245  sub _tree_construction_main ($) {
7245            ## Step 5;            ## Step 5;
7246            redo S2;            redo S2;
7247          } # S2          } # S2
7248          redo B;          next B;
7249        }        }
7250      }      }
7251      redo B;      next B;
7252      } continue { # B
7253        if ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM) {
7254          ## NOTE: The code below is executed in cases where it does not have
7255          ## to be, but it it is harmless even in those cases.
7256          ## has an element in scope
7257          INSCOPE: {
7258            for (reverse 0..$#{$self->{open_elements}}) {
7259              my $node = $self->{open_elements}->[$_];
7260              if ($node->[1] & FOREIGN_EL) {
7261                last INSCOPE;
7262              } elsif ($node->[1] & SCOPING_EL) {
7263                last;
7264              }
7265            }
7266            
7267            ## NOTE: No foreign element in scope.
7268            $self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM;
7269          } # INSCOPE
7270        }
7271    } # B    } # B
7272    
7273    ## Stop parsing # MUST    ## Stop parsing # MUST
# Line 6614  sub set_inner_html ($$$) { Line 7344  sub set_inner_html ($$$) {
7344          !!!cp ('i4');          !!!cp ('i4');
7345          !!!parse-error (type => 'NULL');          !!!parse-error (type => 'NULL');
7346          $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST          $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST
7347          } elsif ($self->{next_char} <= 0x0008 or
7348                   (0x000E <= $self->{next_char} and
7349                    $self->{next_char} <= 0x001F) or
7350                   (0x007F <= $self->{next_char} and
7351                    $self->{next_char} <= 0x009F) or
7352                   (0xD800 <= $self->{next_char} and
7353                    $self->{next_char} <= 0xDFFF) or
7354                   (0xFDD0 <= $self->{next_char} and
7355                    $self->{next_char} <= 0xFDDF) or
7356                   {
7357                    0xFFFE => 1, 0xFFFF => 1, 0x1FFFE => 1, 0x1FFFF => 1,
7358                    0x2FFFE => 1, 0x2FFFF => 1, 0x3FFFE => 1, 0x3FFFF => 1,
7359                    0x4FFFE => 1, 0x4FFFF => 1, 0x5FFFE => 1, 0x5FFFF => 1,
7360                    0x6FFFE => 1, 0x6FFFF => 1, 0x7FFFE => 1, 0x7FFFF => 1,
7361                    0x8FFFE => 1, 0x8FFFF => 1, 0x9FFFE => 1, 0x9FFFF => 1,
7362                    0xAFFFE => 1, 0xAFFFF => 1, 0xBFFFE => 1, 0xBFFFF => 1,
7363                    0xCFFFE => 1, 0xCFFFF => 1, 0xDFFFE => 1, 0xDFFFF => 1,
7364                    0xEFFFE => 1, 0xEFFFF => 1, 0xFFFFE => 1, 0xFFFFF => 1,
7365                    0x10FFFE => 1, 0x10FFFF => 1,
7366                   }->{$self->{next_char}}) {
7367            !!!cp ('i4.1');
7368            !!!parse-error (type => 'control char', level => $self->{must_level});
7369    ## TODO: error type documentation
7370        }        }
7371      };      };
7372      $p->{prev_char} = [-1, -1, -1];      $p->{prev_char} = [-1, -1, -1];

Legend:
Removed from v.1.124  
changed lines
  Added in v.1.141

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24