/[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.113 by wakaba, Sun Mar 16 07:07:59 2008 UTC revision 1.122 by wakaba, Sun Apr 6 06:34:11 2008 UTC
# Line 108  sub parse_byte_string ($$$$;$) { Line 108  sub parse_byte_string ($$$$;$) {
108    $self->{change_encoding} = sub {    $self->{change_encoding} = sub {
109      my $self = shift;      my $self = shift;
110      my $charset = lc shift;      my $charset = lc shift;
111        my $token = shift;
112      ## TODO: if $charset is supported      ## TODO: if $charset is supported
113      ## TODO: normalize charset name      ## TODO: normalize charset name
114    
# Line 126  sub parse_byte_string ($$$$;$) { Line 127  sub parse_byte_string ($$$$;$) {
127      }      }
128    
129      !!!parse-error (type => 'charset label detected:'.$self->{input_encoding}.      !!!parse-error (type => 'charset label detected:'.$self->{input_encoding}.
130          ':'.$charset, level => 'w');          ':'.$charset, level => 'w', token => $token);
131    
132      ## Step 3      ## Step 3
133      # if (can) {      # if (can) {
# Line 465  sub _get_next_token ($) { Line 466  sub _get_next_token ($) {
466        # Anything else        # Anything else
467        my $token = {type => CHARACTER_TOKEN,        my $token = {type => CHARACTER_TOKEN,
468                     data => chr $self->{next_char},                     data => chr $self->{next_char},
469                     line => $self->{line}, column => $self->{column}};                     line => $self->{line}, column => $self->{column},
470                      };
471        ## Stay in the data state        ## Stay in the data state
472        !!!next-input-character;        !!!next-input-character;
473    
# Line 485  sub _get_next_token ($) { Line 487  sub _get_next_token ($) {
487        unless (defined $token) {        unless (defined $token) {
488          !!!cp (13);          !!!cp (13);
489          !!!emit ({type => CHARACTER_TOKEN, data => '&',          !!!emit ({type => CHARACTER_TOKEN, data => '&',
490                    line => $l, column => $c});                    line => $l, column => $c,
491                     });
492        } else {        } else {
493          !!!cp (14);          !!!cp (14);
494          !!!emit ($token);          !!!emit ($token);
# Line 506  sub _get_next_token ($) { Line 509  sub _get_next_token ($) {
509    
510            !!!emit ({type => CHARACTER_TOKEN, data => '<',            !!!emit ({type => CHARACTER_TOKEN, data => '<',
511                      line => $self->{line_prev},                      line => $self->{line_prev},
512                      column => $self->{column_prev}});                      column => $self->{column_prev},
513                       });
514    
515            redo A;            redo A;
516          }          }
# Line 544  sub _get_next_token ($) { Line 548  sub _get_next_token ($) {
548            redo A;            redo A;
549          } elsif ($self->{next_char} == 0x003E) { # >          } elsif ($self->{next_char} == 0x003E) { # >
550            !!!cp (21);            !!!cp (21);
551            !!!parse-error (type => 'empty start tag');            !!!parse-error (type => 'empty start tag',
552                              line => $self->{line_prev},
553                              column => $self->{column_prev});
554            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
555            !!!next-input-character;            !!!next-input-character;
556    
557            !!!emit ({type => CHARACTER_TOKEN, data => '<>',            !!!emit ({type => CHARACTER_TOKEN, data => '<>',
558                      line => $self->{line_prev},                      line => $self->{line_prev},
559                      column => $self->{column_prev}});                      column => $self->{column_prev},
560                       });
561    
562            redo A;            redo A;
563          } elsif ($self->{next_char} == 0x003F) { # ?          } elsif ($self->{next_char} == 0x003F) { # ?
564            !!!cp (22);            !!!cp (22);
565            !!!parse-error (type => 'pio');            !!!parse-error (type => 'pio',
566                              line => $self->{line_prev},
567                              column => $self->{column_prev});
568            $self->{state} = BOGUS_COMMENT_STATE;            $self->{state} = BOGUS_COMMENT_STATE;
569            $self->{current_token} = {type => COMMENT_TOKEN, data => '',            $self->{current_token} = {type => COMMENT_TOKEN, data => '',
570                                      line => $self->{line_prev},                                      line => $self->{line_prev},
571                                      column => $self->{column_prev}};                                      column => $self->{column_prev},
572                                       };
573            ## $self->{next_char} is intentionally left as is            ## $self->{next_char} is intentionally left as is
574            redo A;            redo A;
575          } else {          } else {
# Line 570  sub _get_next_token ($) { Line 580  sub _get_next_token ($) {
580    
581            !!!emit ({type => CHARACTER_TOKEN, data => '<',            !!!emit ({type => CHARACTER_TOKEN, data => '<',
582                      line => $self->{line_prev},                      line => $self->{line_prev},
583                      column => $self->{column_prev}});                      column => $self->{column_prev},
584                       });
585    
586            redo A;            redo A;
587          }          }
# Line 599  sub _get_next_token ($) { Line 610  sub _get_next_token ($) {
610                $self->{state} = DATA_STATE;                $self->{state} = DATA_STATE;
611    
612                !!!emit ({type => CHARACTER_TOKEN, data => '</',                !!!emit ({type => CHARACTER_TOKEN, data => '</',
613                          line => $l, column => $c});                          line => $l, column => $c,
614                           });
615        
616                redo A;                redo A;
617              }              }
# Line 619  sub _get_next_token ($) { Line 631  sub _get_next_token ($) {
631              !!!back-next-input-character (@next_char);              !!!back-next-input-character (@next_char);
632              $self->{state} = DATA_STATE;              $self->{state} = DATA_STATE;
633              !!!emit ({type => CHARACTER_TOKEN, data => '</',              !!!emit ({type => CHARACTER_TOKEN, data => '</',
634                        line => $l, column => $c});                        line => $l, column => $c,
635                         });
636              redo A;              redo A;
637            } else {            } else {
638              !!!cp (27);              !!!cp (27);
# Line 633  sub _get_next_token ($) { Line 646  sub _get_next_token ($) {
646            # next-input-character is already done            # next-input-character is already done
647            $self->{state} = DATA_STATE;            $self->{state} = DATA_STATE;
648            !!!emit ({type => CHARACTER_TOKEN, data => '</',            !!!emit ({type => CHARACTER_TOKEN, data => '</',
649                      line => $l, column => $c});                      line => $l, column => $c,
650                       });
651            redo A;            redo A;
652          }          }
653        }        }
# Line 659  sub _get_next_token ($) { Line 673  sub _get_next_token ($) {
673          redo A;          redo A;
674        } elsif ($self->{next_char} == 0x003E) { # >        } elsif ($self->{next_char} == 0x003E) { # >
675          !!!cp (31);          !!!cp (31);
676          !!!parse-error (type => 'empty end tag');          !!!parse-error (type => 'empty end tag',
677                            line => $self->{line_prev}, ## "<" in "</>"
678                            column => $self->{column_prev} - 1);
679          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
680          !!!next-input-character;          !!!next-input-character;
681          redo A;          redo A;
# Line 670  sub _get_next_token ($) { Line 686  sub _get_next_token ($) {
686          # reconsume          # reconsume
687    
688          !!!emit ({type => CHARACTER_TOKEN, data => '</',          !!!emit ({type => CHARACTER_TOKEN, data => '</',
689                    line => $l, column => $c});                    line => $l, column => $c,
690                     });
691    
692          redo A;          redo A;
693        } else {        } else {
# Line 679  sub _get_next_token ($) { Line 696  sub _get_next_token ($) {
696          $self->{state} = BOGUS_COMMENT_STATE;          $self->{state} = BOGUS_COMMENT_STATE;
697          $self->{current_token} = {type => COMMENT_TOKEN, data => '',          $self->{current_token} = {type => COMMENT_TOKEN, data => '',
698                                    line => $self->{line_prev}, # "<" of "</"                                    line => $self->{line_prev}, # "<" of "</"
699                                    column => $self->{column_prev} - 1};                                    column => $self->{column_prev} - 1,
700                                     };
701          ## $self->{next_char} is intentionally left as is          ## $self->{next_char} is intentionally left as is
702          redo A;          redo A;
703        }        }
# Line 696  sub _get_next_token ($) { Line 714  sub _get_next_token ($) {
714        } elsif ($self->{next_char} == 0x003E) { # >        } elsif ($self->{next_char} == 0x003E) { # >
715          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
716            !!!cp (35);            !!!cp (35);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
717            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
718          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
719            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 729  sub _get_next_token ($) { Line 745  sub _get_next_token ($) {
745          !!!parse-error (type => 'unclosed tag');          !!!parse-error (type => 'unclosed tag');
746          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
747            !!!cp (39);            !!!cp (39);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
748            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
749          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
750            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 786  sub _get_next_token ($) { Line 800  sub _get_next_token ($) {
800        } elsif ($self->{next_char} == 0x003E) { # >        } elsif ($self->{next_char} == 0x003E) { # >
801          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
802            !!!cp (46);            !!!cp (46);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
803            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
804          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
805            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 809  sub _get_next_token ($) { Line 821  sub _get_next_token ($) {
821        } elsif (0x0041 <= $self->{next_char} and        } elsif (0x0041 <= $self->{next_char} and
822                 $self->{next_char} <= 0x005A) { # A..Z                 $self->{next_char} <= 0x005A) { # A..Z
823          !!!cp (49);          !!!cp (49);
824          $self->{current_attribute} = {name => chr ($self->{next_char} + 0x0020),          $self->{current_attribute}
825                                value => ''};              = {name => chr ($self->{next_char} + 0x0020),
826                   value => '',
827                   line => $self->{line}, column => $self->{column}};
828          $self->{state} = ATTRIBUTE_NAME_STATE;          $self->{state} = ATTRIBUTE_NAME_STATE;
829          !!!next-input-character;          !!!next-input-character;
830          redo A;          redo A;
# Line 833  sub _get_next_token ($) { Line 847  sub _get_next_token ($) {
847          !!!parse-error (type => 'unclosed tag');          !!!parse-error (type => 'unclosed tag');
848          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
849            !!!cp (52);            !!!cp (52);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
850            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
851          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
852            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 864  sub _get_next_token ($) { Line 876  sub _get_next_token ($) {
876          } else {          } else {
877            !!!cp (56);            !!!cp (56);
878          }          }
879          $self->{current_attribute} = {name => chr ($self->{next_char}),          $self->{current_attribute}
880                                value => ''};              = {name => chr ($self->{next_char}),
881                   value => '',
882                   line => $self->{line}, column => $self->{column}};
883          $self->{state} = ATTRIBUTE_NAME_STATE;          $self->{state} = ATTRIBUTE_NAME_STATE;
884          !!!next-input-character;          !!!next-input-character;
885          redo A;          redo A;
# Line 875  sub _get_next_token ($) { Line 889  sub _get_next_token ($) {
889          if (exists $self->{current_token}->{attributes} # start tag or end tag          if (exists $self->{current_token}->{attributes} # start tag or end tag
890              ->{$self->{current_attribute}->{name}}) { # MUST              ->{$self->{current_attribute}->{name}}) { # MUST
891            !!!cp (57);            !!!cp (57);
892            !!!parse-error (type => 'duplicate attribute:'.$self->{current_attribute}->{name});            !!!parse-error (type => 'duplicate attribute:'.$self->{current_attribute}->{name}, line => $self->{current_attribute}->{line}, column => $self->{current_attribute}->{column});
893            ## Discard $self->{current_attribute} # MUST            ## Discard $self->{current_attribute} # MUST
894          } else {          } else {
895            !!!cp (58);            !!!cp (58);
# Line 904  sub _get_next_token ($) { Line 918  sub _get_next_token ($) {
918          $before_leave->();          $before_leave->();
919          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
920            !!!cp (61);            !!!cp (61);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
921            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
922          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
923            !!!cp (62);            !!!cp (62);
# Line 950  sub _get_next_token ($) { Line 962  sub _get_next_token ($) {
962          $before_leave->();          $before_leave->();
963          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
964            !!!cp (66);            !!!cp (66);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
965            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
966          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
967            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1002  sub _get_next_token ($) { Line 1012  sub _get_next_token ($) {
1012        } elsif ($self->{next_char} == 0x003E) { # >        } elsif ($self->{next_char} == 0x003E) { # >
1013          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
1014            !!!cp (73);            !!!cp (73);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
1015            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
1016          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
1017            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1026  sub _get_next_token ($) { Line 1034  sub _get_next_token ($) {
1034        } elsif (0x0041 <= $self->{next_char} and        } elsif (0x0041 <= $self->{next_char} and
1035                 $self->{next_char} <= 0x005A) { # A..Z                 $self->{next_char} <= 0x005A) { # A..Z
1036          !!!cp (76);          !!!cp (76);
1037          $self->{current_attribute} = {name => chr ($self->{next_char} + 0x0020),          $self->{current_attribute}
1038                                value => ''};              = {name => chr ($self->{next_char} + 0x0020),
1039                   value => '',
1040                   line => $self->{line}, column => $self->{column}};
1041          $self->{state} = ATTRIBUTE_NAME_STATE;          $self->{state} = ATTRIBUTE_NAME_STATE;
1042          !!!next-input-character;          !!!next-input-character;
1043          redo A;          redo A;
# Line 1051  sub _get_next_token ($) { Line 1061  sub _get_next_token ($) {
1061          !!!parse-error (type => 'unclosed tag');          !!!parse-error (type => 'unclosed tag');
1062          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
1063            !!!cp (79);            !!!cp (79);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
1064            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
1065          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
1066            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1074  sub _get_next_token ($) { Line 1082  sub _get_next_token ($) {
1082          redo A;          redo A;
1083        } else {        } else {
1084          !!!cp (82);          !!!cp (82);
1085          $self->{current_attribute} = {name => chr ($self->{next_char}),          $self->{current_attribute}
1086                                value => ''};              = {name => chr ($self->{next_char}),
1087                   value => '',
1088                   line => $self->{line}, column => $self->{column}};
1089          $self->{state} = ATTRIBUTE_NAME_STATE;          $self->{state} = ATTRIBUTE_NAME_STATE;
1090          !!!next-input-character;          !!!next-input-character;
1091          redo A;                  redo A;        
# Line 1108  sub _get_next_token ($) { Line 1118  sub _get_next_token ($) {
1118        } elsif ($self->{next_char} == 0x003E) { # >        } elsif ($self->{next_char} == 0x003E) { # >
1119          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
1120            !!!cp (87);            !!!cp (87);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
1121            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
1122          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
1123            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1133  sub _get_next_token ($) { Line 1141  sub _get_next_token ($) {
1141          !!!parse-error (type => 'unclosed tag');          !!!parse-error (type => 'unclosed tag');
1142          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
1143            !!!cp (90);            !!!cp (90);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
1144            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
1145          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
1146            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1182  sub _get_next_token ($) { Line 1188  sub _get_next_token ($) {
1188          !!!parse-error (type => 'unclosed attribute value');          !!!parse-error (type => 'unclosed attribute value');
1189          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
1190            !!!cp (97);            !!!cp (97);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
1191            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
1192          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
1193            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1226  sub _get_next_token ($) { Line 1230  sub _get_next_token ($) {
1230          !!!parse-error (type => 'unclosed attribute value');          !!!parse-error (type => 'unclosed attribute value');
1231          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
1232            !!!cp (103);            !!!cp (103);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
1233            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
1234          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
1235            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1273  sub _get_next_token ($) { Line 1275  sub _get_next_token ($) {
1275        } elsif ($self->{next_char} == 0x003E) { # >        } elsif ($self->{next_char} == 0x003E) { # >
1276          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
1277            !!!cp (109);            !!!cp (109);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
1278            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
1279          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
1280            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1298  sub _get_next_token ($) { Line 1298  sub _get_next_token ($) {
1298          !!!parse-error (type => 'unclosed tag');          !!!parse-error (type => 'unclosed tag');
1299          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
1300            !!!cp (112);            !!!cp (112);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
1301            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
1302          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
1303            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1370  sub _get_next_token ($) { Line 1368  sub _get_next_token ($) {
1368        } elsif ($self->{next_char} == 0x003E) { # >        } elsif ($self->{next_char} == 0x003E) { # >
1369          if ($self->{current_token}->{type} == START_TAG_TOKEN) {          if ($self->{current_token}->{type} == START_TAG_TOKEN) {
1370            !!!cp (119);            !!!cp (119);
           $self->{current_token}->{first_start_tag}  
               = not defined $self->{last_emitted_start_tag_name};  
1371            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
1372          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
1373            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
# Line 1459  sub _get_next_token ($) { Line 1455  sub _get_next_token ($) {
1455          if ($self->{next_char} == 0x002D) { # -          if ($self->{next_char} == 0x002D) { # -
1456            !!!cp (127);            !!!cp (127);
1457            $self->{current_token} = {type => COMMENT_TOKEN, data => '',            $self->{current_token} = {type => COMMENT_TOKEN, data => '',
1458                                      line => $l, column => $c};                                      line => $l, column => $c,
1459                                       };
1460            $self->{state} = COMMENT_START_STATE;            $self->{state} = COMMENT_START_STATE;
1461            !!!next-input-character;            !!!next-input-character;
1462            redo A;            redo A;
# Line 1497  sub _get_next_token ($) { Line 1494  sub _get_next_token ($) {
1494                      $self->{state} = DOCTYPE_STATE;                      $self->{state} = DOCTYPE_STATE;
1495                      $self->{current_token} = {type => DOCTYPE_TOKEN,                      $self->{current_token} = {type => DOCTYPE_TOKEN,
1496                                                quirks => 1,                                                quirks => 1,
1497                                                line => $l, column => $c};                                                line => $l, column => $c,
1498                                                 };
1499                      !!!next-input-character;                      !!!next-input-character;
1500                      redo A;                      redo A;
1501                    } else {                    } else {
# Line 1527  sub _get_next_token ($) { Line 1525  sub _get_next_token ($) {
1525        !!!back-next-input-character (@next_char);        !!!back-next-input-character (@next_char);
1526        $self->{state} = BOGUS_COMMENT_STATE;        $self->{state} = BOGUS_COMMENT_STATE;
1527        $self->{current_token} = {type => COMMENT_TOKEN, data => '',        $self->{current_token} = {type => COMMENT_TOKEN, data => '',
1528                                  line => $l, column => $c};                                  line => $l, column => $c,
1529                                   };
1530        redo A;        redo A;
1531                
1532        ## ISSUE: typos in spec: chacacters, is is a parse error        ## ISSUE: typos in spec: chacacters, is is a parse error
# Line 1651  sub _get_next_token ($) { Line 1650  sub _get_next_token ($) {
1650          redo A;          redo A;
1651        } elsif ($self->{next_char} == 0x002D) { # -        } elsif ($self->{next_char} == 0x002D) { # -
1652          !!!cp (152);          !!!cp (152);
1653          !!!parse-error (type => 'dash in comment');          !!!parse-error (type => 'dash in comment',
1654                            line => $self->{line_prev},
1655                            column => $self->{column_prev});
1656          $self->{current_token}->{data} .= '-'; # comment          $self->{current_token}->{data} .= '-'; # comment
1657          ## Stay in the state          ## Stay in the state
1658          !!!next-input-character;          !!!next-input-character;
# Line 1667  sub _get_next_token ($) { Line 1668  sub _get_next_token ($) {
1668          redo A;          redo A;
1669        } else {        } else {
1670          !!!cp (154);          !!!cp (154);
1671          !!!parse-error (type => 'dash in comment');          !!!parse-error (type => 'dash in comment',
1672                            line => $self->{line_prev},
1673                            column => $self->{column_prev});
1674          $self->{current_token}->{data} .= '--' . chr ($self->{next_char}); # comment          $self->{current_token}->{data} .= '--' . chr ($self->{next_char}); # comment
1675          $self->{state} = COMMENT_STATE;          $self->{state} = COMMENT_STATE;
1676          !!!next-input-character;          !!!next-input-character;
# Line 2321  sub _tokenize_attempt_to_consume_an_enti Line 2324  sub _tokenize_attempt_to_consume_an_enti
2324          }          }
2325    
2326          return {type => CHARACTER_TOKEN, data => chr $code,          return {type => CHARACTER_TOKEN, data => chr $code,
2327                  has_reference => 1, line => $l, column => $c};                  has_reference => 1,
2328                    line => $l, column => $c,
2329                   };
2330        } # X        } # X
2331      } elsif (0x0030 <= $self->{next_char} and      } elsif (0x0030 <= $self->{next_char} and
2332               $self->{next_char} <= 0x0039) { # 0..9               $self->{next_char} <= 0x0039) { # 0..9
# Line 2364  sub _tokenize_attempt_to_consume_an_enti Line 2369  sub _tokenize_attempt_to_consume_an_enti
2369        }        }
2370                
2371        return {type => CHARACTER_TOKEN, data => chr $code, has_reference => 1,        return {type => CHARACTER_TOKEN, data => chr $code, has_reference => 1,
2372                line => $l, column => $c};                line => $l, column => $c,
2373                 };
2374      } else {      } else {
2375        !!!cp (1019);        !!!cp (1019);
2376        !!!parse-error (type => 'bare nero', line => $l, column => $c);        !!!parse-error (type => 'bare nero', line => $l, column => $c);
# Line 2418  sub _tokenize_attempt_to_consume_an_enti Line 2424  sub _tokenize_attempt_to_consume_an_enti
2424      if ($match > 0) {      if ($match > 0) {
2425        !!!cp (1023);        !!!cp (1023);
2426        return {type => CHARACTER_TOKEN, data => $value, has_reference => 1,        return {type => CHARACTER_TOKEN, data => $value, has_reference => 1,
2427                line => $l, column => $c};                line => $l, column => $c,
2428                 };
2429      } elsif ($match < 0) {      } elsif ($match < 0) {
2430        !!!parse-error (type => 'no refc', line => $l, column => $c);        !!!parse-error (type => 'no refc', line => $l, column => $c);
2431        if ($in_attr and $match < -1) {        if ($in_attr and $match < -1) {
2432          !!!cp (1024);          !!!cp (1024);
2433          return {type => CHARACTER_TOKEN, data => '&'.$entity_name,          return {type => CHARACTER_TOKEN, data => '&'.$entity_name,
2434                  line => $l, column => $c};                  line => $l, column => $c,
2435                   };
2436        } else {        } else {
2437          !!!cp (1025);          !!!cp (1025);
2438          return {type => CHARACTER_TOKEN, data => $value, has_reference => 1,          return {type => CHARACTER_TOKEN, data => $value, has_reference => 1,
2439                  line => $l, column => $c};                  line => $l, column => $c,
2440                   };
2441        }        }
2442      } else {      } else {
2443        !!!cp (1026);        !!!cp (1026);
2444        !!!parse-error (type => 'bare ero', line => $l, column => $c);        !!!parse-error (type => 'bare ero', line => $l, column => $c);
2445        ## NOTE: "No characters are consumed" in the spec.        ## NOTE: "No characters are consumed" in the spec.
2446        return {type => CHARACTER_TOKEN, data => '&'.$value,        return {type => CHARACTER_TOKEN, data => '&'.$value,
2447                line => $l, column => $c};                line => $l, column => $c,
2448                 };
2449      }      }
2450    } else {    } else {
2451      !!!cp (1027);      !!!cp (1027);
# Line 2522  sub _tree_construction_initial ($) { Line 2532  sub _tree_construction_initial ($) {
2532                
2533        my $doctype = $self->{document}->create_document_type_definition        my $doctype = $self->{document}->create_document_type_definition
2534          ($token->{name}); ## ISSUE: If name is missing (e.g. <!DOCTYPE>)?          ($token->{name}); ## ISSUE: If name is missing (e.g. <!DOCTYPE>)?
2535          ## NOTE: Default value for both |public_id| and |system_id| attributes
2536          ## are empty strings, so that we don't set any value in missing cases.
2537        $doctype->public_id ($token->{public_identifier})        $doctype->public_id ($token->{public_identifier})
2538            if defined $token->{public_identifier};            if defined $token->{public_identifier};
2539        $doctype->system_id ($token->{system_identifier})        $doctype->system_id ($token->{system_identifier})
# Line 2738  sub _tree_construction_root_element ($) Line 2750  sub _tree_construction_root_element ($)
2750        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
2751          if ($token->{tag_name} eq 'html') {          if ($token->{tag_name} eq 'html') {
2752            my $root_element;            my $root_element;
2753            !!!create-element ($root_element, $token->{tag_name}, $token->{attributes});            !!!create-element ($root_element, $token->{tag_name}, $token->{attributes}, $token);
2754            $self->{document}->append_child ($root_element);            $self->{document}->append_child ($root_element);
2755            push @{$self->{open_elements}}, [$root_element, 'html'];            push @{$self->{open_elements}}, [$root_element, 'html'];
2756    
# Line 2746  sub _tree_construction_root_element ($) Line 2758  sub _tree_construction_root_element ($)
2758              !!!cp ('t24');              !!!cp ('t24');
2759              $self->{application_cache_selection}              $self->{application_cache_selection}
2760                  ->($token->{attributes}->{manifest}->{value});                  ->($token->{attributes}->{manifest}->{value});
2761              ## ISSUE: No relative reference resolution?              ## ISSUE: Spec is unclear on relative references.
2762                ## According to Hixie (#whatwg 2008-03-19), it should be
2763                ## resolved against the base URI of the document in HTML
2764                ## or xml:base of the element in XHTML.
2765            } else {            } else {
2766              !!!cp ('t25');              !!!cp ('t25');
2767              $self->{application_cache_selection}->(undef);              $self->{application_cache_selection}->(undef);
# Line 2768  sub _tree_construction_root_element ($) Line 2783  sub _tree_construction_root_element ($)
2783          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
2784        }        }
2785    
2786      my $root_element; !!!create-element ($root_element, 'html');      my $root_element; !!!create-element ($root_element, 'html',, $token);
2787      $self->{document}->append_child ($root_element);      $self->{document}->append_child ($root_element);
2788      push @{$self->{open_elements}}, [$root_element, 'html'];      push @{$self->{open_elements}}, [$root_element, 'html'];
2789    
# Line 2963  sub _tree_construction_main ($) { Line 2978  sub _tree_construction_main ($) {
2978      ## Step 1      ## Step 1
2979      my $start_tag_name = $token->{tag_name};      my $start_tag_name = $token->{tag_name};
2980      my $el;      my $el;
2981      !!!create-element ($el, $start_tag_name, $token->{attributes});      !!!create-element ($el, $start_tag_name, $token->{attributes}, $token);
2982    
2983      ## Step 2      ## Step 2
2984      $insert->($el);      $insert->($el);
# Line 3013  sub _tree_construction_main ($) { Line 3028  sub _tree_construction_main ($) {
3028    
3029    my $script_start_tag = sub () {    my $script_start_tag = sub () {
3030      my $script_el;      my $script_el;
3031      !!!create-element ($script_el, 'script', $token->{attributes});      !!!create-element ($script_el, 'script', $token->{attributes}, $token);
3032      ## TODO: mark as "parser-inserted"      ## TODO: mark as "parser-inserted"
3033    
3034      $self->{content_model} = CDATA_CONTENT_MODEL;      $self->{content_model} = CDATA_CONTENT_MODEL;
# Line 3130  sub _tree_construction_main ($) { Line 3145  sub _tree_construction_main ($) {
3145        }        }
3146        if (not $self->{open_elements}->[-1]->[0] eq $formatting_element->[0]) {        if (not $self->{open_elements}->[-1]->[0] eq $formatting_element->[0]) {
3147          !!!cp ('t58');          !!!cp ('t58');
3148          !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1],          !!!parse-error (type => 'not closed',
3149                            value => $self->{open_elements}->[-1]->[0]
3150                                ->manakai_local_name,
3151                          token => $end_tag_token);                          token => $end_tag_token);
3152        }        }
3153                
# Line 3410  sub _tree_construction_main ($) { Line 3427  sub _tree_construction_main ($) {
3427          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3428            !!!cp ('t89');            !!!cp ('t89');
3429            ## As if <head>            ## As if <head>
3430            !!!create-element ($self->{head_element}, 'head');            !!!create-element ($self->{head_element}, 'head',, $token);
3431            $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});            $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3432            push @{$self->{open_elements}}, [$self->{head_element}, 'head'];            push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3433    
# Line 3440  sub _tree_construction_main ($) { Line 3457  sub _tree_construction_main ($) {
3457    
3458              ## "after head" insertion mode              ## "after head" insertion mode
3459              ## As if <body>              ## As if <body>
3460              !!!insert-element ('body');              !!!insert-element ('body',, $token);
3461              $self->{insertion_mode} = IN_BODY_IM;              $self->{insertion_mode} = IN_BODY_IM;
3462              ## reprocess              ## reprocess
3463              redo B;              redo B;
# Line 3448  sub _tree_construction_main ($) { Line 3465  sub _tree_construction_main ($) {
3465              if ($token->{tag_name} eq 'head') {              if ($token->{tag_name} eq 'head') {
3466                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3467                  !!!cp ('t93');                  !!!cp ('t93');
3468                  !!!create-element ($self->{head_element}, $token->{tag_name}, $token->{attributes});                  !!!create-element ($self->{head_element}, $token->{tag_name}, $token->{attributes}, $token);
3469                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3470                  push @{$self->{open_elements}}, [$self->{head_element}, $token->{tag_name}];                  push @{$self->{open_elements}}, [$self->{head_element}, $token->{tag_name}];
3471                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
# Line 3467  sub _tree_construction_main ($) { Line 3484  sub _tree_construction_main ($) {
3484              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3485                !!!cp ('t96');                !!!cp ('t96');
3486                ## As if <head>                ## As if <head>
3487                !!!create-element ($self->{head_element}, 'head');                !!!create-element ($self->{head_element}, 'head',, $token);
3488                $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3489                push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3490    
# Line 3498  sub _tree_construction_main ($) { Line 3515  sub _tree_construction_main ($) {
3515                } else {                } else {
3516                  !!!cp ('t101');                  !!!cp ('t101');
3517                }                }
3518                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
3519                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
3520                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
3521                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
# Line 3513  sub _tree_construction_main ($) { Line 3530  sub _tree_construction_main ($) {
3530                } else {                } else {
3531                  !!!cp ('t103');                  !!!cp ('t103');
3532                }                }
3533                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
3534                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
3535                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
3536                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
# Line 3528  sub _tree_construction_main ($) { Line 3545  sub _tree_construction_main ($) {
3545                } else {                } else {
3546                  !!!cp ('t105');                  !!!cp ('t105');
3547                }                }
3548                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
3549                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.
3550    
3551                unless ($self->{confident}) {                unless ($self->{confident}) {
3552                  if ($token->{attributes}->{charset}) { ## TODO: And if supported                  if ($token->{attributes}->{charset}) { ## TODO: And if supported
3553                    !!!cp ('t106');                    !!!cp ('t106');
3554                    $self->{change_encoding}                    $self->{change_encoding}
3555                        ->($self, $token->{attributes}->{charset}->{value});                        ->($self, $token->{attributes}->{charset}->{value},
3556                             $token);
3557                                        
3558                    $meta_el->[0]->get_attribute_node_ns (undef, 'charset')                    $meta_el->[0]->get_attribute_node_ns (undef, 'charset')
3559                        ->set_user_data (manakai_has_reference =>                        ->set_user_data (manakai_has_reference =>
# Line 3550  sub _tree_construction_main ($) { Line 3568  sub _tree_construction_main ($) {
3568                            ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {                            ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {
3569                      !!!cp ('t107');                      !!!cp ('t107');
3570                      $self->{change_encoding}                      $self->{change_encoding}
3571                          ->($self, defined $1 ? $1 : defined $2 ? $2 : $3);                          ->($self, defined $1 ? $1 : defined $2 ? $2 : $3,
3572                               $token);
3573                      $meta_el->[0]->get_attribute_node_ns (undef, 'content')                      $meta_el->[0]->get_attribute_node_ns (undef, 'content')
3574                          ->set_user_data (manakai_has_reference =>                          ->set_user_data (manakai_has_reference =>
3575                                               $token->{attributes}->{content}                                               $token->{attributes}->{content}
# Line 3623  sub _tree_construction_main ($) { Line 3642  sub _tree_construction_main ($) {
3642                if ($self->{insertion_mode} == IN_HEAD_IM) {                if ($self->{insertion_mode} == IN_HEAD_IM) {
3643                  !!!cp ('t116');                  !!!cp ('t116');
3644                  ## NOTE: and scripting is disalbed                  ## NOTE: and scripting is disalbed
3645                  !!!insert-element ($token->{tag_name}, $token->{attributes});                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
3646                  $self->{insertion_mode} = IN_HEAD_NOSCRIPT_IM;                  $self->{insertion_mode} = IN_HEAD_NOSCRIPT_IM;
3647                  !!!next-token;                  !!!next-token;
3648                  redo B;                  redo B;
# Line 3682  sub _tree_construction_main ($) { Line 3701  sub _tree_construction_main ($) {
3701                }                }
3702    
3703                ## "after head" insertion mode                ## "after head" insertion mode
3704                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
3705                if ($token->{tag_name} eq 'body') {                if ($token->{tag_name} eq 'body') {
3706                  !!!cp ('t126');                  !!!cp ('t126');
3707                  $self->{insertion_mode} = IN_BODY_IM;                  $self->{insertion_mode} = IN_BODY_IM;
# Line 3722  sub _tree_construction_main ($) { Line 3741  sub _tree_construction_main ($) {
3741    
3742              ## "after head" insertion mode              ## "after head" insertion mode
3743              ## As if <body>              ## As if <body>
3744              !!!insert-element ('body');              !!!insert-element ('body',, $token);
3745              $self->{insertion_mode} = IN_BODY_IM;              $self->{insertion_mode} = IN_BODY_IM;
3746              ## reprocess              ## reprocess
3747              redo B;              redo B;
# Line 3731  sub _tree_construction_main ($) { Line 3750  sub _tree_construction_main ($) {
3750                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3751                  !!!cp ('t132');                  !!!cp ('t132');
3752                  ## As if <head>                  ## As if <head>
3753                  !!!create-element ($self->{head_element}, 'head');                  !!!create-element ($self->{head_element}, 'head',, $token);
3754                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3755                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3756    
# Line 3784  sub _tree_construction_main ($) { Line 3803  sub _tree_construction_main ($) {
3803                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3804                  !!!cp ('t139');                  !!!cp ('t139');
3805                  ## As if <head>                  ## As if <head>
3806                  !!!create-element ($self->{head_element}, 'head');                  !!!create-element ($self->{head_element}, 'head',, $token);
3807                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3808                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3809    
# Line 3807  sub _tree_construction_main ($) { Line 3826  sub _tree_construction_main ($) {
3826                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3827                  !!!cp ('t142');                  !!!cp ('t142');
3828                  ## As if <head>                  ## As if <head>
3829                  !!!create-element ($self->{head_element}, 'head');                  !!!create-element ($self->{head_element}, 'head',, $token);
3830                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3831                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3832    
# Line 3861  sub _tree_construction_main ($) { Line 3880  sub _tree_construction_main ($) {
3880    
3881              ## "after head" insertion mode              ## "after head" insertion mode
3882              ## As if <body>              ## As if <body>
3883              !!!insert-element ('body');              !!!insert-element ('body',, $token);
3884              $self->{insertion_mode} = IN_BODY_IM;              $self->{insertion_mode} = IN_BODY_IM;
3885              ## reprocess              ## reprocess
3886              redo B;              redo B;
# Line 3870  sub _tree_construction_main ($) { Line 3889  sub _tree_construction_main ($) {
3889            !!!cp ('t149.1');            !!!cp ('t149.1');
3890    
3891            ## NOTE: As if <head>            ## NOTE: As if <head>
3892            !!!create-element ($self->{head_element}, 'head');            !!!create-element ($self->{head_element}, 'head',, $token);
3893            $self->{open_elements}->[-1]->[0]->append_child            $self->{open_elements}->[-1]->[0]->append_child
3894                ($self->{head_element});                ($self->{head_element});
3895            #push @{$self->{open_elements}}, [$self->{head_element}, 'head'];            #push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
# Line 3914  sub _tree_construction_main ($) { Line 3933  sub _tree_construction_main ($) {
3933          }          }
3934    
3935          ## NOTE: As if <body>          ## NOTE: As if <body>
3936          !!!insert-element ('body');          !!!insert-element ('body',, $token);
3937          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
3938          ## NOTE: Reprocess.          ## NOTE: Reprocess.
3939          redo B;          redo B;
# Line 3947  sub _tree_construction_main ($) { Line 3966  sub _tree_construction_main ($) {
3966    
3967                      ## Close the cell                      ## Close the cell
3968                      !!!back-token; # <?>                      !!!back-token; # <?>
3969                      $token = {type => END_TAG_TOKEN, tag_name => $node->[1]};                      $token = {type => END_TAG_TOKEN,
3970                                  tag_name => $node->[0]->manakai_local_name,
3971                                  line => $token->{line},
3972                                  column => $token->{column}};
3973                      redo B;                      redo B;
3974                    } elsif ({                    } elsif ({
3975                              table => 1, html => 1,                              table => 1, html => 1,
# Line 4003  sub _tree_construction_main ($) { Line 4025  sub _tree_construction_main ($) {
4025    
4026                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {
4027                    !!!cp ('t159');                    !!!cp ('t159');
4028                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                    !!!parse-error (type => 'not closed',
4029                                      value => $self->{open_elements}->[-1]->[0]
4030                                          ->manakai_local_name,
4031                                      token => $token);
4032                  } else {                  } else {
4033                    !!!cp ('t160');                    !!!cp ('t160');
4034                  }                  }
# Line 4060  sub _tree_construction_main ($) { Line 4085  sub _tree_construction_main ($) {
4085    
4086                  if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {                  if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
4087                    !!!cp ('t167');                    !!!cp ('t167');
4088                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                    !!!parse-error (type => 'not closed',
4089                                      value => $self->{open_elements}->[-1]->[0]
4090                                          ->manakai_local_name,
4091                                      token => $token);
4092                  } else {                  } else {
4093                    !!!cp ('t168');                    !!!cp ('t168');
4094                  }                  }
# Line 4120  sub _tree_construction_main ($) { Line 4148  sub _tree_construction_main ($) {
4148                                    
4149                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {
4150                    !!!cp ('t175');                    !!!cp ('t175');
4151                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                    !!!parse-error (type => 'not closed',
4152                                      value => $self->{open_elements}->[-1]->[0]
4153                                          ->manakai_local_name,
4154                                      token => $token);
4155                  } else {                  } else {
4156                    !!!cp ('t176');                    !!!cp ('t176');
4157                  }                  }
# Line 4160  sub _tree_construction_main ($) { Line 4191  sub _tree_construction_main ($) {
4191    
4192                      ## Close the cell                      ## Close the cell
4193                      !!!back-token; # </?>                      !!!back-token; # </?>
4194                      $token = {type => END_TAG_TOKEN, tag_name => $tn};                      $token = {type => END_TAG_TOKEN, tag_name => $tn,
4195                                  line => $token->{line},
4196                                  column => $token->{column}};
4197                      redo B;                      redo B;
4198                    } elsif ($node->[1] eq 'td' or $node->[1] eq 'th') {                    } elsif ($node->[1] eq 'td' or $node->[1] eq 'th') {
4199                      !!!cp ('t180');                      !!!cp ('t180');
# Line 4221  sub _tree_construction_main ($) { Line 4254  sub _tree_construction_main ($) {
4254    
4255                if ($self->{open_elements}->[-1]->[1] ne 'caption') {                if ($self->{open_elements}->[-1]->[1] ne 'caption') {
4256                  !!!cp ('t188');                  !!!cp ('t188');
4257                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                  !!!parse-error (type => 'not closed',
4258                                    value => $self->{open_elements}->[-1]->[0]
4259                                        ->manakai_local_name,
4260                                    token => $token);
4261                } else {                } else {
4262                  !!!cp ('t189');                  !!!cp ('t189');
4263                }                }
# Line 4362  sub _tree_construction_main ($) { Line 4398  sub _tree_construction_main ($) {
4398                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4399                  }                  }
4400                                    
4401                  !!!insert-element ('tbody');                  !!!insert-element ('tbody',, $token);
4402                  $self->{insertion_mode} = IN_TABLE_BODY_IM;                  $self->{insertion_mode} = IN_TABLE_BODY_IM;
4403                  ## reprocess in the "in table body" insertion mode...                  ## reprocess in the "in table body" insertion mode...
4404                }                }
# Line 4385  sub _tree_construction_main ($) { Line 4421  sub _tree_construction_main ($) {
4421                  $self->{insertion_mode} = IN_ROW_IM;                  $self->{insertion_mode} = IN_ROW_IM;
4422                  if ($token->{tag_name} eq 'tr') {                  if ($token->{tag_name} eq 'tr') {
4423                    !!!cp ('t204');                    !!!cp ('t204');
4424                    !!!insert-element ($token->{tag_name}, $token->{attributes});                    !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4425                    !!!next-token;                    !!!next-token;
4426                    redo B;                    redo B;
4427                  } else {                  } else {
4428                    !!!cp ('t205');                    !!!cp ('t205');
4429                    !!!insert-element ('tr');                    !!!insert-element ('tr',, $token);
4430                    ## reprocess in the "in row" insertion mode                    ## reprocess in the "in row" insertion mode
4431                  }                  }
4432                } else {                } else {
# Line 4405  sub _tree_construction_main ($) { Line 4441  sub _tree_construction_main ($) {
4441                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4442                }                }
4443                                
4444                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4445                $self->{insertion_mode} = IN_CELL_IM;                $self->{insertion_mode} = IN_CELL_IM;
4446    
4447                push @$active_formatting_elements, ['#marker', ''];                push @$active_formatting_elements, ['#marker', ''];
# Line 4526  sub _tree_construction_main ($) { Line 4562  sub _tree_construction_main ($) {
4562                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4563                  }                  }
4564                                    
4565                  !!!insert-element ('colgroup');                  !!!insert-element ('colgroup',, $token);
4566                  $self->{insertion_mode} = IN_COLUMN_GROUP_IM;                  $self->{insertion_mode} = IN_COLUMN_GROUP_IM;
4567                  ## reprocess                  ## reprocess
4568                  redo B;                  redo B;
# Line 4546  sub _tree_construction_main ($) { Line 4582  sub _tree_construction_main ($) {
4582                  push @$active_formatting_elements, ['#marker', '']                  push @$active_formatting_elements, ['#marker', '']
4583                      if $token->{tag_name} eq 'caption';                      if $token->{tag_name} eq 'caption';
4584                                    
4585                  !!!insert-element ($token->{tag_name}, $token->{attributes});                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4586                  $self->{insertion_mode} = {                  $self->{insertion_mode} = {
4587                                             caption => IN_CAPTION_IM,                                             caption => IN_CAPTION_IM,
4588                                             colgroup => IN_COLUMN_GROUP_IM,                                             colgroup => IN_COLUMN_GROUP_IM,
# Line 4560  sub _tree_construction_main ($) { Line 4596  sub _tree_construction_main ($) {
4596                  die "$0: in table: <>: $token->{tag_name}";                  die "$0: in table: <>: $token->{tag_name}";
4597                }                }
4598              } elsif ($token->{tag_name} eq 'table') {              } elsif ($token->{tag_name} eq 'table') {
4599                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                !!!parse-error (type => 'not closed',
4600                                  value => $self->{open_elements}->[-1]->[0]
4601                                      ->manakai_local_name,
4602                                  token => $token);
4603    
4604                ## As if </table>                ## As if </table>
4605                ## have a table element in table scope                ## have a table element in table scope
# Line 4599  sub _tree_construction_main ($) { Line 4638  sub _tree_construction_main ($) {
4638    
4639                if ($self->{open_elements}->[-1]->[1] ne 'table') {                if ($self->{open_elements}->[-1]->[1] ne 'table') {
4640                  !!!cp ('t225');                  !!!cp ('t225');
4641  ## ISSUE: Can this case be reached?                  ## NOTE: |<table><tr><table>|
4642                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                  !!!parse-error (type => 'not closed',
4643                                    value => $self->{open_elements}->[-1]->[0]
4644                                        ->manakai_local_name,
4645                                    token => $token);
4646                } else {                } else {
4647                  !!!cp ('t226');                  !!!cp ('t226');
4648                }                }
# Line 4640  sub _tree_construction_main ($) { Line 4682  sub _tree_construction_main ($) {
4682                  !!!cp ('t227.3');                  !!!cp ('t227.3');
4683                  !!!parse-error (type => 'in table:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'in table:'.$token->{tag_name}, token => $token);
4684    
4685                  !!!insert-element ($token->{tag_name}, $token->{attributes});                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4686    
4687                  ## TODO: form element pointer                  ## TODO: form element pointer
4688    
# Line 4984  sub _tree_construction_main ($) { Line 5026  sub _tree_construction_main ($) {
5026            } elsif ($token->{type} == START_TAG_TOKEN) {            } elsif ($token->{type} == START_TAG_TOKEN) {
5027              if ($token->{tag_name} eq 'col') {              if ($token->{tag_name} eq 'col') {
5028                !!!cp ('t262');                !!!cp ('t262');
5029                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5030                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5031                !!!next-token;                !!!next-token;
5032                redo B;                redo B;
# Line 5066  sub _tree_construction_main ($) { Line 5108  sub _tree_construction_main ($) {
5108                  !!!cp ('t273');                  !!!cp ('t273');
5109                }                }
5110    
5111                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5112                !!!next-token;                !!!next-token;
5113                redo B;                redo B;
5114              } elsif ($token->{tag_name} eq 'optgroup') {              } elsif ($token->{tag_name} eq 'optgroup') {
# Line 5086  sub _tree_construction_main ($) { Line 5128  sub _tree_construction_main ($) {
5128                  !!!cp ('t277');                  !!!cp ('t277');
5129                }                }
5130    
5131                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5132                !!!next-token;                !!!next-token;
5133                redo B;                redo B;
5134          } elsif ($token->{tag_name} eq 'select' or          } elsif ($token->{tag_name} eq 'select' or
# Line 5429  sub _tree_construction_main ($) { Line 5471  sub _tree_construction_main ($) {
5471          if ($token->{tag_name} eq 'frameset' and          if ($token->{tag_name} eq 'frameset' and
5472              $self->{insertion_mode} == IN_FRAMESET_IM) {              $self->{insertion_mode} == IN_FRAMESET_IM) {
5473            !!!cp ('t318');            !!!cp ('t318');
5474            !!!insert-element ($token->{tag_name}, $token->{attributes});            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5475            !!!next-token;            !!!next-token;
5476            redo B;            redo B;
5477          } elsif ($token->{tag_name} eq 'frame' and          } elsif ($token->{tag_name} eq 'frame' and
5478                   $self->{insertion_mode} == IN_FRAMESET_IM) {                   $self->{insertion_mode} == IN_FRAMESET_IM) {
5479            !!!cp ('t319');            !!!cp ('t319');
5480            !!!insert-element ($token->{tag_name}, $token->{attributes});            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5481            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
5482            !!!next-token;            !!!next-token;
5483            redo B;            redo B;
# Line 5544  sub _tree_construction_main ($) { Line 5586  sub _tree_construction_main ($) {
5586                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
5587          !!!cp ('t334');          !!!cp ('t334');
5588          ## 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
5589          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
5590          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
5591          !!!next-token;          !!!next-token;
5592          redo B;          redo B;
5593        } elsif ($token->{tag_name} eq 'meta') {        } elsif ($token->{tag_name} eq 'meta') {
5594          ## 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
5595          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
5596          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.
5597    
5598          unless ($self->{confident}) {          unless ($self->{confident}) {
5599            if ($token->{attributes}->{charset}) { ## TODO: And if supported            if ($token->{attributes}->{charset}) { ## TODO: And if supported
5600              !!!cp ('t335');              !!!cp ('t335');
5601              $self->{change_encoding}              $self->{change_encoding}
5602                  ->($self, $token->{attributes}->{charset}->{value});                  ->($self, $token->{attributes}->{charset}->{value}, $token);
5603                            
5604              $meta_el->[0]->get_attribute_node_ns (undef, 'charset')              $meta_el->[0]->get_attribute_node_ns (undef, 'charset')
5605                  ->set_user_data (manakai_has_reference =>                  ->set_user_data (manakai_has_reference =>
# Line 5572  sub _tree_construction_main ($) { Line 5614  sub _tree_construction_main ($) {
5614                      ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {                      ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {
5615                !!!cp ('t336');                !!!cp ('t336');
5616                $self->{change_encoding}                $self->{change_encoding}
5617                    ->($self, defined $1 ? $1 : defined $2 ? $2 : $3);                    ->($self, defined $1 ? $1 : defined $2 ? $2 : $3, $token);
5618                $meta_el->[0]->get_attribute_node_ns (undef, 'content')                $meta_el->[0]->get_attribute_node_ns (undef, 'content')
5619                    ->set_user_data (manakai_has_reference =>                    ->set_user_data (manakai_has_reference =>
5620                                         $token->{attributes}->{content}                                         $token->{attributes}->{content}
# Line 5646  sub _tree_construction_main ($) { Line 5688  sub _tree_construction_main ($) {
5688            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5689              !!!cp ('t344');              !!!cp ('t344');
5690              !!!back-token;              !!!back-token;
5691              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p',
5692                          line => $token->{line}, column => $token->{column}};
5693              redo B;              redo B;
5694            } elsif ({            } elsif ({
5695                      applet => 1, table => 1, caption => 1, td => 1, th => 1,                      applet => 1, table => 1, caption => 1, td => 1, th => 1,
# Line 5657  sub _tree_construction_main ($) { Line 5700  sub _tree_construction_main ($) {
5700            }            }
5701          } # INSCOPE          } # INSCOPE
5702                        
5703          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
5704          if ($token->{tag_name} eq 'pre' or $token->{tag_name} eq 'listing') {          if ($token->{tag_name} eq 'pre' or $token->{tag_name} eq 'listing') {
5705            !!!next-token;            !!!next-token;
5706            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
# Line 5699  sub _tree_construction_main ($) { Line 5742  sub _tree_construction_main ($) {
5742            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5743              !!!cp ('t353');              !!!cp ('t353');
5744              !!!back-token;              !!!back-token;
5745              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p',
5746                          line => $token->{line}, column => $token->{column}};
5747              redo B;              redo B;
5748            } elsif ({            } elsif ({
5749                      applet => 1, table => 1, caption => 1, td => 1, th => 1,                      applet => 1, table => 1, caption => 1, td => 1, th => 1,
# Line 5721  sub _tree_construction_main ($) { Line 5765  sub _tree_construction_main ($) {
5765            if ($li_or_dtdd->{$node->[1]}) {            if ($li_or_dtdd->{$node->[1]}) {
5766              if ($i != -1) {              if ($i != -1) {
5767                !!!cp ('t355');                !!!cp ('t355');
5768                !!!parse-error (type => 'end tag missing:'.                !!!parse-error (type => 'not closed',
5769                                $self->{open_elements}->[-1]->[1], token => $token);                                value => $self->{open_elements}->[-1]->[0]
5770                                      ->manakai_local_name,
5771                                  token => $token);
5772              } else {              } else {
5773                !!!cp ('t356');                !!!cp ('t356');
5774              }              }
# Line 5749  sub _tree_construction_main ($) { Line 5795  sub _tree_construction_main ($) {
5795            redo LI;            redo LI;
5796          } # LI          } # LI
5797                        
5798          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
5799          !!!next-token;          !!!next-token;
5800          redo B;          redo B;
5801        } elsif ($token->{tag_name} eq 'plaintext') {        } elsif ($token->{tag_name} eq 'plaintext') {
# Line 5758  sub _tree_construction_main ($) { Line 5804  sub _tree_construction_main ($) {
5804            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5805              !!!cp ('t367');              !!!cp ('t367');
5806              !!!back-token;              !!!back-token;
5807              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p',
5808                          line => $token->{line}, column => $token->{column}};
5809              redo B;              redo B;
5810            } elsif ({            } elsif ({
5811                      applet => 1, table => 1, caption => 1, td => 1, th => 1,                      applet => 1, table => 1, caption => 1, td => 1, th => 1,
# Line 5769  sub _tree_construction_main ($) { Line 5816  sub _tree_construction_main ($) {
5816            }            }
5817          } # INSCOPE          } # INSCOPE
5818                        
5819          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
5820                        
5821          $self->{content_model} = PLAINTEXT_CONTENT_MODEL;          $self->{content_model} = PLAINTEXT_CONTENT_MODEL;
5822                        
# Line 5783  sub _tree_construction_main ($) { Line 5830  sub _tree_construction_main ($) {
5830              !!!parse-error (type => 'in a:a', token => $token);              !!!parse-error (type => 'in a:a', token => $token);
5831                            
5832              !!!back-token;              !!!back-token;
5833              $token = {type => END_TAG_TOKEN, tag_name => 'a'};              $token = {type => END_TAG_TOKEN, tag_name => 'a',
5834                          line => $token->{line}, column => $token->{column}};
5835              $formatting_end_tag->($token);              $formatting_end_tag->($token);
5836                            
5837              AFE2: for (reverse 0..$#$active_formatting_elements) {              AFE2: for (reverse 0..$#$active_formatting_elements) {
# Line 5809  sub _tree_construction_main ($) { Line 5857  sub _tree_construction_main ($) {
5857                        
5858          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5859    
5860          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
5861          push @$active_formatting_elements, $self->{open_elements}->[-1];          push @$active_formatting_elements, $self->{open_elements}->[-1];
5862    
5863          !!!next-token;          !!!next-token;
# Line 5824  sub _tree_construction_main ($) { Line 5872  sub _tree_construction_main ($) {
5872              !!!cp ('t376');              !!!cp ('t376');
5873              !!!parse-error (type => 'in nobr:nobr', token => $token);              !!!parse-error (type => 'in nobr:nobr', token => $token);
5874              !!!back-token;              !!!back-token;
5875              $token = {type => END_TAG_TOKEN, tag_name => 'nobr'};              $token = {type => END_TAG_TOKEN, tag_name => 'nobr',
5876                          line => $token->{line}, column => $token->{column}};
5877              redo B;              redo B;
5878            } elsif ({            } elsif ({
5879                      applet => 1, table => 1, caption => 1, td => 1, th => 1,                      applet => 1, table => 1, caption => 1, td => 1, th => 1,
# Line 5835  sub _tree_construction_main ($) { Line 5884  sub _tree_construction_main ($) {
5884            }            }
5885          } # INSCOPE          } # INSCOPE
5886                    
5887          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
5888          push @$active_formatting_elements, $self->{open_elements}->[-1];          push @$active_formatting_elements, $self->{open_elements}->[-1];
5889                    
5890          !!!next-token;          !!!next-token;
# Line 5848  sub _tree_construction_main ($) { Line 5897  sub _tree_construction_main ($) {
5897              !!!cp ('t378');              !!!cp ('t378');
5898              !!!parse-error (type => 'in button:button', token => $token);              !!!parse-error (type => 'in button:button', token => $token);
5899              !!!back-token;              !!!back-token;
5900              $token = {type => END_TAG_TOKEN, tag_name => 'button'};              $token = {type => END_TAG_TOKEN, tag_name => 'button',
5901                          line => $token->{line}, column => $token->{column}};
5902              redo B;              redo B;
5903            } elsif ({            } elsif ({
5904                      applet => 1, table => 1, caption => 1, td => 1, th => 1,                      applet => 1, table => 1, caption => 1, td => 1, th => 1,
# Line 5861  sub _tree_construction_main ($) { Line 5911  sub _tree_construction_main ($) {
5911                        
5912          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5913                        
5914          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
5915    
5916          ## TODO: associate with $self->{form_element} if defined          ## TODO: associate with $self->{form_element} if defined
5917    
# Line 5903  sub _tree_construction_main ($) { Line 5953  sub _tree_construction_main ($) {
5953            delete $at->{prompt};            delete $at->{prompt};
5954            my @tokens = (            my @tokens = (
5955                          {type => START_TAG_TOKEN, tag_name => 'form',                          {type => START_TAG_TOKEN, tag_name => 'form',
5956                           attributes => $form_attrs},                           attributes => $form_attrs,
5957                          {type => START_TAG_TOKEN, tag_name => 'hr'},                           line => $token->{line}, column => $token->{column}},
5958                          {type => START_TAG_TOKEN, tag_name => 'p'},                          {type => START_TAG_TOKEN, tag_name => 'hr',
5959                          {type => START_TAG_TOKEN, tag_name => 'label'},                           line => $token->{line}, column => $token->{column}},
5960                            {type => START_TAG_TOKEN, tag_name => 'p',
5961                             line => $token->{line}, column => $token->{column}},
5962                            {type => START_TAG_TOKEN, tag_name => 'label',
5963                             line => $token->{line}, column => $token->{column}},
5964                         );                         );
5965            if ($prompt_attr) {            if ($prompt_attr) {
5966              !!!cp ('t390');              !!!cp ('t390');
5967              push @tokens, {type => CHARACTER_TOKEN, data => $prompt_attr->{value}};              push @tokens, {type => CHARACTER_TOKEN, data => $prompt_attr->{value},
5968                               #line => $token->{line}, column => $token->{column},
5969                              };
5970            } else {            } else {
5971              !!!cp ('t391');              !!!cp ('t391');
5972              push @tokens, {type => CHARACTER_TOKEN,              push @tokens, {type => CHARACTER_TOKEN,
5973                             data => 'This is a searchable index. Insert your search keywords here: '}; # SHOULD                             data => 'This is a searchable index. Insert your search keywords here: ',
5974                               #line => $token->{line}, column => $token->{column},
5975                              }; # SHOULD
5976              ## TODO: make this configurable              ## TODO: make this configurable
5977            }            }
5978            push @tokens,            push @tokens,
5979                          {type => START_TAG_TOKEN, tag_name => 'input', attributes => $at},                          {type => START_TAG_TOKEN, tag_name => 'input', attributes => $at,
5980                             line => $token->{line}, column => $token->{column}},
5981                          #{type => CHARACTER_TOKEN, data => ''}, # SHOULD                          #{type => CHARACTER_TOKEN, data => ''}, # SHOULD
5982                          {type => END_TAG_TOKEN, tag_name => 'label'},                          {type => END_TAG_TOKEN, tag_name => 'label',
5983                          {type => END_TAG_TOKEN, tag_name => 'p'},                           line => $token->{line}, column => $token->{column}},
5984                          {type => START_TAG_TOKEN, tag_name => 'hr'},                          {type => END_TAG_TOKEN, tag_name => 'p',
5985                          {type => END_TAG_TOKEN, tag_name => 'form'};                           line => $token->{line}, column => $token->{column}},
5986                            {type => START_TAG_TOKEN, tag_name => 'hr',
5987                             line => $token->{line}, column => $token->{column}},
5988                            {type => END_TAG_TOKEN, tag_name => 'form',
5989                             line => $token->{line}, column => $token->{column}};
5990            $token = shift @tokens;            $token = shift @tokens;
5991            !!!back-token (@tokens);            !!!back-token (@tokens);
5992            redo B;            redo B;
# Line 5931  sub _tree_construction_main ($) { Line 5994  sub _tree_construction_main ($) {
5994        } elsif ($token->{tag_name} eq 'textarea') {        } elsif ($token->{tag_name} eq 'textarea') {
5995          my $tag_name = $token->{tag_name};          my $tag_name = $token->{tag_name};
5996          my $el;          my $el;
5997          !!!create-element ($el, $token->{tag_name}, $token->{attributes});          !!!create-element ($el, $token->{tag_name}, $token->{attributes}, $token);
5998                    
5999          ## TODO: $self->{form_element} if defined          ## TODO: $self->{form_element} if defined
6000          $self->{content_model} = RCDATA_CONTENT_MODEL;          $self->{content_model} = RCDATA_CONTENT_MODEL;
# Line 5999  sub _tree_construction_main ($) { Line 6062  sub _tree_construction_main ($) {
6062          ## NOTE: There is an "as if <br>" code clone.          ## NOTE: There is an "as if <br>" code clone.
6063          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
6064                    
6065          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6066    
6067          if ({          if ({
6068               applet => 1, marquee => 1, object => 1,               applet => 1, marquee => 1, object => 1,
# Line 6076  sub _tree_construction_main ($) { Line 6139  sub _tree_construction_main ($) {
6139                     tbody => 1, tfoot => 1, thead => 1,                     tbody => 1, tfoot => 1, thead => 1,
6140                    }->{$_->[1]}) {                    }->{$_->[1]}) {
6141              !!!cp ('t403');              !!!cp ('t403');
6142              !!!parse-error (type => 'not closed:'.$_->[1], token => $token);              !!!parse-error (type => 'not closed',
6143                                value => $_->[0]->manakai_local_name,
6144                                token => $token);
6145              last;              last;
6146            } else {            } else {
6147              !!!cp ('t404');              !!!cp ('t404');
# Line 6087  sub _tree_construction_main ($) { Line 6152  sub _tree_construction_main ($) {
6152          !!!next-token;          !!!next-token;
6153          redo B;          redo B;
6154        } elsif ($token->{tag_name} eq 'html') {        } elsif ($token->{tag_name} eq 'html') {
6155            ## TODO: Update this code.  It seems that the code below is not
6156            ## up-to-date, though it has same effect as speced.
6157          if (@{$self->{open_elements}} > 1 and $self->{open_elements}->[1]->[1] eq 'body') {          if (@{$self->{open_elements}} > 1 and $self->{open_elements}->[1]->[1] eq 'body') {
6158            ## ISSUE: There is an issue in the spec.            ## ISSUE: There is an issue in the spec.
6159            if ($self->{open_elements}->[-1]->[1] ne 'body') {            if ($self->{open_elements}->[-1]->[1] ne 'body') {
6160              !!!cp ('t406');              !!!cp ('t406');
6161              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[1]->[1], token => $token);              !!!parse-error (type => 'not closed',
6162                                value => $self->{open_elements}->[1]->[0]
6163                                    ->manakai_local_name,
6164                                token => $token);
6165            } else {            } else {
6166              !!!cp ('t407');              !!!cp ('t407');
6167            }            }
# Line 6147  sub _tree_construction_main ($) { Line 6217  sub _tree_construction_main ($) {
6217            ## Step 2.            ## Step 2.
6218            if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {            if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
6219              !!!cp ('t412');              !!!cp ('t412');
6220              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);              !!!parse-error (type => 'not closed',
6221                                value => $self->{open_elements}->[-1]->[0]
6222                                    ->manakai_local_name,
6223                                token => $token);
6224            } else {            } else {
6225              !!!cp ('t414');              !!!cp ('t414');
6226            }            }
# Line 6198  sub _tree_construction_main ($) { Line 6271  sub _tree_construction_main ($) {
6271            ## Step 2.            ## Step 2.
6272            if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {            if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
6273              !!!cp ('t417.1');              !!!cp ('t417.1');
6274              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);              !!!parse-error (type => 'not closed',
6275                                value => $self->{open_elements}->[-1]->[0]
6276                                    ->manakai_local_name,
6277                                token => $token);
6278            } else {            } else {
6279              !!!cp ('t420');              !!!cp ('t420');
6280            }              }  
# Line 6278  sub _tree_construction_main ($) { Line 6354  sub _tree_construction_main ($) {
6354          if (defined $i) {          if (defined $i) {
6355            if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {            if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
6356              !!!cp ('t412.1');              !!!cp ('t412.1');
6357              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);              !!!parse-error (type => 'not closed',
6358                                value => $self->{open_elements}->[-1]->[0]
6359                                    ->manakai_local_name,
6360                                token => $token);
6361            } else {            } else {
6362              !!!cp ('t414.1');              !!!cp ('t414.1');
6363            }            }
# Line 6291  sub _tree_construction_main ($) { Line 6370  sub _tree_construction_main ($) {
6370            !!!cp ('t415.1');            !!!cp ('t415.1');
6371            ## As if <p>, then reprocess the current token            ## As if <p>, then reprocess the current token
6372            my $el;            my $el;
6373            !!!create-element ($el, 'p');            !!!create-element ($el, 'p',, $token);
6374            $insert->($el);            $insert->($el);
6375            ## NOTE: Not inserted into |$self->{open_elements}|.            ## NOTE: Not inserted into |$self->{open_elements}|.
6376          }          }
# Line 6315  sub _tree_construction_main ($) { Line 6394  sub _tree_construction_main ($) {
6394          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
6395                    
6396          my $el;          my $el;
6397          !!!create-element ($el, 'br');          !!!create-element ($el, 'br',, $token);
6398          $insert->($el);          $insert->($el);
6399                    
6400          ## Ignore the token.          ## Ignore the token.
# Line 6363  sub _tree_construction_main ($) { Line 6442  sub _tree_construction_main ($) {
6442              if ($token->{tag_name} ne $self->{open_elements}->[-1]->[1]) {              if ($token->{tag_name} ne $self->{open_elements}->[-1]->[1]) {
6443                !!!cp ('t431');                !!!cp ('t431');
6444                ## NOTE: <x><y></x>                ## NOTE: <x><y></x>
6445                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                !!!parse-error (type => 'not closed',
6446                                  value => $self->{open_elements}->[-1]->[0]
6447                                      ->manakai_local_name,
6448                                  token => $token);
6449              } else {              } else {
6450                !!!cp ('t432');                !!!cp ('t432');
6451              }              }
# Line 6445  sub set_inner_html ($$$) { Line 6527  sub set_inner_html ($$$) {
6527    
6528      ## Step 8 # MUST      ## Step 8 # MUST
6529      my $i = 0;      my $i = 0;
6530      my $line = 1;      $p->{line_prev} = $p->{line} = 1;
6531      my $column = 0;      $p->{column_prev} = $p->{column} = 0;
6532      $p->{set_next_char} = sub {      $p->{set_next_char} = sub {
6533        my $self = shift;        my $self = shift;
6534    
# Line 6455  sub set_inner_html ($$$) { Line 6537  sub set_inner_html ($$$) {
6537    
6538        $self->{next_char} = -1 and return if $i >= length $$s;        $self->{next_char} = -1 and return if $i >= length $$s;
6539        $self->{next_char} = ord substr $$s, $i++, 1;        $self->{next_char} = ord substr $$s, $i++, 1;
6540        $column++;  
6541          ($p->{line_prev}, $p->{column_prev}) = ($p->{line}, $p->{column});
6542          $p->{column}++;
6543    
6544        if ($self->{next_char} == 0x000A) { # LF        if ($self->{next_char} == 0x000A) { # LF
6545          $line++;          $p->{line}++;
6546          $column = 0;          $p->{column} = 0;
6547          !!!cp ('i1');          !!!cp ('i1');
6548        } elsif ($self->{next_char} == 0x000D) { # CR        } elsif ($self->{next_char} == 0x000D) { # CR
6549          $i++ if substr ($$s, $i, 1) eq "\x0A";          $i++ if substr ($$s, $i, 1) eq "\x0A";
6550          $self->{next_char} = 0x000A; # LF # MUST          $self->{next_char} = 0x000A; # LF # MUST
6551          $line++;          $p->{line}++;
6552          $column = 0;          $p->{column} = 0;
6553          !!!cp ('i2');          !!!cp ('i2');
6554        } elsif ($self->{next_char} > 0x10FFFF) {        } elsif ($self->{next_char} > 0x10FFFF) {
6555          $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST          $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST
# Line 6481  sub set_inner_html ($$$) { Line 6565  sub set_inner_html ($$$) {
6565            
6566      my $ponerror = $onerror || sub {      my $ponerror = $onerror || sub {
6567        my (%opt) = @_;        my (%opt) = @_;
6568        warn "Parse error ($opt{type}) at line $opt{line} column $opt{column}\n";        my $line = $opt{line};
6569          my $column = $opt{column};
6570          if (defined $opt{token} and defined $opt{token}->{line}) {
6571            $line = $opt{token}->{line};
6572            $column = $opt{token}->{column};
6573          }
6574          warn "Parse error ($opt{type}) at line $line column $column\n";
6575      };      };
6576      $p->{parse_error} = sub {      $p->{parse_error} = sub {
6577        $ponerror->(@_, line => $line, column => $column);        $ponerror->(line => $p->{line}, column => $p->{column}, @_);
6578      };      };
6579            
6580      $p->_initialize_tokenizer;      $p->_initialize_tokenizer;
# Line 6564  sub set_inner_html ($$$) { Line 6654  sub set_inner_html ($$$) {
6654      ## ISSUE: mutation events?      ## ISSUE: mutation events?
6655    
6656      $p->_terminate_tree_constructor;      $p->_terminate_tree_constructor;
6657    
6658        delete $p->{parse_error}; # delete loop
6659    } else {    } else {
6660      die "$0: |set_inner_html| is not defined for node of type $nt";      die "$0: |set_inner_html| is not defined for node of type $nt";
6661    }    }

Legend:
Removed from v.1.113  
changed lines
  Added in v.1.122

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24