/[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.121 by wakaba, Thu Mar 20 08:04:58 2008 UTC revision 1.127 by wakaba, Sat Apr 12 15:25:52 2008 UTC
# Line 12  use Error qw(:try); Line 12  use Error qw(:try);
12  ## TODO: 1252 parse error (revision 1264)  ## TODO: 1252 parse error (revision 1264)
13  ## TODO: 8859-11 = 874 (revision 1271)  ## TODO: 8859-11 = 874 (revision 1271)
14    
15  my $permitted_slash_tag_name = {  my $HTML_NS = q<http://www.w3.org/1999/xhtml>;
16    base => 1,  my $MML_NS = q<http://www.w3.org/1998/Math/MathML>;
17    link => 1,  my $SVG_NS = q<http://www.w3.org/2000/svg>;
18    meta => 1,  my $XLINK_NS = q<http://www.w3.org/1999/xlink>;
19    hr => 1,  my $XML_NS = q<http://www.w3.org/XML/1998/namespace>;
20    br => 1,  my $XMLNS_NS = q<http://www.w3.org/2000/xmlns/>;
21    img => 1,  
22    embed => 1,  sub A_EL () { 0b1 }
23    param => 1,  sub ADDRESS_EL () { 0b10 }
24    area => 1,  sub BODY_EL () { 0b100 }
25    col => 1,  sub BUTTON_EL () { 0b1000 }
26    input => 1,  sub CAPTION_EL () { 0b10000 }
27    sub DD_EL () { 0b100000 }
28    sub DIV_EL () { 0b1000000 }
29    sub DT_EL () { 0b10000000 }
30    sub FORM_EL () { 0b100000000 }
31    sub FORMATTING_EL () { 0b1000000000 }
32    sub FRAMESET_EL () { 0b10000000000 }
33    sub HEADING_EL () { 0b100000000000 }
34    sub HTML_EL () { 0b1000000000000 }
35    sub LI_EL () { 0b10000000000000 }
36    sub NOBR_EL () { 0b100000000000000 }
37    sub OPTION_EL () { 0b1000000000000000 }
38    sub OPTGROUP_EL () { 0b10000000000000000 }
39    sub P_EL () { 0b100000000000000000 }
40    sub SELECT_EL () { 0b1000000000000000000 }
41    sub TABLE_EL () { 0b10000000000000000000 }
42    sub TABLE_CELL_EL () { 0b100000000000000000000 }
43    sub TABLE_ROW_EL () { 0b1000000000000000000000 }
44    sub TABLE_ROW_GROUP_EL () { 0b10000000000000000000000 }
45    sub MISC_SCOPING_EL () { 0b100000000000000000000000 }
46    sub MISC_SPECIAL_EL () { 0b1000000000000000000000000 }
47    sub FOREIGN_EL () { 0b10000000000000000000000000 }
48    sub FOREIGN_FLOW_CONTENT_EL () { 0b100000000000000000000000000 }
49    sub MML_AXML_EL () { 0b1000000000000000000000000000 }
50    
51    sub TABLE_ROWS_EL () {
52      TABLE_EL |
53      TABLE_ROW_EL |
54      TABLE_ROW_GROUP_EL
55    }
56    
57    sub END_TAG_OPTIONAL_EL () {
58      DD_EL |
59      DT_EL |
60      LI_EL |
61      P_EL
62    }
63    
64    sub ALL_END_TAG_OPTIONAL_EL () {
65      END_TAG_OPTIONAL_EL |
66      BODY_EL |
67      HTML_EL |
68      TABLE_CELL_EL |
69      TABLE_ROW_EL |
70      TABLE_ROW_GROUP_EL
71    }
72    
73    sub SCOPING_EL () {
74      BUTTON_EL |
75      CAPTION_EL |
76      HTML_EL |
77      TABLE_EL |
78      TABLE_CELL_EL |
79      MISC_SCOPING_EL
80    }
81    
82    sub TABLE_SCOPING_EL () {
83      HTML_EL |
84      TABLE_EL
85    }
86    
87    sub TABLE_ROWS_SCOPING_EL () {
88      HTML_EL |
89      TABLE_ROW_GROUP_EL
90    }
91    
92    sub TABLE_ROW_SCOPING_EL () {
93      HTML_EL |
94      TABLE_ROW_EL
95    }
96    
97    sub SPECIAL_EL () {
98      ADDRESS_EL |
99      BODY_EL |
100      DIV_EL |
101      END_TAG_OPTIONAL_EL |
102      FORM_EL |
103      FRAMESET_EL |
104      HEADING_EL |
105      OPTION_EL |
106      OPTGROUP_EL |
107      SELECT_EL |
108      TABLE_ROW_EL |
109      TABLE_ROW_GROUP_EL |
110      MISC_SPECIAL_EL
111    }
112    
113    my $el_category = {
114      a => A_EL | FORMATTING_EL,
115      address => ADDRESS_EL,
116      applet => MISC_SCOPING_EL,
117      area => MISC_SPECIAL_EL,
118      b => FORMATTING_EL,
119      base => MISC_SPECIAL_EL,
120      basefont => MISC_SPECIAL_EL,
121      bgsound => MISC_SPECIAL_EL,
122      big => FORMATTING_EL,
123      blockquote => MISC_SPECIAL_EL,
124      body => BODY_EL,
125      br => MISC_SPECIAL_EL,
126      button => BUTTON_EL,
127      caption => CAPTION_EL,
128      center => MISC_SPECIAL_EL,
129      col => MISC_SPECIAL_EL,
130      colgroup => MISC_SPECIAL_EL,
131      dd => DD_EL,
132      dir => MISC_SPECIAL_EL,
133      div => DIV_EL,
134      dl => MISC_SPECIAL_EL,
135      dt => DT_EL,
136      em => FORMATTING_EL,
137      embed => MISC_SPECIAL_EL,
138      fieldset => MISC_SPECIAL_EL,
139      font => FORMATTING_EL,
140      form => FORM_EL,
141      frame => MISC_SPECIAL_EL,
142      frameset => FRAMESET_EL,
143      h1 => HEADING_EL,
144      h2 => HEADING_EL,
145      h3 => HEADING_EL,
146      h4 => HEADING_EL,
147      h5 => HEADING_EL,
148      h6 => HEADING_EL,
149      head => MISC_SPECIAL_EL,
150      hr => MISC_SPECIAL_EL,
151      html => HTML_EL,
152      i => FORMATTING_EL,
153      iframe => MISC_SPECIAL_EL,
154      img => MISC_SPECIAL_EL,
155      input => MISC_SPECIAL_EL,
156      isindex => MISC_SPECIAL_EL,
157      li => LI_EL,
158      link => MISC_SPECIAL_EL,
159      listing => MISC_SPECIAL_EL,
160      marquee => MISC_SCOPING_EL,
161      menu => MISC_SPECIAL_EL,
162      meta => MISC_SPECIAL_EL,
163      nobr => NOBR_EL | FORMATTING_EL,
164      noembed => MISC_SPECIAL_EL,
165      noframes => MISC_SPECIAL_EL,
166      noscript => MISC_SPECIAL_EL,
167      object => MISC_SCOPING_EL,
168      ol => MISC_SPECIAL_EL,
169      optgroup => OPTGROUP_EL,
170      option => OPTION_EL,
171      p => P_EL,
172      param => MISC_SPECIAL_EL,
173      plaintext => MISC_SPECIAL_EL,
174      pre => MISC_SPECIAL_EL,
175      s => FORMATTING_EL,
176      script => MISC_SPECIAL_EL,
177      select => SELECT_EL,
178      small => FORMATTING_EL,
179      spacer => MISC_SPECIAL_EL,
180      strike => FORMATTING_EL,
181      strong => FORMATTING_EL,
182      style => MISC_SPECIAL_EL,
183      table => TABLE_EL,
184      tbody => TABLE_ROW_GROUP_EL,
185      td => TABLE_CELL_EL,
186      textarea => MISC_SPECIAL_EL,
187      tfoot => TABLE_ROW_GROUP_EL,
188      th => TABLE_CELL_EL,
189      thead => TABLE_ROW_GROUP_EL,
190      title => MISC_SPECIAL_EL,
191      tr => TABLE_ROW_EL,
192      tt => FORMATTING_EL,
193      u => FORMATTING_EL,
194      ul => MISC_SPECIAL_EL,
195      wbr => MISC_SPECIAL_EL,
196    };
197    
198    my $el_category_f = {
199      $MML_NS => {
200        'annotation-xml' => MML_AXML_EL,
201        mi => FOREIGN_FLOW_CONTENT_EL,
202        mo => FOREIGN_FLOW_CONTENT_EL,
203        mn => FOREIGN_FLOW_CONTENT_EL,
204        ms => FOREIGN_FLOW_CONTENT_EL,
205        mtext => FOREIGN_FLOW_CONTENT_EL,
206      },
207      $SVG_NS => {
208        foreignobject => FOREIGN_FLOW_CONTENT_EL, ## TODO: case
209        desc => FOREIGN_FLOW_CONTENT_EL,
210        title => FOREIGN_FLOW_CONTENT_EL,
211      },
212      ## NOTE: In addition, FOREIGN_EL is set to non-HTML elements.
213  };  };
214    
215  my $c1_entity_char = {  my $c1_entity_char = {
# Line 61  my $c1_entity_char = { Line 247  my $c1_entity_char = {
247    0x9F => 0x0178,    0x9F => 0x0178,
248  }; # $c1_entity_char  }; # $c1_entity_char
249    
 my $special_category = {  
   address => 1, area => 1, base => 1, basefont => 1, bgsound => 1,  
   blockquote => 1, body => 1, br => 1, center => 1, col => 1, colgroup => 1,  
   dd => 1, dir => 1, div => 1, dl => 1, dt => 1, embed => 1, fieldset => 1,  
   form => 1, frame => 1, frameset => 1, h1 => 1, h2 => 1, h3 => 1,  
   h4 => 1, h5 => 1, h6 => 1, head => 1, hr => 1, iframe => 1, image => 1,  
   img => 1, input => 1, isindex => 1, li => 1, link => 1, listing => 1,  
   menu => 1, meta => 1, noembed => 1, noframes => 1, noscript => 1,  
   ol => 1, optgroup => 1, option => 1, p => 1, param => 1, plaintext => 1,  
   pre => 1, script => 1, select => 1, spacer => 1, style => 1, tbody => 1,  
   textarea => 1, tfoot => 1, thead => 1, title => 1, tr => 1, ul => 1, wbr => 1,  
 };  
 my $scoping_category = {  
   applet => 1, button => 1, caption => 1, html => 1, marquee => 1, object => 1,  
   table => 1, td => 1, th => 1,  
 };  
 my $formatting_category = {  
   a => 1, b => 1, big => 1, em => 1, font => 1, i => 1, nobr => 1,  
   s => 1, small => 1, strile => 1, strong => 1, tt => 1, u => 1,  
 };  
 # $phrasing_category: all other elements  
   
250  sub parse_byte_string ($$$$;$) {  sub parse_byte_string ($$$$;$) {
251    my $self = ref $_[0] ? shift : shift->new;    my $self = ref $_[0] ? shift : shift->new;
252    my $charset = shift;    my $charset = shift;
# Line 295  sub DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUO Line 459  sub DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUO
459  sub AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE () { 31 }  sub AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE () { 31 }
460  sub BOGUS_DOCTYPE_STATE () { 32 }  sub BOGUS_DOCTYPE_STATE () { 32 }
461  sub AFTER_ATTRIBUTE_VALUE_QUOTED_STATE () { 33 }  sub AFTER_ATTRIBUTE_VALUE_QUOTED_STATE () { 33 }
462    sub SELF_CLOSING_START_TAG_STATE () { 34 }
463    sub CDATA_BLOCK_STATE () { 35 }
464    
465  sub DOCTYPE_TOKEN () { 1 }  sub DOCTYPE_TOKEN () { 1 }
466  sub COMMENT_TOKEN () { 2 }  sub COMMENT_TOKEN () { 2 }
# Line 312  sub ROW_IMS ()        { 0b10000000 } Line 478  sub ROW_IMS ()        { 0b10000000 }
478  sub BODY_AFTER_IMS () { 0b100000000 }  sub BODY_AFTER_IMS () { 0b100000000 }
479  sub FRAME_IMS ()      { 0b1000000000 }  sub FRAME_IMS ()      { 0b1000000000 }
480  sub SELECT_IMS ()     { 0b10000000000 }  sub SELECT_IMS ()     { 0b10000000000 }
481    sub IN_FOREIGN_CONTENT_IM () { 0b100000000000 }
482        ## NOTE: "in foreign content" insertion mode is special; it is combined
483        ## with the secondary insertion mode.  In this parser, they are stored
484        ## together in the bit-or'ed form.
485    
486  ## NOTE: "initial" and "before html" insertion modes have no constants.  ## NOTE: "initial" and "before html" insertion modes have no constants.
487    
# Line 348  sub _initialize_tokenizer ($) { Line 518  sub _initialize_tokenizer ($) {
518    undef $self->{current_attribute};    undef $self->{current_attribute};
519    undef $self->{last_emitted_start_tag_name};    undef $self->{last_emitted_start_tag_name};
520    undef $self->{last_attribute_value_state};    undef $self->{last_attribute_value_state};
521      delete $self->{self_closing};
522    $self->{char} = [];    $self->{char} = [];
523    # $self->{next_char}    # $self->{next_char}
524    !!!next-input-character;    !!!next-input-character;
# Line 368  sub _initialize_tokenizer ($) { Line 539  sub _initialize_tokenizer ($) {
539  ##        ->{value}  ##        ->{value}
540  ##        ->{has_reference} == 1 or 0  ##        ->{has_reference} == 1 or 0
541  ##   ->{data} (COMMENT_TOKEN, CHARACTER_TOKEN)  ##   ->{data} (COMMENT_TOKEN, CHARACTER_TOKEN)
542    ## NOTE: The "self-closing flag" is hold as |$self->{self_closing}|.
543    ##     |->{self_closing}| is used to save the value of |$self->{self_closing}|
544    ##     while the token is pushed back to the stack.
545    
546    ## ISSUE: "When a DOCTYPE token is created, its
547    ## <i>self-closing flag</i> must be unset (its other state is that it
548    ## be set), and its attributes list must be empty.": Wrong subject?
549    
550  ## Emitted token MUST immediately be handled by the tree construction state.  ## Emitted token MUST immediately be handled by the tree construction state.
551    
# Line 394  sub _initialize_tokenizer ($) { Line 572  sub _initialize_tokenizer ($) {
572    
573  sub _get_next_token ($) {  sub _get_next_token ($) {
574    my $self = shift;    my $self = shift;
575    
576      if ($self->{self_closing}) {
577        !!!parse-error (type => 'nestc', token => $self->{current_token});
578        ## NOTE: The |self_closing| flag is only set by start tag token.
579        ## In addition, when a start tag token is emitted, it is always set to
580        ## |current_token|.
581        delete $self->{self_closing};
582      }
583    
584    if (@{$self->{token}}) {    if (@{$self->{token}}) {
585        $self->{self_closing} = $self->{token}->[0]->{self_closing};
586      return shift @{$self->{token}};      return shift @{$self->{token}};
587    }    }
588    
# Line 765  sub _get_next_token ($) { Line 953  sub _get_next_token ($) {
953    
954          redo A;          redo A;
955        } elsif ($self->{next_char} == 0x002F) { # /        } elsif ($self->{next_char} == 0x002F) { # /
956            !!!cp (42);
957            $self->{state} = SELF_CLOSING_START_TAG_STATE;
958          !!!next-input-character;          !!!next-input-character;
         if ($self->{next_char} == 0x003E and # >  
             $self->{current_token}->{type} == START_TAG_TOKEN and  
             $permitted_slash_tag_name->{$self->{current_token}->{tag_name}}) {  
           # permitted slash  
           !!!cp (42);  
           #  
         } else {  
           !!!cp (43);  
           !!!parse-error (type => 'nestc');  
         }  
         $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;  
         # next-input-character is already done  
959          redo A;          redo A;
960        } else {        } else {
961          !!!cp (44);          !!!cp (44);
# Line 829  sub _get_next_token ($) { Line 1007  sub _get_next_token ($) {
1007          !!!next-input-character;          !!!next-input-character;
1008          redo A;          redo A;
1009        } elsif ($self->{next_char} == 0x002F) { # /        } elsif ($self->{next_char} == 0x002F) { # /
1010            !!!cp (50);
1011            $self->{state} = SELF_CLOSING_START_TAG_STATE;
1012          !!!next-input-character;          !!!next-input-character;
         if ($self->{next_char} == 0x003E and # >  
             $self->{current_token}->{type} == START_TAG_TOKEN and  
             $permitted_slash_tag_name->{$self->{current_token}->{tag_name}}) {  
           # permitted slash  
           !!!cp (50);  
           #  
         } else {  
           !!!cp (51);  
           !!!parse-error (type => 'nestc');  
         }  
         ## Stay in the state  
         # next-input-character is already done  
1013          redo A;          redo A;
1014        } elsif ($self->{next_char} == -1) {        } elsif ($self->{next_char} == -1) {
1015          !!!parse-error (type => 'unclosed tag');          !!!parse-error (type => 'unclosed tag');
# Line 942  sub _get_next_token ($) { Line 1110  sub _get_next_token ($) {
1110          !!!next-input-character;          !!!next-input-character;
1111          redo A;          redo A;
1112        } elsif ($self->{next_char} == 0x002F) { # /        } elsif ($self->{next_char} == 0x002F) { # /
1113            !!!cp (64);
1114          $before_leave->();          $before_leave->();
1115            $self->{state} = SELF_CLOSING_START_TAG_STATE;
1116          !!!next-input-character;          !!!next-input-character;
         if ($self->{next_char} == 0x003E and # >  
             $self->{current_token}->{type} == START_TAG_TOKEN and  
             $permitted_slash_tag_name->{$self->{current_token}->{tag_name}}) {  
           # permitted slash  
           !!!cp (64);  
           #  
         } else {  
           !!!cp (65);  
           !!!parse-error (type => 'nestc');  
         }  
         $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;  
         # next-input-character is already done  
1117          redo A;          redo A;
1118        } elsif ($self->{next_char} == -1) {        } elsif ($self->{next_char} == -1) {
1119          !!!parse-error (type => 'unclosed tag');          !!!parse-error (type => 'unclosed tag');
# Line 1042  sub _get_next_token ($) { Line 1200  sub _get_next_token ($) {
1200          !!!next-input-character;          !!!next-input-character;
1201          redo A;          redo A;
1202        } elsif ($self->{next_char} == 0x002F) { # /        } elsif ($self->{next_char} == 0x002F) { # /
1203            !!!cp (77);
1204            $self->{state} = SELF_CLOSING_START_TAG_STATE;
1205          !!!next-input-character;          !!!next-input-character;
         if ($self->{next_char} == 0x003E and # >  
             $self->{current_token}->{type} == START_TAG_TOKEN and  
             $permitted_slash_tag_name->{$self->{current_token}->{tag_name}}) {  
           # permitted slash  
           !!!cp (77);  
           #  
         } else {  
           !!!cp (78);  
           !!!parse-error (type => 'nestc');  
           ## TODO: Different error type for <aa / bb> than <aa/>  
         }  
         $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;  
         # next-input-character is already done  
1206          redo A;          redo A;
1207        } elsif ($self->{next_char} == -1) {        } elsif ($self->{next_char} == -1) {
1208          !!!parse-error (type => 'unclosed tag');          !!!parse-error (type => 'unclosed tag');
# Line 1388  sub _get_next_token ($) { Line 1535  sub _get_next_token ($) {
1535    
1536          redo A;          redo A;
1537        } elsif ($self->{next_char} == 0x002F) { # /        } elsif ($self->{next_char} == 0x002F) { # /
1538            !!!cp (122);
1539            $self->{state} = SELF_CLOSING_START_TAG_STATE;
1540          !!!next-input-character;          !!!next-input-character;
         if ($self->{next_char} == 0x003E and # >  
             $self->{current_token}->{type} == START_TAG_TOKEN and  
             $permitted_slash_tag_name->{$self->{current_token}->{tag_name}}) {  
           # permitted slash  
           !!!cp (122);  
           #  
         } else {  
           !!!cp (123);  
           !!!parse-error (type => 'nestc');  
         }  
         $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;  
         # next-input-character is already done  
1541          redo A;          redo A;
1542        } else {        } else {
1543          !!!cp (124);          !!!cp ('124.1');
1544          !!!parse-error (type => 'no space between attributes');          !!!parse-error (type => 'no space between attributes');
1545          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;
1546          ## reconsume          ## reconsume
1547          redo A;          redo A;
1548        }        }
1549        } elsif ($self->{state} == SELF_CLOSING_START_TAG_STATE) {
1550          if ($self->{next_char} == 0x003E) { # >
1551            if ($self->{current_token}->{type} == END_TAG_TOKEN) {
1552              !!!cp ('124.2');
1553              !!!parse-error (type => 'nestc', token => $self->{current_token});
1554              ## TODO: Different type than slash in start tag
1555              $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
1556              if ($self->{current_token}->{attributes}) {
1557                !!!cp ('124.4');
1558                !!!parse-error (type => 'end tag attribute');
1559              } else {
1560                !!!cp ('124.5');
1561              }
1562              ## TODO: Test |<title></title/>|
1563            } else {
1564              !!!cp ('124.3');
1565              $self->{self_closing} = 1;
1566            }
1567    
1568            $self->{state} = DATA_STATE;
1569            !!!next-input-character;
1570    
1571            !!!emit ($self->{current_token}); # start tag or end tag
1572    
1573            redo A;
1574          } else {
1575            !!!cp ('124.4');
1576            !!!parse-error (type => 'nestc');
1577            ## TODO: This error type is wrong.
1578            $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;
1579            ## Reconsume.
1580            redo A;
1581          }
1582      } elsif ($self->{state} == BOGUS_COMMENT_STATE) {      } elsif ($self->{state} == BOGUS_COMMENT_STATE) {
1583        ## (only happen if PCDATA state)        ## (only happen if PCDATA state)
1584                
# Line 1516  sub _get_next_token ($) { Line 1686  sub _get_next_token ($) {
1686          } else {          } else {
1687            !!!cp (135);            !!!cp (135);
1688          }          }
1689          } elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM and
1690                   $self->{open_elements}->[-1]->[1] & FOREIGN_EL and
1691                   $self->{next_char} == 0x005B) { # [
1692            !!!next-input-character;
1693            push @next_char, $self->{next_char};
1694            if ($self->{next_char} == 0x0043) { # C
1695              !!!next-input-character;
1696              push @next_char, $self->{next_char};
1697              if ($self->{next_char} == 0x0044) { # D
1698                !!!next-input-character;
1699                push @next_char, $self->{next_char};
1700                if ($self->{next_char} == 0x0041) { # A
1701                  !!!next-input-character;
1702                  push @next_char, $self->{next_char};
1703                  if ($self->{next_char} == 0x0054) { # T
1704                    !!!next-input-character;
1705                    push @next_char, $self->{next_char};
1706                    if ($self->{next_char} == 0x0041) { # A
1707                      !!!next-input-character;
1708                      push @next_char, $self->{next_char};
1709                      if ($self->{next_char} == 0x005B) { # [
1710                        !!!cp (135.1);
1711                        $self->{state} = CDATA_BLOCK_STATE;
1712                        !!!next-input-character;
1713                        redo A;
1714                      } else {
1715                        !!!cp (135.2);
1716                      }
1717                    } else {
1718                      !!!cp (135.3);
1719                    }
1720                  } else {
1721                    !!!cp (135.4);                
1722                  }
1723                } else {
1724                  !!!cp (135.5);
1725                }
1726              } else {
1727                !!!cp (135.6);
1728              }
1729            } else {
1730              !!!cp (135.7);
1731            }
1732        } else {        } else {
1733          !!!cp (136);          !!!cp (136);
1734        }        }
# Line 2240  sub _get_next_token ($) { Line 2453  sub _get_next_token ($) {
2453          !!!next-input-character;          !!!next-input-character;
2454          redo A;          redo A;
2455        }        }
2456        } elsif ($self->{state} == CDATA_BLOCK_STATE) {
2457          my $s = '';
2458          
2459          my ($l, $c) = ($self->{line}, $self->{column});
2460    
2461          CS: while ($self->{next_char} != -1) {
2462            if ($self->{next_char} == 0x005D) { # ]
2463              !!!next-input-character;
2464              if ($self->{next_char} == 0x005D) { # ]
2465                !!!next-input-character;
2466                MDC: {
2467                  if ($self->{next_char} == 0x003E) { # >
2468                    !!!cp (221.1);
2469                    !!!next-input-character;
2470                    last CS;
2471                  } elsif ($self->{next_char} == 0x005D) { # ]
2472                    !!!cp (221.2);
2473                    $s .= ']';
2474                    !!!next-input-character;
2475                    redo MDC;
2476                  } else {
2477                    !!!cp (221.3);
2478                    $s .= ']]';
2479                    #
2480                  }
2481                } # MDC
2482              } else {
2483                !!!cp (221.4);
2484                $s .= ']';
2485                #
2486              }
2487            } else {
2488              !!!cp (221.5);
2489              #
2490            }
2491            $s .= chr $self->{next_char};
2492            !!!next-input-character;
2493          } # CS
2494    
2495          $self->{state} = DATA_STATE;
2496          ## next-input-character done or EOF, which is reconsumed.
2497    
2498          if (length $s) {
2499            !!!cp (221.6);
2500            !!!emit ({type => CHARACTER_TOKEN, data => $s,
2501                      line => $l, column => $c});
2502          } else {
2503            !!!cp (221.7);
2504          }
2505    
2506          redo A;
2507    
2508          ## ISSUE: "text tokens" in spec.
2509          ## TODO: Streaming support
2510      } else {      } else {
2511        die "$0: $self->{state}: Unknown state";        die "$0: $self->{state}: Unknown state";
2512      }      }
# Line 2532  sub _tree_construction_initial ($) { Line 2799  sub _tree_construction_initial ($) {
2799                
2800        my $doctype = $self->{document}->create_document_type_definition        my $doctype = $self->{document}->create_document_type_definition
2801          ($token->{name}); ## ISSUE: If name is missing (e.g. <!DOCTYPE>)?          ($token->{name}); ## ISSUE: If name is missing (e.g. <!DOCTYPE>)?
2802          ## NOTE: Default value for both |public_id| and |system_id| attributes
2803          ## are empty strings, so that we don't set any value in missing cases.
2804        $doctype->public_id ($token->{public_identifier})        $doctype->public_id ($token->{public_identifier})
2805            if defined $token->{public_identifier};            if defined $token->{public_identifier};
2806        $doctype->system_id ($token->{system_identifier})        $doctype->system_id ($token->{system_identifier})
# Line 2668  sub _tree_construction_initial ($) { Line 2937  sub _tree_construction_initial ($) {
2937        $self->{document}->manakai_compat_mode ('quirks');        $self->{document}->manakai_compat_mode ('quirks');
2938        ## Go to the "before html" insertion mode.        ## Go to the "before html" insertion mode.
2939        ## reprocess        ## reprocess
2940          !!!ack-later;
2941        return;        return;
2942      } elsif ($token->{type} == CHARACTER_TOKEN) {      } elsif ($token->{type} == CHARACTER_TOKEN) {
2943        if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { # \x0D        if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { # \x0D
# Line 2748  sub _tree_construction_root_element ($) Line 3018  sub _tree_construction_root_element ($)
3018        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
3019          if ($token->{tag_name} eq 'html') {          if ($token->{tag_name} eq 'html') {
3020            my $root_element;            my $root_element;
3021            !!!create-element ($root_element, $token->{tag_name}, $token->{attributes}, $token);            !!!create-element ($root_element, $HTML_NS, $token->{tag_name}, $token->{attributes}, $token);
3022            $self->{document}->append_child ($root_element);            $self->{document}->append_child ($root_element);
3023            push @{$self->{open_elements}}, [$root_element, 'html'];            push @{$self->{open_elements}},
3024                  [$root_element, $el_category->{html}];
3025    
3026            if ($token->{attributes}->{manifest}) {            if ($token->{attributes}->{manifest}) {
3027              !!!cp ('t24');              !!!cp ('t24');
# Line 2765  sub _tree_construction_root_element ($) Line 3036  sub _tree_construction_root_element ($)
3036              $self->{application_cache_selection}->(undef);              $self->{application_cache_selection}->(undef);
3037            }            }
3038    
3039              !!!nack ('t25c');
3040    
3041            !!!next-token;            !!!next-token;
3042            return; ## Go to the "before head" insertion mode.            return; ## Go to the "before head" insertion mode.
3043          } else {          } else {
# Line 2781  sub _tree_construction_root_element ($) Line 3054  sub _tree_construction_root_element ($)
3054          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
3055        }        }
3056    
3057      my $root_element; !!!create-element ($root_element, 'html',, $token);      my $root_element;
3058        !!!create-element ($root_element, $HTML_NS, 'html',, $token);
3059      $self->{document}->append_child ($root_element);      $self->{document}->append_child ($root_element);
3060      push @{$self->{open_elements}}, [$root_element, 'html'];      push @{$self->{open_elements}}, [$root_element, $el_category->{html}];
3061    
3062      $self->{application_cache_selection}->(undef);      $self->{application_cache_selection}->(undef);
3063    
3064      ## NOTE: Reprocess the token.      ## NOTE: Reprocess the token.
3065        !!!ack-later;
3066      return; ## Go to the "before head" insertion mode.      return; ## Go to the "before head" insertion mode.
3067    
3068      ## ISSUE: There is an issue in the spec      ## ISSUE: There is an issue in the spec
# Line 2811  sub _reset_insertion_mode ($) { Line 3086  sub _reset_insertion_mode ($) {
3086        if ($self->{open_elements}->[0]->[0] eq $node->[0]) {        if ($self->{open_elements}->[0]->[0] eq $node->[0]) {
3087          $last = 1;          $last = 1;
3088          if (defined $self->{inner_html_node}) {          if (defined $self->{inner_html_node}) {
3089            if ($self->{inner_html_node}->[1] eq 'td' or            if ($self->{inner_html_node}->[1] & TABLE_CELL_EL) {
               $self->{inner_html_node}->[1] eq 'th') {  
3090              !!!cp ('t27');              !!!cp ('t27');
3091              #              #
3092            } else {            } else {
# Line 2822  sub _reset_insertion_mode ($) { Line 3096  sub _reset_insertion_mode ($) {
3096          }          }
3097        }        }
3098            
3099        ## Step 4..13      ## Step 4..14
3100        my $new_mode = {      my $new_mode;
3101        if ($node->[1] & FOREIGN_EL) {
3102          ## NOTE: Strictly spaking, the line below only applies to MathML and
3103          ## SVG elements.  Currently the HTML syntax supports only MathML and
3104          ## SVG elements as foreigners.
3105          $new_mode = $self->{insertion_mode} | IN_FOREIGN_CONTENT_IM;
3106          ## ISSUE: What is set as the secondary insertion mode?
3107        } else {
3108          $new_mode = {
3109                        select => IN_SELECT_IM,                        select => IN_SELECT_IM,
3110                        ## NOTE: |option| and |optgroup| do not set                        ## NOTE: |option| and |optgroup| do not set
3111                        ## insertion mode to "in select" by themselves.                        ## insertion mode to "in select" by themselves.
# Line 2839  sub _reset_insertion_mode ($) { Line 3121  sub _reset_insertion_mode ($) {
3121                        head => IN_BODY_IM, # not in head!                        head => IN_BODY_IM, # not in head!
3122                        body => IN_BODY_IM,                        body => IN_BODY_IM,
3123                        frameset => IN_FRAMESET_IM,                        frameset => IN_FRAMESET_IM,
3124                       }->{$node->[1]};                       }->{$node->[0]->manakai_local_name};
3125        $self->{insertion_mode} = $new_mode and return if defined $new_mode;      }
3126        $self->{insertion_mode} = $new_mode and return if defined $new_mode;
3127                
3128        ## Step 14        ## Step 15
3129        if ($node->[1] eq 'html') {        if ($node->[1] & HTML_EL) {
3130          unless (defined $self->{head_element}) {          unless (defined $self->{head_element}) {
3131            !!!cp ('t29');            !!!cp ('t29');
3132            $self->{insertion_mode} = BEFORE_HEAD_IM;            $self->{insertion_mode} = BEFORE_HEAD_IM;
# Line 2857  sub _reset_insertion_mode ($) { Line 3140  sub _reset_insertion_mode ($) {
3140          !!!cp ('t31');          !!!cp ('t31');
3141        }        }
3142                
3143        ## Step 15        ## Step 16
3144        $self->{insertion_mode} = IN_BODY_IM and return if $last;        $self->{insertion_mode} = IN_BODY_IM and return if $last;
3145                
3146        ## Step 16        ## Step 17
3147        $i--;        $i--;
3148        $node = $self->{open_elements}->[$i];        $node = $self->{open_elements}->[$i];
3149                
3150        ## Step 17        ## Step 18
3151        redo S3;        redo S3;
3152      } # S3      } # S3
3153    
# Line 2976  sub _tree_construction_main ($) { Line 3259  sub _tree_construction_main ($) {
3259      ## Step 1      ## Step 1
3260      my $start_tag_name = $token->{tag_name};      my $start_tag_name = $token->{tag_name};
3261      my $el;      my $el;
3262      !!!create-element ($el, $start_tag_name, $token->{attributes}, $token);      !!!create-element ($el, $HTML_NS, $start_tag_name, $token->{attributes}, $token);
3263    
3264      ## Step 2      ## Step 2
3265      $insert->($el);      $insert->($el);
# Line 2987  sub _tree_construction_main ($) { Line 3270  sub _tree_construction_main ($) {
3270    
3271      ## Step 4      ## Step 4
3272      my $text = '';      my $text = '';
3273        !!!nack ('t40.1');
3274      !!!next-token;      !!!next-token;
3275      while ($token->{type} == CHARACTER_TOKEN) { # or until stop tokenizing      while ($token->{type} == CHARACTER_TOKEN) { # or until stop tokenizing
3276        !!!cp ('t40');        !!!cp ('t40');
# Line 3026  sub _tree_construction_main ($) { Line 3310  sub _tree_construction_main ($) {
3310    
3311    my $script_start_tag = sub () {    my $script_start_tag = sub () {
3312      my $script_el;      my $script_el;
3313      !!!create-element ($script_el, 'script', $token->{attributes}, $token);      !!!create-element ($script_el, $HTML_NS, 'script', $token->{attributes}, $token);
3314      ## TODO: mark as "parser-inserted"      ## TODO: mark as "parser-inserted"
3315    
3316      $self->{content_model} = CDATA_CONTENT_MODEL;      $self->{content_model} = CDATA_CONTENT_MODEL;
3317      delete $self->{escape}; # MUST      delete $self->{escape}; # MUST
3318            
3319      my $text = '';      my $text = '';
3320        !!!nack ('t45.1');
3321      !!!next-token;      !!!next-token;
3322      while ($token->{type} == CHARACTER_TOKEN) {      while ($token->{type} == CHARACTER_TOKEN) {
3323        !!!cp ('t45');        !!!cp ('t45');
# Line 3090  sub _tree_construction_main ($) { Line 3375  sub _tree_construction_main ($) {
3375        my $formatting_element;        my $formatting_element;
3376        my $formatting_element_i_in_active;        my $formatting_element_i_in_active;
3377        AFE: for (reverse 0..$#$active_formatting_elements) {        AFE: for (reverse 0..$#$active_formatting_elements) {
3378          if ($active_formatting_elements->[$_]->[1] eq $tag_name) {          if ($active_formatting_elements->[$_]->[0] eq '#marker') {
3379              !!!cp ('t52');
3380              last AFE;
3381            } elsif ($active_formatting_elements->[$_]->[0]->manakai_local_name
3382                         eq $tag_name) {
3383            !!!cp ('t51');            !!!cp ('t51');
3384            $formatting_element = $active_formatting_elements->[$_];            $formatting_element = $active_formatting_elements->[$_];
3385            $formatting_element_i_in_active = $_;            $formatting_element_i_in_active = $_;
3386            last AFE;            last AFE;
         } elsif ($active_formatting_elements->[$_]->[0] eq '#marker') {  
           !!!cp ('t52');  
           last AFE;  
3387          }          }
3388        } # AFE        } # AFE
3389        unless (defined $formatting_element) {        unless (defined $formatting_element) {
# Line 3125  sub _tree_construction_main ($) { Line 3411  sub _tree_construction_main ($) {
3411              !!!next-token;              !!!next-token;
3412              return;              return;
3413            }            }
3414          } elsif ({          } elsif ($node->[1] & SCOPING_EL) {
                   applet => 1, table => 1, caption => 1, td => 1, th => 1,  
                   button => 1, marquee => 1, object => 1, html => 1,  
                  }->{$node->[1]}) {  
3415            !!!cp ('t56');            !!!cp ('t56');
3416            $in_scope = 0;            $in_scope = 0;
3417          }          }
# Line 3143  sub _tree_construction_main ($) { Line 3426  sub _tree_construction_main ($) {
3426        }        }
3427        if (not $self->{open_elements}->[-1]->[0] eq $formatting_element->[0]) {        if (not $self->{open_elements}->[-1]->[0] eq $formatting_element->[0]) {
3428          !!!cp ('t58');          !!!cp ('t58');
3429          !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1],          !!!parse-error (type => 'not closed',
3430                            value => $self->{open_elements}->[-1]->[0]
3431                                ->manakai_local_name,
3432                          token => $end_tag_token);                          token => $end_tag_token);
3433        }        }
3434                
# Line 3152  sub _tree_construction_main ($) { Line 3437  sub _tree_construction_main ($) {
3437        my $furthest_block_i_in_open;        my $furthest_block_i_in_open;
3438        OE: for (reverse 0..$#{$self->{open_elements}}) {        OE: for (reverse 0..$#{$self->{open_elements}}) {
3439          my $node = $self->{open_elements}->[$_];          my $node = $self->{open_elements}->[$_];
3440          if (not $formatting_category->{$node->[1]} and          if (not ($node->[1] & FORMATTING_EL) and
3441              #not $phrasing_category->{$node->[1]} and              #not $phrasing_category->{$node->[1]} and
3442              ($special_category->{$node->[1]} or              ($node->[1] & SPECIAL_EL or
3443               $scoping_category->{$node->[1]})) { ## Scoping is redundant, maybe               $node->[1] & SCOPING_EL)) { ## Scoping is redundant, maybe
3444            !!!cp ('t59');            !!!cp ('t59');
3445            $furthest_block = $node;            $furthest_block = $node;
3446            $furthest_block_i_in_open = $_;            $furthest_block_i_in_open = $_;
# Line 3241  sub _tree_construction_main ($) { Line 3526  sub _tree_construction_main ($) {
3526        } # S7          } # S7  
3527                
3528        ## Step 8        ## Step 8
3529        if ({        if ($common_ancestor_node->[1] & TABLE_ROWS_EL) {
            table => 1, tbody => 1, tfoot => 1, thead => 1, tr => 1,  
           }->{$common_ancestor_node->[1]}) {  
3530          my $foster_parent_element;          my $foster_parent_element;
3531          my $next_sibling;          my $next_sibling;
3532                           OE: for (reverse 0..$#{$self->{open_elements}}) {          OE: for (reverse 0..$#{$self->{open_elements}}) {
3533                             if ($self->{open_elements}->[$_]->[1] eq 'table') {            if ($self->{open_elements}->[$_]->[1] & TABLE_EL) {
3534                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
3535                               if (defined $parent and $parent->node_type == 1) {                               if (defined $parent and $parent->node_type == 1) {
3536                                 !!!cp ('t65.1');                                 !!!cp ('t65.1');
# Line 3320  sub _tree_construction_main ($) { Line 3603  sub _tree_construction_main ($) {
3603    
3604    my $insert_to_foster = sub {    my $insert_to_foster = sub {
3605      my $child = shift;      my $child = shift;
3606      if ({      if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {
          table => 1, tbody => 1, tfoot => 1, thead => 1, tr => 1,  
         }->{$self->{open_elements}->[-1]->[1]}) {  
3607        # MUST        # MUST
3608        my $foster_parent_element;        my $foster_parent_element;
3609        my $next_sibling;        my $next_sibling;
3610                           OE: for (reverse 0..$#{$self->{open_elements}}) {        OE: for (reverse 0..$#{$self->{open_elements}}) {
3611                             if ($self->{open_elements}->[$_]->[1] eq 'table') {          if ($self->{open_elements}->[$_]->[1] & TABLE_EL) {
3612                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
3613                               if (defined $parent and $parent->node_type == 1) {                               if (defined $parent and $parent->node_type == 1) {
3614                                 !!!cp ('t70');                                 !!!cp ('t70');
# Line 3352  sub _tree_construction_main ($) { Line 3633  sub _tree_construction_main ($) {
3633      }      }
3634    }; # $insert_to_foster    }; # $insert_to_foster
3635    
3636    B: {    B: while (1) {
3637      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
3638        !!!cp ('t73');        !!!cp ('t73');
3639        !!!parse-error (type => 'DOCTYPE in the middle', token => $token);        !!!parse-error (type => 'DOCTYPE in the middle', token => $token);
3640        ## Ignore the token        ## Ignore the token
3641        ## Stay in the phase        ## Stay in the phase
3642        !!!next-token;        !!!next-token;
3643        redo B;        next B;
3644      } elsif ($token->{type} == START_TAG_TOKEN and      } elsif ($token->{type} == START_TAG_TOKEN and
3645               $token->{tag_name} eq 'html') {               $token->{tag_name} eq 'html') {
3646        if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {        if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
# Line 3385  sub _tree_construction_main ($) { Line 3666  sub _tree_construction_main ($) {
3666               $token->{attributes}->{$attr_name}->{value});               $token->{attributes}->{$attr_name}->{value});
3667          }          }
3668        }        }
3669          !!!nack ('t84.1');
3670        !!!next-token;        !!!next-token;
3671        redo B;        next B;
3672      } elsif ($token->{type} == COMMENT_TOKEN) {      } elsif ($token->{type} == COMMENT_TOKEN) {
3673        my $comment = $self->{document}->create_comment ($token->{data});        my $comment = $self->{document}->create_comment ($token->{data});
3674        if ($self->{insertion_mode} & AFTER_HTML_IMS) {        if ($self->{insertion_mode} & AFTER_HTML_IMS) {
# Line 3400  sub _tree_construction_main ($) { Line 3682  sub _tree_construction_main ($) {
3682          $self->{open_elements}->[-1]->[0]->append_child ($comment);          $self->{open_elements}->[-1]->[0]->append_child ($comment);
3683        }        }
3684        !!!next-token;        !!!next-token;
3685        redo B;        next B;
3686      } elsif ($self->{insertion_mode} & HEAD_IMS) {      } elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM) {
3687          if ($token->{type} == CHARACTER_TOKEN) {
3688            !!!cp ('t87.1');
3689            $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});
3690            !!!next-token;
3691            next B;
3692          } elsif ($token->{type} == START_TAG_TOKEN) {
3693            if ($self->{open_elements}->[-1]->[1] & FOREIGN_FLOW_CONTENT_EL or
3694                not ($self->{open_elements}->[-1]->[1] & FOREIGN_EL) or
3695                ($token->{tag_name} eq 'svg' and
3696                 $self->{open_elements}->[-1]->[1] & MML_AXML_EL)) {
3697              ## NOTE: "using the rules for secondary insertion mode"then"continue"
3698              !!!cp ('t87.2');
3699              #
3700            } elsif ({
3701      ## TODO:
3702                     }->{$token->{tag_name}}) {
3703              !!!cp ('t87.2');
3704              !!!parse-error (type => 'not closed',
3705                              value => $self->{open_elements}->[-1]->[0]
3706                                  ->manakai_local_name,
3707                              token => $token);
3708    
3709              pop @{$self->{open_elements}}
3710                  while $self->{open_elements}->[-1]->[1] & FOREIGN_EL;
3711    
3712              $self->{insertion_mode} &= ~ $self->{insertion_mode};
3713              ## Reprocess.
3714              next B;
3715            } else {
3716              ## TODO: case fixup
3717    
3718              !!!insert-element-f ($self->{open_elements}->[-1]->[0]->namespace_uri, $token);
3719    
3720              if ($self->{self_closing}) {
3721                pop @{$self->{open_elements}};
3722                !!!ack ('t87.3');
3723              } else {
3724                !!!cp ('t87.4');
3725              }
3726    
3727              !!!next-token;
3728              next B;
3729            }
3730          } elsif ($token->{type} == END_TAG_TOKEN) {
3731            ## NOTE: "using the rules for secondary insertion mode" then "continue"
3732            !!!cp ('t87.5');
3733            #
3734          } elsif ($token->{type} == END_OF_FILE_TOKEN) {
3735            ## NOTE: "using the rules for secondary insertion mode" then "continue"
3736            !!!cp ('t87.6');
3737            #
3738            ## TODO: ...
3739          } else {
3740            die "$0: $token->{type}: Unknown token type";        
3741          }
3742        }
3743    
3744        if ($self->{insertion_mode} & HEAD_IMS) {
3745        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
3746          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {
3747            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {
# Line 3411  sub _tree_construction_main ($) { Line 3751  sub _tree_construction_main ($) {
3751              !!!cp ('t88.1');              !!!cp ('t88.1');
3752              ## Ignore the token.              ## Ignore the token.
3753              !!!next-token;              !!!next-token;
3754              redo B;              next B;
3755            }            }
3756            unless (length $token->{data}) {            unless (length $token->{data}) {
3757              !!!cp ('t88');              !!!cp ('t88');
3758              !!!next-token;              !!!next-token;
3759              redo B;              next B;
3760            }            }
3761          }          }
3762    
3763          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3764            !!!cp ('t89');            !!!cp ('t89');
3765            ## As if <head>            ## As if <head>
3766            !!!create-element ($self->{head_element}, 'head',, $token);            !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
3767            $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});            $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3768            push @{$self->{open_elements}}, [$self->{head_element}, 'head'];            push @{$self->{open_elements}},
3769                  [$self->{head_element}, $el_category->{head}];
3770    
3771            ## Reprocess in the "in head" insertion mode...            ## Reprocess in the "in head" insertion mode...
3772            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
# Line 3451  sub _tree_construction_main ($) { Line 3792  sub _tree_construction_main ($) {
3792            !!!cp ('t92');            !!!cp ('t92');
3793          }          }
3794    
3795              ## "after head" insertion mode          ## "after head" insertion mode
3796              ## As if <body>          ## As if <body>
3797              !!!insert-element ('body',, $token);          !!!insert-element ('body',, $token);
3798              $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
3799              ## reprocess          ## reprocess
3800              redo B;          next B;
3801            } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
3802              if ($token->{tag_name} eq 'head') {          if ($token->{tag_name} eq 'head') {
3803                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {            if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3804                  !!!cp ('t93');              !!!cp ('t93');
3805                  !!!create-element ($self->{head_element}, $token->{tag_name}, $token->{attributes}, $token);              !!!create-element ($self->{head_element}, $HTML_NS, $token->{tag_name}, $token->{attributes}, $token);
3806                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});              $self->{open_elements}->[-1]->[0]->append_child
3807                  push @{$self->{open_elements}}, [$self->{head_element}, $token->{tag_name}];                  ($self->{head_element});
3808                  $self->{insertion_mode} = IN_HEAD_IM;              push @{$self->{open_elements}},
3809                  !!!next-token;                  [$self->{head_element}, $el_category->{head}];
3810                  redo B;              $self->{insertion_mode} = IN_HEAD_IM;
3811                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {              !!!nack ('t93.1');
3812                  !!!cp ('t94');              !!!next-token;
3813                  #              next B;
3814                } else {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
3815                  !!!cp ('t95');              !!!cp ('t94');
3816                  !!!parse-error (type => 'in head:head', token => $token); # or in head noscript              #
3817                  ## Ignore the token            } else {
3818                  !!!next-token;              !!!cp ('t95');
3819                  redo B;              !!!parse-error (type => 'in head:head', token => $token); # or in head noscript
3820                }              ## Ignore the token
3821              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {              !!!nack ('t95.1');
3822                !!!cp ('t96');              !!!next-token;
3823                ## As if <head>              next B;
3824                !!!create-element ($self->{head_element}, 'head',, $token);            }
3825                $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});          } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3826                push @{$self->{open_elements}}, [$self->{head_element}, 'head'];            !!!cp ('t96');
3827              ## As if <head>
3828              !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
3829              $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3830              push @{$self->{open_elements}},
3831                  [$self->{head_element}, $el_category->{head}];
3832    
3833                $self->{insertion_mode} = IN_HEAD_IM;            $self->{insertion_mode} = IN_HEAD_IM;
3834                ## Reprocess in the "in head" insertion mode...            ## Reprocess in the "in head" insertion mode...
3835              } else {          } else {
3836                !!!cp ('t97');            !!!cp ('t97');
3837              }          }
3838    
3839              if ($token->{tag_name} eq 'base') {              if ($token->{tag_name} eq 'base') {
3840                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
# Line 3507  sub _tree_construction_main ($) { Line 3853  sub _tree_construction_main ($) {
3853                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3854                  !!!cp ('t100');                  !!!cp ('t100');
3855                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);
3856                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}},
3857                        [$self->{head_element}, $el_category->{head}];
3858                } else {                } else {
3859                  !!!cp ('t101');                  !!!cp ('t101');
3860                }                }
# Line 3515  sub _tree_construction_main ($) { Line 3862  sub _tree_construction_main ($) {
3862                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
3863                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
3864                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
3865                  !!!nack ('t101.1');
3866                !!!next-token;                !!!next-token;
3867                redo B;                next B;
3868              } elsif ($token->{tag_name} eq 'link') {              } elsif ($token->{tag_name} eq 'link') {
3869                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3870                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3871                  !!!cp ('t102');                  !!!cp ('t102');
3872                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);
3873                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}},
3874                        [$self->{head_element}, $el_category->{head}];
3875                } else {                } else {
3876                  !!!cp ('t103');                  !!!cp ('t103');
3877                }                }
# Line 3530  sub _tree_construction_main ($) { Line 3879  sub _tree_construction_main ($) {
3879                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
3880                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
3881                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
3882                  !!!ack ('t103.1');
3883                !!!next-token;                !!!next-token;
3884                redo B;                next B;
3885              } elsif ($token->{tag_name} eq 'meta') {              } elsif ($token->{tag_name} eq 'meta') {
3886                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3887                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3888                  !!!cp ('t104');                  !!!cp ('t104');
3889                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);
3890                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}},
3891                        [$self->{head_element}, $el_category->{head}];
3892                } else {                } else {
3893                  !!!cp ('t105');                  !!!cp ('t105');
3894                }                }
# Line 3593  sub _tree_construction_main ($) { Line 3944  sub _tree_construction_main ($) {
3944    
3945                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
3946                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
3947                  !!!ack ('t110.1');
3948                !!!next-token;                !!!next-token;
3949                redo B;                next B;
3950              } elsif ($token->{tag_name} eq 'title') {              } elsif ($token->{tag_name} eq 'title') {
3951                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3952                  !!!cp ('t111');                  !!!cp ('t111');
# Line 3607  sub _tree_construction_main ($) { Line 3959  sub _tree_construction_main ($) {
3959                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
3960                  !!!cp ('t112');                  !!!cp ('t112');
3961                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);
3962                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}},
3963                        [$self->{head_element}, $el_category->{head}];
3964                } else {                } else {
3965                  !!!cp ('t113');                  !!!cp ('t113');
3966                }                }
# Line 3618  sub _tree_construction_main ($) { Line 3971  sub _tree_construction_main ($) {
3971                $parse_rcdata->(RCDATA_CONTENT_MODEL);                $parse_rcdata->(RCDATA_CONTENT_MODEL);
3972                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
3973                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
3974                redo B;                next B;
3975              } elsif ($token->{tag_name} eq 'style') {              } elsif ($token->{tag_name} eq 'style') {
3976                ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and                ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and
3977                ## insertion mode IN_HEAD_IM)                ## insertion mode IN_HEAD_IM)
# Line 3626  sub _tree_construction_main ($) { Line 3979  sub _tree_construction_main ($) {
3979                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3980                  !!!cp ('t114');                  !!!cp ('t114');
3981                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);
3982                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}},
3983                        [$self->{head_element}, $el_category->{head}];
3984                } else {                } else {
3985                  !!!cp ('t115');                  !!!cp ('t115');
3986                }                }
3987                $parse_rcdata->(CDATA_CONTENT_MODEL);                $parse_rcdata->(CDATA_CONTENT_MODEL);
3988                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
3989                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
3990                redo B;                next B;
3991              } elsif ($token->{tag_name} eq 'noscript') {              } elsif ($token->{tag_name} eq 'noscript') {
3992                if ($self->{insertion_mode} == IN_HEAD_IM) {                if ($self->{insertion_mode} == IN_HEAD_IM) {
3993                  !!!cp ('t116');                  !!!cp ('t116');
3994                  ## NOTE: and scripting is disalbed                  ## NOTE: and scripting is disalbed
3995                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
3996                  $self->{insertion_mode} = IN_HEAD_NOSCRIPT_IM;                  $self->{insertion_mode} = IN_HEAD_NOSCRIPT_IM;
3997                    !!!nack ('t116.1');
3998                  !!!next-token;                  !!!next-token;
3999                  redo B;                  next B;
4000                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4001                  !!!cp ('t117');                  !!!cp ('t117');
4002                  !!!parse-error (type => 'in noscript:noscript', token => $token);                  !!!parse-error (type => 'in noscript:noscript', token => $token);
4003                  ## Ignore the token                  ## Ignore the token
4004                    !!!nack ('t117.1');
4005                  !!!next-token;                  !!!next-token;
4006                  redo B;                  next B;
4007                } else {                } else {
4008                  !!!cp ('t118');                  !!!cp ('t118');
4009                  #                  #
# Line 3664  sub _tree_construction_main ($) { Line 4020  sub _tree_construction_main ($) {
4020                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4021                  !!!cp ('t120');                  !!!cp ('t120');
4022                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'after head:'.$token->{tag_name}, token => $token);
4023                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}},
4024                        [$self->{head_element}, $el_category->{head}];
4025                } else {                } else {
4026                  !!!cp ('t121');                  !!!cp ('t121');
4027                }                }
# Line 3673  sub _tree_construction_main ($) { Line 4030  sub _tree_construction_main ($) {
4030                $script_start_tag->();                $script_start_tag->();
4031                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
4032                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4033                redo B;                next B;
4034              } elsif ($token->{tag_name} eq 'body' or              } elsif ($token->{tag_name} eq 'body' or
4035                       $token->{tag_name} eq 'frameset') {                       $token->{tag_name} eq 'frameset') {
4036                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
# Line 3707  sub _tree_construction_main ($) { Line 4064  sub _tree_construction_main ($) {
4064                } else {                } else {
4065                  die "$0: tag name: $self->{tag_name}";                  die "$0: tag name: $self->{tag_name}";
4066                }                }
4067                  !!!nack ('t127.1');
4068                !!!next-token;                !!!next-token;
4069                redo B;                next B;
4070              } else {              } else {
4071                !!!cp ('t128');                !!!cp ('t128');
4072                #                #
# Line 3740  sub _tree_construction_main ($) { Line 4098  sub _tree_construction_main ($) {
4098              !!!insert-element ('body',, $token);              !!!insert-element ('body',, $token);
4099              $self->{insertion_mode} = IN_BODY_IM;              $self->{insertion_mode} = IN_BODY_IM;
4100              ## reprocess              ## reprocess
4101              redo B;              !!!ack-later;
4102                next B;
4103            } elsif ($token->{type} == END_TAG_TOKEN) {            } elsif ($token->{type} == END_TAG_TOKEN) {
4104              if ($token->{tag_name} eq 'head') {              if ($token->{tag_name} eq 'head') {
4105                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4106                  !!!cp ('t132');                  !!!cp ('t132');
4107                  ## As if <head>                  ## As if <head>
4108                  !!!create-element ($self->{head_element}, 'head',, $token);                  !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
4109                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
4110                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}},
4111                        [$self->{head_element}, $el_category->{head}];
4112    
4113                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
4114                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4115                  $self->{insertion_mode} = AFTER_HEAD_IM;                  $self->{insertion_mode} = AFTER_HEAD_IM;
4116                  !!!next-token;                  !!!next-token;
4117                  redo B;                  next B;
4118                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4119                  !!!cp ('t133');                  !!!cp ('t133');
4120                  ## As if </noscript>                  ## As if </noscript>
# Line 3765  sub _tree_construction_main ($) { Line 4125  sub _tree_construction_main ($) {
4125                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4126                  $self->{insertion_mode} = AFTER_HEAD_IM;                  $self->{insertion_mode} = AFTER_HEAD_IM;
4127                  !!!next-token;                  !!!next-token;
4128                  redo B;                  next B;
4129                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
4130                  !!!cp ('t134');                  !!!cp ('t134');
4131                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4132                  $self->{insertion_mode} = AFTER_HEAD_IM;                  $self->{insertion_mode} = AFTER_HEAD_IM;
4133                  !!!next-token;                  !!!next-token;
4134                  redo B;                  next B;
4135                } else {                } else {
4136                  !!!cp ('t135');                  !!!cp ('t135');
4137                  #                  #
# Line 3782  sub _tree_construction_main ($) { Line 4142  sub _tree_construction_main ($) {
4142                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4143                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
4144                  !!!next-token;                  !!!next-token;
4145                  redo B;                  next B;
4146                } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {                } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4147                  !!!cp ('t137');                  !!!cp ('t137');
4148                  !!!parse-error (type => 'unmatched end tag:noscript', token => $token);                  !!!parse-error (type => 'unmatched end tag:noscript', token => $token);
4149                  ## Ignore the token ## ISSUE: An issue in the spec.                  ## Ignore the token ## ISSUE: An issue in the spec.
4150                  !!!next-token;                  !!!next-token;
4151                  redo B;                  next B;
4152                } else {                } else {
4153                  !!!cp ('t138');                  !!!cp ('t138');
4154                  #                  #
# Line 3799  sub _tree_construction_main ($) { Line 4159  sub _tree_construction_main ($) {
4159                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4160                  !!!cp ('t139');                  !!!cp ('t139');
4161                  ## As if <head>                  ## As if <head>
4162                  !!!create-element ($self->{head_element}, 'head',, $token);                  !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
4163                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
4164                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}},
4165                        [$self->{head_element}, $el_category->{head}];
4166    
4167                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
4168                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
# Line 3810  sub _tree_construction_main ($) { Line 4171  sub _tree_construction_main ($) {
4171                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4172                  ## Ignore the token                  ## Ignore the token
4173                  !!!next-token;                  !!!next-token;
4174                  redo B;                  next B;
4175                } else {                } else {
4176                  !!!cp ('t141');                  !!!cp ('t141');
4177                }                }
# Line 3822  sub _tree_construction_main ($) { Line 4183  sub _tree_construction_main ($) {
4183                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4184                  !!!cp ('t142');                  !!!cp ('t142');
4185                  ## As if <head>                  ## As if <head>
4186                  !!!create-element ($self->{head_element}, 'head',, $token);                  !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
4187                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
4188                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}},
4189                        [$self->{head_element}, $el_category->{head}];
4190    
4191                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
4192                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
# Line 3842  sub _tree_construction_main ($) { Line 4204  sub _tree_construction_main ($) {
4204                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4205                  ## Ignore the token                  ## Ignore the token
4206                  !!!next-token;                  !!!next-token;
4207                  redo B;                  next B;
4208                }                }
4209              }              }
4210    
# Line 3869  sub _tree_construction_main ($) { Line 4231  sub _tree_construction_main ($) {
4231                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4232                ## Ignore the token ## ISSUE: An issue in the spec.                ## Ignore the token ## ISSUE: An issue in the spec.
4233                !!!next-token;                !!!next-token;
4234                redo B;                next B;
4235              } else {              } else {
4236                !!!cp ('t149');                !!!cp ('t149');
4237              }              }
# Line 3879  sub _tree_construction_main ($) { Line 4241  sub _tree_construction_main ($) {
4241              !!!insert-element ('body',, $token);              !!!insert-element ('body',, $token);
4242              $self->{insertion_mode} = IN_BODY_IM;              $self->{insertion_mode} = IN_BODY_IM;
4243              ## reprocess              ## reprocess
4244              redo B;              next B;
4245        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
4246          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4247            !!!cp ('t149.1');            !!!cp ('t149.1');
4248    
4249            ## NOTE: As if <head>            ## NOTE: As if <head>
4250            !!!create-element ($self->{head_element}, 'head',, $token);            !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
4251            $self->{open_elements}->[-1]->[0]->append_child            $self->{open_elements}->[-1]->[0]->append_child
4252                ($self->{head_element});                ($self->{head_element});
4253            #push @{$self->{open_elements}}, [$self->{head_element}, 'head'];            #push @{$self->{open_elements}},
4254              #    [$self->{head_element}, $el_category->{head}];
4255            #$self->{insertion_mode} = IN_HEAD_IM;            #$self->{insertion_mode} = IN_HEAD_IM;
4256            ## NOTE: Reprocess.            ## NOTE: Reprocess.
4257    
# Line 3932  sub _tree_construction_main ($) { Line 4295  sub _tree_construction_main ($) {
4295          !!!insert-element ('body',, $token);          !!!insert-element ('body',, $token);
4296          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
4297          ## NOTE: Reprocess.          ## NOTE: Reprocess.
4298          redo B;          next B;
4299        } else {        } else {
4300          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
4301        }        }
# Line 3947  sub _tree_construction_main ($) { Line 4310  sub _tree_construction_main ($) {
4310              $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});              $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});
4311    
4312              !!!next-token;              !!!next-token;
4313              redo B;              next B;
4314            } elsif ($token->{type} == START_TAG_TOKEN) {            } elsif ($token->{type} == START_TAG_TOKEN) {
4315              if ({              if ({
4316                   caption => 1, col => 1, colgroup => 1, tbody => 1,                   caption => 1, col => 1, colgroup => 1, tbody => 1,
# Line 3957  sub _tree_construction_main ($) { Line 4320  sub _tree_construction_main ($) {
4320                  ## have an element in table scope                  ## have an element in table scope
4321                  for (reverse 0..$#{$self->{open_elements}}) {                  for (reverse 0..$#{$self->{open_elements}}) {
4322                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
4323                    if ($node->[1] eq 'td' or $node->[1] eq 'th') {                    if ($node->[1] & TABLE_CELL_EL) {
4324                      !!!cp ('t151');                      !!!cp ('t151');
4325    
4326                      ## Close the cell                      ## Close the cell
4327                      !!!back-token; # <?>                      !!!back-token; # <x>
4328                      $token = {type => END_TAG_TOKEN, tag_name => $node->[1],                      $token = {type => END_TAG_TOKEN,
4329                                  tag_name => $node->[0]->manakai_local_name,
4330                                line => $token->{line},                                line => $token->{line},
4331                                column => $token->{column}};                                column => $token->{column}};
4332                      redo B;                      next B;
4333                    } elsif ({                    } elsif ($node->[1] & TABLE_SCOPING_EL) {
                             table => 1, html => 1,  
                            }->{$node->[1]}) {  
4334                      !!!cp ('t152');                      !!!cp ('t152');
4335                      ## ISSUE: This case can never be reached, maybe.                      ## ISSUE: This case can never be reached, maybe.
4336                      last;                      last;
# Line 3979  sub _tree_construction_main ($) { Line 4341  sub _tree_construction_main ($) {
4341                  !!!parse-error (type => 'start tag not allowed',                  !!!parse-error (type => 'start tag not allowed',
4342                      value => $token->{tag_name}, token => $token);                      value => $token->{tag_name}, token => $token);
4343                  ## Ignore the token                  ## Ignore the token
4344                    !!!nack ('t153.1');
4345                  !!!next-token;                  !!!next-token;
4346                  redo B;                  next B;
4347                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {
4348                  !!!parse-error (type => 'not closed:caption', token => $token);                  !!!parse-error (type => 'not closed:caption', token => $token);
4349                                    
# Line 3990  sub _tree_construction_main ($) { Line 4353  sub _tree_construction_main ($) {
4353                  INSCOPE: {                  INSCOPE: {
4354                    for (reverse 0..$#{$self->{open_elements}}) {                    for (reverse 0..$#{$self->{open_elements}}) {
4355                      my $node = $self->{open_elements}->[$_];                      my $node = $self->{open_elements}->[$_];
4356                      if ($node->[1] eq 'caption') {                      if ($node->[1] & CAPTION_EL) {
4357                        !!!cp ('t155');                        !!!cp ('t155');
4358                        $i = $_;                        $i = $_;
4359                        last INSCOPE;                        last INSCOPE;
4360                      } elsif ({                      } elsif ($node->[1] & TABLE_SCOPING_EL) {
                               table => 1, html => 1,  
                              }->{$node->[1]}) {  
4361                        !!!cp ('t156');                        !!!cp ('t156');
4362                        last;                        last;
4363                      }                      }
# Line 4006  sub _tree_construction_main ($) { Line 4367  sub _tree_construction_main ($) {
4367                    !!!parse-error (type => 'start tag not allowed',                    !!!parse-error (type => 'start tag not allowed',
4368                                    value => $token->{tag_name}, token => $token);                                    value => $token->{tag_name}, token => $token);
4369                    ## Ignore the token                    ## Ignore the token
4370                      !!!nack ('t157.1');
4371                    !!!next-token;                    !!!next-token;
4372                    redo B;                    next B;
4373                  } # INSCOPE                  } # INSCOPE
4374                                    
4375                  ## generate implied end tags                  ## generate implied end tags
4376                  while ({                  while ($self->{open_elements}->[-1]->[1]
4377                          dd => 1, dt => 1, li => 1, p => 1,                             & END_TAG_OPTIONAL_EL) {
                        }->{$self->{open_elements}->[-1]->[1]}) {  
4378                    !!!cp ('t158');                    !!!cp ('t158');
4379                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4380                  }                  }
4381    
4382                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {                  unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {
4383                    !!!cp ('t159');                    !!!cp ('t159');
4384                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                    !!!parse-error (type => 'not closed',
4385                                      value => $self->{open_elements}->[-1]->[0]
4386                                          ->manakai_local_name,
4387                                      token => $token);
4388                  } else {                  } else {
4389                    !!!cp ('t160');                    !!!cp ('t160');
4390                  }                  }
# Line 4032  sub _tree_construction_main ($) { Line 4396  sub _tree_construction_main ($) {
4396                  $self->{insertion_mode} = IN_TABLE_IM;                  $self->{insertion_mode} = IN_TABLE_IM;
4397                                    
4398                  ## reprocess                  ## reprocess
4399                  redo B;                  !!!ack-later;
4400                    next B;
4401                } else {                } else {
4402                  !!!cp ('t161');                  !!!cp ('t161');
4403                  #                  #
# Line 4048  sub _tree_construction_main ($) { Line 4413  sub _tree_construction_main ($) {
4413                  my $i;                  my $i;
4414                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4415                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
4416                    if ($node->[1] eq $token->{tag_name}) {                    if ($node->[0]->manakai_local_name eq $token->{tag_name}) {
4417                      !!!cp ('t163');                      !!!cp ('t163');
4418                      $i = $_;                      $i = $_;
4419                      last INSCOPE;                      last INSCOPE;
4420                    } elsif ({                    } elsif ($node->[1] & TABLE_SCOPING_EL) {
                             table => 1, html => 1,  
                            }->{$node->[1]}) {  
4421                      !!!cp ('t164');                      !!!cp ('t164');
4422                      last INSCOPE;                      last INSCOPE;
4423                    }                    }
# Line 4064  sub _tree_construction_main ($) { Line 4427  sub _tree_construction_main ($) {
4427                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4428                      ## Ignore the token                      ## Ignore the token
4429                      !!!next-token;                      !!!next-token;
4430                      redo B;                      next B;
4431                    }                    }
4432                                    
4433                  ## generate implied end tags                  ## generate implied end tags
4434                  while ({                  while ($self->{open_elements}->[-1]->[1]
4435                          dd => 1, dt => 1, li => 1, p => 1,                             & END_TAG_OPTIONAL_EL) {
                        }->{$self->{open_elements}->[-1]->[1]}) {  
4436                    !!!cp ('t166');                    !!!cp ('t166');
4437                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4438                  }                  }
4439    
4440                  if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {                  if ($self->{open_elements}->[-1]->[0]->manakai_local_name
4441                            ne $token->{tag_name}) {
4442                    !!!cp ('t167');                    !!!cp ('t167');
4443                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                    !!!parse-error (type => 'not closed',
4444                                      value => $self->{open_elements}->[-1]->[0]
4445                                          ->manakai_local_name,
4446                                      token => $token);
4447                  } else {                  } else {
4448                    !!!cp ('t168');                    !!!cp ('t168');
4449                  }                  }
# Line 4089  sub _tree_construction_main ($) { Line 4455  sub _tree_construction_main ($) {
4455                  $self->{insertion_mode} = IN_ROW_IM;                  $self->{insertion_mode} = IN_ROW_IM;
4456                                    
4457                  !!!next-token;                  !!!next-token;
4458                  redo B;                  next B;
4459                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {
4460                  !!!cp ('t169');                  !!!cp ('t169');
4461                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4462                  ## Ignore the token                  ## Ignore the token
4463                  !!!next-token;                  !!!next-token;
4464                  redo B;                  next B;
4465                } else {                } else {
4466                  !!!cp ('t170');                  !!!cp ('t170');
4467                  #                  #
# Line 4107  sub _tree_construction_main ($) { Line 4473  sub _tree_construction_main ($) {
4473                  INSCOPE: {                  INSCOPE: {
4474                    for (reverse 0..$#{$self->{open_elements}}) {                    for (reverse 0..$#{$self->{open_elements}}) {
4475                      my $node = $self->{open_elements}->[$_];                      my $node = $self->{open_elements}->[$_];
4476                      if ($node->[1] eq $token->{tag_name}) {                      if ($node->[1] & CAPTION_EL) {
4477                        !!!cp ('t171');                        !!!cp ('t171');
4478                        $i = $_;                        $i = $_;
4479                        last INSCOPE;                        last INSCOPE;
4480                      } elsif ({                      } elsif ($node->[1] & TABLE_SCOPING_EL) {
                               table => 1, html => 1,  
                              }->{$node->[1]}) {  
4481                        !!!cp ('t172');                        !!!cp ('t172');
4482                        last;                        last;
4483                      }                      }
# Line 4124  sub _tree_construction_main ($) { Line 4488  sub _tree_construction_main ($) {
4488                                    value => $token->{tag_name}, token => $token);                                    value => $token->{tag_name}, token => $token);
4489                    ## Ignore the token                    ## Ignore the token
4490                    !!!next-token;                    !!!next-token;
4491                    redo B;                    next B;
4492                  } # INSCOPE                  } # INSCOPE
4493                                    
4494                  ## generate implied end tags                  ## generate implied end tags
4495                  while ({                  while ($self->{open_elements}->[-1]->[1]
4496                          dd => 1, dt => 1, li => 1, p => 1,                             & END_TAG_OPTIONAL_EL) {
                        }->{$self->{open_elements}->[-1]->[1]}) {  
4497                    !!!cp ('t174');                    !!!cp ('t174');
4498                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4499                  }                  }
4500                                    
4501                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {                  unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {
4502                    !!!cp ('t175');                    !!!cp ('t175');
4503                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                    !!!parse-error (type => 'not closed',
4504                                      value => $self->{open_elements}->[-1]->[0]
4505                                          ->manakai_local_name,
4506                                      token => $token);
4507                  } else {                  } else {
4508                    !!!cp ('t176');                    !!!cp ('t176');
4509                  }                  }
# Line 4149  sub _tree_construction_main ($) { Line 4515  sub _tree_construction_main ($) {
4515                  $self->{insertion_mode} = IN_TABLE_IM;                  $self->{insertion_mode} = IN_TABLE_IM;
4516                                    
4517                  !!!next-token;                  !!!next-token;
4518                  redo B;                  next B;
4519                } elsif ($self->{insertion_mode} == IN_CELL_IM) {                } elsif ($self->{insertion_mode} == IN_CELL_IM) {
4520                  !!!cp ('t177');                  !!!cp ('t177');
4521                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4522                  ## Ignore the token                  ## Ignore the token
4523                  !!!next-token;                  !!!next-token;
4524                  redo B;                  next B;
4525                } else {                } else {
4526                  !!!cp ('t178');                  !!!cp ('t178');
4527                  #                  #
# Line 4171  sub _tree_construction_main ($) { Line 4537  sub _tree_construction_main ($) {
4537                INSCOPE: {                INSCOPE: {
4538                  for (reverse 0..$#{$self->{open_elements}}) {                  for (reverse 0..$#{$self->{open_elements}}) {
4539                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
4540                    if ($node->[1] eq $token->{tag_name}) {                    if ($node->[0]->manakai_local_name eq $token->{tag_name}) {
4541                      !!!cp ('t179');                      !!!cp ('t179');
4542                      $i = $_;                      $i = $_;
4543    
4544                      ## Close the cell                      ## Close the cell
4545                      !!!back-token; # </?>                      !!!back-token; # </x>
4546                      $token = {type => END_TAG_TOKEN, tag_name => $tn,                      $token = {type => END_TAG_TOKEN, tag_name => $tn,
4547                                line => $token->{line},                                line => $token->{line},
4548                                column => $token->{column}};                                column => $token->{column}};
4549                      redo B;                      next B;
4550                    } elsif ($node->[1] eq 'td' or $node->[1] eq 'th') {                    } elsif ($node->[1] & TABLE_CELL_EL) {
4551                      !!!cp ('t180');                      !!!cp ('t180');
4552                      $tn = $node->[1];                      $tn = $node->[0]->manakai_local_name;
4553                      ## NOTE: There is exactly one |td| or |th| element                      ## NOTE: There is exactly one |td| or |th| element
4554                      ## in scope in the stack of open elements by definition.                      ## in scope in the stack of open elements by definition.
4555                    } elsif ({                    } elsif ($node->[1] & TABLE_SCOPING_EL) {
                             table => 1, html => 1,  
                            }->{$node->[1]}) {  
4556                      ## ISSUE: Can this be reached?                      ## ISSUE: Can this be reached?
4557                      !!!cp ('t181');                      !!!cp ('t181');
4558                      last;                      last;
# Line 4200  sub _tree_construction_main ($) { Line 4564  sub _tree_construction_main ($) {
4564                      value => $token->{tag_name}, token => $token);                      value => $token->{tag_name}, token => $token);
4565                  ## Ignore the token                  ## Ignore the token
4566                  !!!next-token;                  !!!next-token;
4567                  redo B;                  next B;
4568                } # INSCOPE                } # INSCOPE
4569              } elsif ($token->{tag_name} eq 'table' and              } elsif ($token->{tag_name} eq 'table' and
4570                       $self->{insertion_mode} == IN_CAPTION_IM) {                       $self->{insertion_mode} == IN_CAPTION_IM) {
# Line 4211  sub _tree_construction_main ($) { Line 4575  sub _tree_construction_main ($) {
4575                my $i;                my $i;
4576                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4577                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4578                  if ($node->[1] eq 'caption') {                  if ($node->[1] & CAPTION_EL) {
4579                    !!!cp ('t184');                    !!!cp ('t184');
4580                    $i = $_;                    $i = $_;
4581                    last INSCOPE;                    last INSCOPE;
4582                  } elsif ({                  } elsif ($node->[1] & TABLE_SCOPING_EL) {
                           table => 1, html => 1,  
                          }->{$node->[1]}) {  
4583                    !!!cp ('t185');                    !!!cp ('t185');
4584                    last INSCOPE;                    last INSCOPE;
4585                  }                  }
# Line 4227  sub _tree_construction_main ($) { Line 4589  sub _tree_construction_main ($) {
4589                  !!!parse-error (type => 'unmatched end tag:caption', token => $token);                  !!!parse-error (type => 'unmatched end tag:caption', token => $token);
4590                  ## Ignore the token                  ## Ignore the token
4591                  !!!next-token;                  !!!next-token;
4592                  redo B;                  next B;
4593                }                }
4594                                
4595                ## generate implied end tags                ## generate implied end tags
4596                while ({                while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
                       dd => 1, dt => 1, li => 1, p => 1,  
                      }->{$self->{open_elements}->[-1]->[1]}) {  
4597                  !!!cp ('t187');                  !!!cp ('t187');
4598                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4599                }                }
4600    
4601                if ($self->{open_elements}->[-1]->[1] ne 'caption') {                unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {
4602                  !!!cp ('t188');                  !!!cp ('t188');
4603                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                  !!!parse-error (type => 'not closed',
4604                                    value => $self->{open_elements}->[-1]->[0]
4605                                        ->manakai_local_name,
4606                                    token => $token);
4607                } else {                } else {
4608                  !!!cp ('t189');                  !!!cp ('t189');
4609                }                }
# Line 4252  sub _tree_construction_main ($) { Line 4615  sub _tree_construction_main ($) {
4615                $self->{insertion_mode} = IN_TABLE_IM;                $self->{insertion_mode} = IN_TABLE_IM;
4616    
4617                ## reprocess                ## reprocess
4618                redo B;                next B;
4619              } elsif ({              } elsif ({
4620                        body => 1, col => 1, colgroup => 1, html => 1,                        body => 1, col => 1, colgroup => 1, html => 1,
4621                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
# Line 4261  sub _tree_construction_main ($) { Line 4624  sub _tree_construction_main ($) {
4624                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4625                  ## Ignore the token                  ## Ignore the token
4626                  !!!next-token;                  !!!next-token;
4627                  redo B;                  next B;
4628                } else {                } else {
4629                  !!!cp ('t191');                  !!!cp ('t191');
4630                  #                  #
# Line 4275  sub _tree_construction_main ($) { Line 4638  sub _tree_construction_main ($) {
4638                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4639                ## Ignore the token                ## Ignore the token
4640                !!!next-token;                !!!next-token;
4641                redo B;                next B;
4642              } else {              } else {
4643                !!!cp ('t193');                !!!cp ('t193');
4644                #                #
4645              }              }
4646        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
4647          for my $entry (@{$self->{open_elements}}) {          for my $entry (@{$self->{open_elements}}) {
4648            if (not {            unless ($entry->[1] & ALL_END_TAG_OPTIONAL_EL) {
             dd => 1, dt => 1, li => 1, p => 1, tbody => 1, td => 1, tfoot => 1,  
             th => 1, thead => 1, tr => 1, body => 1, html => 1,  
           }->{$entry->[1]}) {  
4649              !!!cp ('t75');              !!!cp ('t75');
4650              !!!parse-error (type => 'in body:#eof', token => $token);              !!!parse-error (type => 'in body:#eof', token => $token);
4651              last;              last;
# Line 4309  sub _tree_construction_main ($) { Line 4669  sub _tree_construction_main ($) {
4669            unless (length $token->{data}) {            unless (length $token->{data}) {
4670              !!!cp ('t194');              !!!cp ('t194');
4671              !!!next-token;              !!!next-token;
4672              redo B;              next B;
4673            } else {            } else {
4674              !!!cp ('t195');              !!!cp ('t195');
4675            }            }
# Line 4323  sub _tree_construction_main ($) { Line 4683  sub _tree_construction_main ($) {
4683              ## result in a new Text node.              ## result in a new Text node.
4684              $reconstruct_active_formatting_elements->($insert_to_foster);              $reconstruct_active_formatting_elements->($insert_to_foster);
4685                            
4686              if ({              if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {
                  table => 1, tbody => 1, tfoot => 1,  
                  thead => 1, tr => 1,  
                 }->{$self->{open_elements}->[-1]->[1]}) {  
4687                # MUST                # MUST
4688                my $foster_parent_element;                my $foster_parent_element;
4689                my $next_sibling;                my $next_sibling;
4690                my $prev_sibling;                my $prev_sibling;
4691                OE: for (reverse 0..$#{$self->{open_elements}}) {                OE: for (reverse 0..$#{$self->{open_elements}}) {
4692                  if ($self->{open_elements}->[$_]->[1] eq 'table') {                  if ($self->{open_elements}->[$_]->[1] & TABLE_EL) {
4693                    my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                    my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
4694                    if (defined $parent and $parent->node_type == 1) {                    if (defined $parent and $parent->node_type == 1) {
4695                      !!!cp ('t196');                      !!!cp ('t196');
# Line 4367  sub _tree_construction_main ($) { Line 4724  sub _tree_construction_main ($) {
4724          }          }
4725                            
4726          !!!next-token;          !!!next-token;
4727          redo B;          next B;
4728        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
4729              if ({              if ({
4730                   tr => ($self->{insertion_mode} != IN_ROW_IM),                   tr => ($self->{insertion_mode} != IN_ROW_IM),
# Line 4375  sub _tree_construction_main ($) { Line 4732  sub _tree_construction_main ($) {
4732                  }->{$token->{tag_name}}) {                  }->{$token->{tag_name}}) {
4733                if ($self->{insertion_mode} == IN_TABLE_IM) {                if ($self->{insertion_mode} == IN_TABLE_IM) {
4734                  ## Clear back to table context                  ## Clear back to table context
4735                  while ($self->{open_elements}->[-1]->[1] ne 'table' and                  while (not ($self->{open_elements}->[-1]->[1]
4736                         $self->{open_elements}->[-1]->[1] ne 'html') {                                  & TABLE_SCOPING_EL)) {
4737                    !!!cp ('t201');                    !!!cp ('t201');
4738                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4739                  }                  }
# Line 4393  sub _tree_construction_main ($) { Line 4750  sub _tree_construction_main ($) {
4750                  }                  }
4751                                    
4752                  ## Clear back to table body context                  ## Clear back to table body context
4753                  while (not {                  while (not ($self->{open_elements}->[-1]->[1]
4754                    tbody => 1, tfoot => 1, thead => 1, html => 1,                                  & TABLE_ROWS_SCOPING_EL)) {
                 }->{$self->{open_elements}->[-1]->[1]}) {  
4755                    !!!cp ('t203');                    !!!cp ('t203');
4756                    ## ISSUE: Can this case be reached?                    ## ISSUE: Can this case be reached?
4757                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
# Line 4405  sub _tree_construction_main ($) { Line 4761  sub _tree_construction_main ($) {
4761                  if ($token->{tag_name} eq 'tr') {                  if ($token->{tag_name} eq 'tr') {
4762                    !!!cp ('t204');                    !!!cp ('t204');
4763                    !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                    !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4764                      !!!nack ('t204');
4765                    !!!next-token;                    !!!next-token;
4766                    redo B;                    next B;
4767                  } else {                  } else {
4768                    !!!cp ('t205');                    !!!cp ('t205');
4769                    !!!insert-element ('tr',, $token);                    !!!insert-element ('tr',, $token);
# Line 4417  sub _tree_construction_main ($) { Line 4774  sub _tree_construction_main ($) {
4774                }                }
4775    
4776                ## Clear back to table row context                ## Clear back to table row context
4777                while (not {                while (not ($self->{open_elements}->[-1]->[1]
4778                  tr => 1, html => 1,                                & TABLE_ROW_SCOPING_EL)) {
               }->{$self->{open_elements}->[-1]->[1]}) {  
4779                  !!!cp ('t207');                  !!!cp ('t207');
4780                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4781                }                }
# Line 4429  sub _tree_construction_main ($) { Line 4785  sub _tree_construction_main ($) {
4785    
4786                push @$active_formatting_elements, ['#marker', ''];                push @$active_formatting_elements, ['#marker', ''];
4787                                
4788                  !!!nack ('t207.1');
4789                !!!next-token;                !!!next-token;
4790                redo B;                next B;
4791              } elsif ({              } elsif ({
4792                        caption => 1, col => 1, colgroup => 1,                        caption => 1, col => 1, colgroup => 1,
4793                        tbody => 1, tfoot => 1, thead => 1,                        tbody => 1, tfoot => 1, thead => 1,
# Line 4442  sub _tree_construction_main ($) { Line 4799  sub _tree_construction_main ($) {
4799                  my $i;                  my $i;
4800                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4801                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
4802                    if ($node->[1] eq 'tr') {                    if ($node->[1] & TABLE_ROW_EL) {
4803                      !!!cp ('t208');                      !!!cp ('t208');
4804                      $i = $_;                      $i = $_;
4805                      last INSCOPE;                      last INSCOPE;
4806                    } elsif ({                    } elsif ($node->[1] & TABLE_SCOPING_EL) {
                             html => 1,  
   
                             ## NOTE: This element does not appear here, maybe.  
                             table => 1,  
                            }->{$node->[1]}) {  
4807                      !!!cp ('t209');                      !!!cp ('t209');
4808                      last INSCOPE;                      last INSCOPE;
4809                    }                    }
4810                  } # INSCOPE                  } # INSCOPE
4811                  unless (defined $i) {                  unless (defined $i) {
4812                   !!!cp ('t210');                    !!!cp ('t210');
4813  ## TODO: This type is wrong.  ## TODO: This type is wrong.
4814                   !!!parse-error (type => 'unmacthed end tag:'.$token->{tag_name}, token => $token);                    !!!parse-error (type => 'unmacthed end tag:'.$token->{tag_name}, token => $token);
4815                    ## Ignore the token                    ## Ignore the token
4816                      !!!nack ('t210.1');
4817                    !!!next-token;                    !!!next-token;
4818                    redo B;                    next B;
4819                  }                  }
4820                                    
4821                  ## Clear back to table row context                  ## Clear back to table row context
4822                  while (not {                  while (not ($self->{open_elements}->[-1]->[1]
4823                    tr => 1, html => 1,                                  & TABLE_ROW_SCOPING_EL)) {
                 }->{$self->{open_elements}->[-1]->[1]}) {  
4824                    !!!cp ('t211');                    !!!cp ('t211');
4825                    ## ISSUE: Can this case be reached?                    ## ISSUE: Can this case be reached?
4826                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
# Line 4479  sub _tree_construction_main ($) { Line 4831  sub _tree_construction_main ($) {
4831                  if ($token->{tag_name} eq 'tr') {                  if ($token->{tag_name} eq 'tr') {
4832                    !!!cp ('t212');                    !!!cp ('t212');
4833                    ## reprocess                    ## reprocess
4834                    redo B;                    !!!ack-later;
4835                      next B;
4836                  } else {                  } else {
4837                    !!!cp ('t213');                    !!!cp ('t213');
4838                    ## reprocess in the "in table body" insertion mode...                    ## reprocess in the "in table body" insertion mode...
# Line 4491  sub _tree_construction_main ($) { Line 4844  sub _tree_construction_main ($) {
4844                  my $i;                  my $i;
4845                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4846                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
4847                    if ({                    if ($node->[1] & TABLE_ROW_GROUP_EL) {
                        tbody => 1, thead => 1, tfoot => 1,  
                       }->{$node->[1]}) {  
4848                      !!!cp ('t214');                      !!!cp ('t214');
4849                      $i = $_;                      $i = $_;
4850                      last INSCOPE;                      last INSCOPE;
4851                    } elsif ({                    } elsif ($node->[1] & TABLE_SCOPING_EL) {
                             table => 1, html => 1,  
                            }->{$node->[1]}) {  
4852                      !!!cp ('t215');                      !!!cp ('t215');
4853                      last INSCOPE;                      last INSCOPE;
4854                    }                    }
# Line 4509  sub _tree_construction_main ($) { Line 4858  sub _tree_construction_main ($) {
4858  ## TODO: This erorr type ios wrong.  ## TODO: This erorr type ios wrong.
4859                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4860                    ## Ignore the token                    ## Ignore the token
4861                      !!!nack ('t216.1');
4862                    !!!next-token;                    !!!next-token;
4863                    redo B;                    next B;
4864                  }                  }
4865    
4866                  ## Clear back to table body context                  ## Clear back to table body context
4867                  while (not {                  while (not ($self->{open_elements}->[-1]->[1]
4868                    tbody => 1, tfoot => 1, thead => 1, html => 1,                                  & TABLE_ROWS_SCOPING_EL)) {
                 }->{$self->{open_elements}->[-1]->[1]}) {  
4869                    !!!cp ('t217');                    !!!cp ('t217');
4870                    ## ISSUE: Can this state be reached?                    ## ISSUE: Can this state be reached?
4871                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
# Line 4538  sub _tree_construction_main ($) { Line 4887  sub _tree_construction_main ($) {
4887    
4888                if ($token->{tag_name} eq 'col') {                if ($token->{tag_name} eq 'col') {
4889                  ## Clear back to table context                  ## Clear back to table context
4890                  while ($self->{open_elements}->[-1]->[1] ne 'table' and                  while (not ($self->{open_elements}->[-1]->[1]
4891                         $self->{open_elements}->[-1]->[1] ne 'html') {                                  & TABLE_SCOPING_EL)) {
4892                    !!!cp ('t219');                    !!!cp ('t219');
4893                    ## ISSUE: Can this state be reached?                    ## ISSUE: Can this state be reached?
4894                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
# Line 4548  sub _tree_construction_main ($) { Line 4897  sub _tree_construction_main ($) {
4897                  !!!insert-element ('colgroup',, $token);                  !!!insert-element ('colgroup',, $token);
4898                  $self->{insertion_mode} = IN_COLUMN_GROUP_IM;                  $self->{insertion_mode} = IN_COLUMN_GROUP_IM;
4899                  ## reprocess                  ## reprocess
4900                  redo B;                  !!!ack-later;
4901                    next B;
4902                } elsif ({                } elsif ({
4903                          caption => 1,                          caption => 1,
4904                          colgroup => 1,                          colgroup => 1,
4905                          tbody => 1, tfoot => 1, thead => 1,                          tbody => 1, tfoot => 1, thead => 1,
4906                         }->{$token->{tag_name}}) {                         }->{$token->{tag_name}}) {
4907                  ## Clear back to table context                  ## Clear back to table context
4908                  while ($self->{open_elements}->[-1]->[1] ne 'table' and                  while (not ($self->{open_elements}->[-1]->[1]
4909                         $self->{open_elements}->[-1]->[1] ne 'html') {                                  & TABLE_SCOPING_EL)) {
4910                    !!!cp ('t220');                    !!!cp ('t220');
4911                    ## ISSUE: Can this state be reached?                    ## ISSUE: Can this state be reached?
4912                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
# Line 4574  sub _tree_construction_main ($) { Line 4924  sub _tree_construction_main ($) {
4924                                             thead => IN_TABLE_BODY_IM,                                             thead => IN_TABLE_BODY_IM,
4925                                            }->{$token->{tag_name}};                                            }->{$token->{tag_name}};
4926                  !!!next-token;                  !!!next-token;
4927                  redo B;                  !!!nack ('t220.1');
4928                    next B;
4929                } else {                } else {
4930                  die "$0: in table: <>: $token->{tag_name}";                  die "$0: in table: <>: $token->{tag_name}";
4931                }                }
4932              } elsif ($token->{tag_name} eq 'table') {              } elsif ($token->{tag_name} eq 'table') {
4933                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                !!!parse-error (type => 'not closed',
4934                                  value => $self->{open_elements}->[-1]->[0]
4935                                      ->manakai_local_name,
4936                                  token => $token);
4937    
4938                ## As if </table>                ## As if </table>
4939                ## have a table element in table scope                ## have a table element in table scope
4940                my $i;                my $i;
4941                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4942                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4943                  if ($node->[1] eq 'table') {                  if ($node->[1] & TABLE_EL) {
4944                    !!!cp ('t221');                    !!!cp ('t221');
4945                    $i = $_;                    $i = $_;
4946                    last INSCOPE;                    last INSCOPE;
4947                  } elsif ({                  } elsif ($node->[1] & TABLE_SCOPING_EL) {
                           #table => 1,  
                           html => 1,  
                          }->{$node->[1]}) {  
4948                    !!!cp ('t222');                    !!!cp ('t222');
4949                    last INSCOPE;                    last INSCOPE;
4950                  }                  }
# Line 4603  sub _tree_construction_main ($) { Line 4954  sub _tree_construction_main ($) {
4954  ## TODO: The following is wrong, maybe.  ## TODO: The following is wrong, maybe.
4955                  !!!parse-error (type => 'unmatched end tag:table', token => $token);                  !!!parse-error (type => 'unmatched end tag:table', token => $token);
4956                  ## Ignore tokens </table><table>                  ## Ignore tokens </table><table>
4957                    !!!nack ('t223.1');
4958                  !!!next-token;                  !!!next-token;
4959                  redo B;                  next B;
4960                }                }
4961                                
4962  ## TODO: Followings are removed from the latest spec.  ## TODO: Followings are removed from the latest spec.
4963                ## generate implied end tags                ## generate implied end tags
4964                while ({                while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
                       dd => 1, dt => 1, li => 1, p => 1,  
                      }->{$self->{open_elements}->[-1]->[1]}) {  
4965                  !!!cp ('t224');                  !!!cp ('t224');
4966                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4967                }                }
4968    
4969                if ($self->{open_elements}->[-1]->[1] ne 'table') {                unless ($self->{open_elements}->[-1]->[1] & TABLE_EL) {
4970                  !!!cp ('t225');                  !!!cp ('t225');
4971  ## ISSUE: Can this case be reached?                  ## NOTE: |<table><tr><table>|
4972                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                  !!!parse-error (type => 'not closed',
4973                                    value => $self->{open_elements}->[-1]->[0]
4974                                        ->manakai_local_name,
4975                                    token => $token);
4976                } else {                } else {
4977                  !!!cp ('t226');                  !!!cp ('t226');
4978                }                }
# Line 4629  sub _tree_construction_main ($) { Line 4982  sub _tree_construction_main ($) {
4982    
4983                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
4984    
4985                ## reprocess            ## reprocess
4986                redo B;            !!!ack-later;
4987              next B;
4988          } elsif ($token->{tag_name} eq 'style') {          } elsif ($token->{tag_name} eq 'style') {
4989            if (not $open_tables->[-1]->[1]) { # tainted            if (not $open_tables->[-1]->[1]) { # tainted
4990              !!!cp ('t227.8');              !!!cp ('t227.8');
4991              ## NOTE: This is a "as if in head" code clone.              ## NOTE: This is a "as if in head" code clone.
4992              $parse_rcdata->(CDATA_CONTENT_MODEL);              $parse_rcdata->(CDATA_CONTENT_MODEL);
4993              redo B;              next B;
4994            } else {            } else {
4995              !!!cp ('t227.7');              !!!cp ('t227.7');
4996              #              #
# Line 4646  sub _tree_construction_main ($) { Line 5000  sub _tree_construction_main ($) {
5000              !!!cp ('t227.6');              !!!cp ('t227.6');
5001              ## NOTE: This is a "as if in head" code clone.              ## NOTE: This is a "as if in head" code clone.
5002              $script_start_tag->();              $script_start_tag->();
5003              redo B;              next B;
5004            } else {            } else {
5005              !!!cp ('t227.5');              !!!cp ('t227.5');
5006              #              #
# Line 4666  sub _tree_construction_main ($) { Line 5020  sub _tree_construction_main ($) {
5020                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
5021    
5022                  !!!next-token;                  !!!next-token;
5023                  redo B;                  !!!ack ('t227.2.1');
5024                    next B;
5025                } else {                } else {
5026                  !!!cp ('t227.2');                  !!!cp ('t227.2');
5027                  #                  #
# Line 4695  sub _tree_construction_main ($) { Line 5050  sub _tree_construction_main ($) {
5050                my $i;                my $i;
5051                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5052                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
5053                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] & TABLE_ROW_EL) {
5054                    !!!cp ('t228');                    !!!cp ('t228');
5055                    $i = $_;                    $i = $_;
5056                    last INSCOPE;                    last INSCOPE;
5057                  } elsif ({                  } elsif ($node->[1] & TABLE_SCOPING_EL) {
                           table => 1, html => 1,  
                          }->{$node->[1]}) {  
5058                    !!!cp ('t229');                    !!!cp ('t229');
5059                    last INSCOPE;                    last INSCOPE;
5060                  }                  }
# Line 4710  sub _tree_construction_main ($) { Line 5063  sub _tree_construction_main ($) {
5063                  !!!cp ('t230');                  !!!cp ('t230');
5064                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5065                  ## Ignore the token                  ## Ignore the token
5066                    !!!nack ('t230.1');
5067                  !!!next-token;                  !!!next-token;
5068                  redo B;                  next B;
5069                } else {                } else {
5070                  !!!cp ('t232');                  !!!cp ('t232');
5071                }                }
5072    
5073                ## Clear back to table row context                ## Clear back to table row context
5074                while (not {                while (not ($self->{open_elements}->[-1]->[1]
5075                  tr => 1, html => 1,                                & TABLE_ROW_SCOPING_EL)) {
               }->{$self->{open_elements}->[-1]->[1]}) {  
5076                  !!!cp ('t231');                  !!!cp ('t231');
5077  ## ISSUE: Can this state be reached?  ## ISSUE: Can this state be reached?
5078                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
# Line 4728  sub _tree_construction_main ($) { Line 5081  sub _tree_construction_main ($) {
5081                pop @{$self->{open_elements}}; # tr                pop @{$self->{open_elements}}; # tr
5082                $self->{insertion_mode} = IN_TABLE_BODY_IM;                $self->{insertion_mode} = IN_TABLE_BODY_IM;
5083                !!!next-token;                !!!next-token;
5084                redo B;                !!!nack ('t231.1');
5085                  next B;
5086              } elsif ($token->{tag_name} eq 'table') {              } elsif ($token->{tag_name} eq 'table') {
5087                if ($self->{insertion_mode} == IN_ROW_IM) {                if ($self->{insertion_mode} == IN_ROW_IM) {
5088                  ## As if </tr>                  ## As if </tr>
# Line 4736  sub _tree_construction_main ($) { Line 5090  sub _tree_construction_main ($) {
5090                  my $i;                  my $i;
5091                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5092                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
5093                    if ($node->[1] eq 'tr') {                    if ($node->[1] & TABLE_ROW_EL) {
5094                      !!!cp ('t233');                      !!!cp ('t233');
5095                      $i = $_;                      $i = $_;
5096                      last INSCOPE;                      last INSCOPE;
5097                    } elsif ({                    } elsif ($node->[1] & TABLE_SCOPING_EL) {
                             table => 1, html => 1,  
                            }->{$node->[1]}) {  
5098                      !!!cp ('t234');                      !!!cp ('t234');
5099                      last INSCOPE;                      last INSCOPE;
5100                    }                    }
# Line 4752  sub _tree_construction_main ($) { Line 5104  sub _tree_construction_main ($) {
5104  ## TODO: The following is wrong.  ## TODO: The following is wrong.
5105                    !!!parse-error (type => 'unmatched end tag:'.$token->{type}, token => $token);                    !!!parse-error (type => 'unmatched end tag:'.$token->{type}, token => $token);
5106                    ## Ignore the token                    ## Ignore the token
5107                      !!!nack ('t236.1');
5108                    !!!next-token;                    !!!next-token;
5109                    redo B;                    next B;
5110                  }                  }
5111                                    
5112                  ## Clear back to table row context                  ## Clear back to table row context
5113                  while (not {                  while (not ($self->{open_elements}->[-1]->[1]
5114                    tr => 1, html => 1,                                  & TABLE_ROW_SCOPING_EL)) {
                 }->{$self->{open_elements}->[-1]->[1]}) {  
5115                    !!!cp ('t236');                    !!!cp ('t236');
5116  ## ISSUE: Can this state be reached?  ## ISSUE: Can this state be reached?
5117                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
# Line 4775  sub _tree_construction_main ($) { Line 5127  sub _tree_construction_main ($) {
5127                  my $i;                  my $i;
5128                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5129                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
5130                    if ({                    if ($node->[1] & TABLE_ROW_GROUP_EL) {
                        tbody => 1, thead => 1, tfoot => 1,  
                       }->{$node->[1]}) {  
5131                      !!!cp ('t237');                      !!!cp ('t237');
5132                      $i = $_;                      $i = $_;
5133                      last INSCOPE;                      last INSCOPE;
5134                    } elsif ({                    } elsif ($node->[1] & TABLE_SCOPING_EL) {
                             table => 1, html => 1,  
                            }->{$node->[1]}) {  
5135                      !!!cp ('t238');                      !!!cp ('t238');
5136                      last INSCOPE;                      last INSCOPE;
5137                    }                    }
# Line 4792  sub _tree_construction_main ($) { Line 5140  sub _tree_construction_main ($) {
5140                    !!!cp ('t239');                    !!!cp ('t239');
5141                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5142                    ## Ignore the token                    ## Ignore the token
5143                      !!!nack ('t239.1');
5144                    !!!next-token;                    !!!next-token;
5145                    redo B;                    next B;
5146                  }                  }
5147                                    
5148                  ## Clear back to table body context                  ## Clear back to table body context
5149                  while (not {                  while (not ($self->{open_elements}->[-1]->[1]
5150                    tbody => 1, tfoot => 1, thead => 1, html => 1,                                  & TABLE_ROWS_SCOPING_EL)) {
                 }->{$self->{open_elements}->[-1]->[1]}) {  
5151                    !!!cp ('t240');                    !!!cp ('t240');
5152                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
5153                  }                  }
# Line 4825  sub _tree_construction_main ($) { Line 5173  sub _tree_construction_main ($) {
5173                my $i;                my $i;
5174                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5175                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
5176                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] & TABLE_EL) {
5177                    !!!cp ('t241');                    !!!cp ('t241');
5178                    $i = $_;                    $i = $_;
5179                    last INSCOPE;                    last INSCOPE;
5180                  } elsif ({                  } elsif ($node->[1] & TABLE_SCOPING_EL) {
                           table => 1, html => 1,  
                          }->{$node->[1]}) {  
5181                    !!!cp ('t242');                    !!!cp ('t242');
5182                    last INSCOPE;                    last INSCOPE;
5183                  }                  }
# Line 4840  sub _tree_construction_main ($) { Line 5186  sub _tree_construction_main ($) {
5186                  !!!cp ('t243');                  !!!cp ('t243');
5187                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5188                  ## Ignore the token                  ## Ignore the token
5189                    !!!nack ('t243.1');
5190                  !!!next-token;                  !!!next-token;
5191                  redo B;                  next B;
5192                }                }
5193                                    
5194                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
# Line 4850  sub _tree_construction_main ($) { Line 5197  sub _tree_construction_main ($) {
5197                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
5198                                
5199                !!!next-token;                !!!next-token;
5200                redo B;                next B;
5201              } elsif ({              } elsif ({
5202                        tbody => 1, tfoot => 1, thead => 1,                        tbody => 1, tfoot => 1, thead => 1,
5203                       }->{$token->{tag_name}} and                       }->{$token->{tag_name}} and
# Line 4860  sub _tree_construction_main ($) { Line 5207  sub _tree_construction_main ($) {
5207                  my $i;                  my $i;
5208                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5209                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
5210                    if ($node->[1] eq $token->{tag_name}) {                    if ($node->[0]->manakai_local_name eq $token->{tag_name}) {
5211                      !!!cp ('t247');                      !!!cp ('t247');
5212                      $i = $_;                      $i = $_;
5213                      last INSCOPE;                      last INSCOPE;
5214                    } elsif ({                    } elsif ($node->[1] & TABLE_SCOPING_EL) {
                             table => 1, html => 1,  
                            }->{$node->[1]}) {  
5215                      !!!cp ('t248');                      !!!cp ('t248');
5216                      last INSCOPE;                      last INSCOPE;
5217                    }                    }
# Line 4875  sub _tree_construction_main ($) { Line 5220  sub _tree_construction_main ($) {
5220                      !!!cp ('t249');                      !!!cp ('t249');
5221                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5222                      ## Ignore the token                      ## Ignore the token
5223                        !!!nack ('t249.1');
5224                      !!!next-token;                      !!!next-token;
5225                      redo B;                      next B;
5226                    }                    }
5227                                    
5228                  ## As if </tr>                  ## As if </tr>
# Line 4884  sub _tree_construction_main ($) { Line 5230  sub _tree_construction_main ($) {
5230                  my $i;                  my $i;
5231                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5232                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
5233                    if ($node->[1] eq 'tr') {                    if ($node->[1] & TABLE_ROW_EL) {
5234                      !!!cp ('t250');                      !!!cp ('t250');
5235                      $i = $_;                      $i = $_;
5236                      last INSCOPE;                      last INSCOPE;
5237                    } elsif ({                    } elsif ($node->[1] & TABLE_SCOPING_EL) {
                             table => 1, html => 1,  
                            }->{$node->[1]}) {  
5238                      !!!cp ('t251');                      !!!cp ('t251');
5239                      last INSCOPE;                      last INSCOPE;
5240                    }                    }
# Line 4899  sub _tree_construction_main ($) { Line 5243  sub _tree_construction_main ($) {
5243                      !!!cp ('t252');                      !!!cp ('t252');
5244                      !!!parse-error (type => 'unmatched end tag:tr', token => $token);                      !!!parse-error (type => 'unmatched end tag:tr', token => $token);
5245                      ## Ignore the token                      ## Ignore the token
5246                        !!!nack ('t252.1');
5247                      !!!next-token;                      !!!next-token;
5248                      redo B;                      next B;
5249                    }                    }
5250                                    
5251                  ## Clear back to table row context                  ## Clear back to table row context
5252                  while (not {                  while (not ($self->{open_elements}->[-1]->[1]
5253                    tr => 1, html => 1,                                  & TABLE_ROW_SCOPING_EL)) {
                 }->{$self->{open_elements}->[-1]->[1]}) {  
5254                    !!!cp ('t253');                    !!!cp ('t253');
5255  ## ISSUE: Can this case be reached?  ## ISSUE: Can this case be reached?
5256                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
# Line 4921  sub _tree_construction_main ($) { Line 5265  sub _tree_construction_main ($) {
5265                my $i;                my $i;
5266                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5267                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
5268                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[0]->manakai_local_name eq $token->{tag_name}) {
5269                    !!!cp ('t254');                    !!!cp ('t254');
5270                    $i = $_;                    $i = $_;
5271                    last INSCOPE;                    last INSCOPE;
5272                  } elsif ({                  } elsif ($node->[1] & TABLE_SCOPING_EL) {
                           table => 1, html => 1,  
                          }->{$node->[1]}) {  
5273                    !!!cp ('t255');                    !!!cp ('t255');
5274                    last INSCOPE;                    last INSCOPE;
5275                  }                  }
# Line 4936  sub _tree_construction_main ($) { Line 5278  sub _tree_construction_main ($) {
5278                  !!!cp ('t256');                  !!!cp ('t256');
5279                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5280                  ## Ignore the token                  ## Ignore the token
5281                    !!!nack ('t256.1');
5282                  !!!next-token;                  !!!next-token;
5283                  redo B;                  next B;
5284                }                }
5285    
5286                ## Clear back to table body context                ## Clear back to table body context
5287                while (not {                while (not ($self->{open_elements}->[-1]->[1]
5288                  tbody => 1, tfoot => 1, thead => 1, html => 1,                                & TABLE_ROWS_SCOPING_EL)) {
               }->{$self->{open_elements}->[-1]->[1]}) {  
5289                  !!!cp ('t257');                  !!!cp ('t257');
5290  ## ISSUE: Can this case be reached?  ## ISSUE: Can this case be reached?
5291                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
# Line 4951  sub _tree_construction_main ($) { Line 5293  sub _tree_construction_main ($) {
5293    
5294                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5295                $self->{insertion_mode} = IN_TABLE_IM;                $self->{insertion_mode} = IN_TABLE_IM;
5296                  !!!nack ('t257.1');
5297                !!!next-token;                !!!next-token;
5298                redo B;                next B;
5299              } elsif ({              } elsif ({
5300                        body => 1, caption => 1, col => 1, colgroup => 1,                        body => 1, caption => 1, col => 1, colgroup => 1,
5301                        html => 1, td => 1, th => 1,                        html => 1, td => 1, th => 1,
5302                        tr => 1, # $self->{insertion_mode} == IN_ROW_IM                        tr => 1, # $self->{insertion_mode} == IN_ROW_IM
5303                        tbody => 1, tfoot => 1, thead => 1, # $self->{insertion_mode} == IN_TABLE_IM                        tbody => 1, tfoot => 1, thead => 1, # $self->{insertion_mode} == IN_TABLE_IM
5304                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
5305                !!!cp ('t258');            !!!cp ('t258');
5306                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5307                ## Ignore the token            ## Ignore the token
5308                !!!next-token;            !!!nack ('t258.1');
5309                redo B;             !!!next-token;
5310              next B;
5311          } else {          } else {
5312            !!!cp ('t259');            !!!cp ('t259');
5313            !!!parse-error (type => 'in table:/'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'in table:/'.$token->{tag_name}, token => $token);
# Line 4972  sub _tree_construction_main ($) { Line 5316  sub _tree_construction_main ($) {
5316            #            #
5317          }          }
5318        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
5319          unless ($self->{open_elements}->[-1]->[1] eq 'html' and          unless ($self->{open_elements}->[-1]->[1] & HTML_EL and
5320                  @{$self->{open_elements}} == 1) { # redundant, maybe                  @{$self->{open_elements}} == 1) { # redundant, maybe
5321            !!!parse-error (type => 'in body:#eof', token => $token);            !!!parse-error (type => 'in body:#eof', token => $token);
5322            !!!cp ('t259.1');            !!!cp ('t259.1');
# Line 4994  sub _tree_construction_main ($) { Line 5338  sub _tree_construction_main ($) {
5338                unless (length $token->{data}) {                unless (length $token->{data}) {
5339                  !!!cp ('t260');                  !!!cp ('t260');
5340                  !!!next-token;                  !!!next-token;
5341                  redo B;                  next B;
5342                }                }
5343              }              }
5344                            
# Line 5005  sub _tree_construction_main ($) { Line 5349  sub _tree_construction_main ($) {
5349                !!!cp ('t262');                !!!cp ('t262');
5350                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5351                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5352                  !!!ack ('t262.1');
5353                !!!next-token;                !!!next-token;
5354                redo B;                next B;
5355              } else {              } else {
5356                !!!cp ('t263');                !!!cp ('t263');
5357                #                #
5358              }              }
5359            } elsif ($token->{type} == END_TAG_TOKEN) {            } elsif ($token->{type} == END_TAG_TOKEN) {
5360              if ($token->{tag_name} eq 'colgroup') {              if ($token->{tag_name} eq 'colgroup') {
5361                if ($self->{open_elements}->[-1]->[1] eq 'html') {                if ($self->{open_elements}->[-1]->[1] & HTML_EL) {
5362                  !!!cp ('t264');                  !!!cp ('t264');
5363                  !!!parse-error (type => 'unmatched end tag:colgroup', token => $token);                  !!!parse-error (type => 'unmatched end tag:colgroup', token => $token);
5364                  ## Ignore the token                  ## Ignore the token
5365                  !!!next-token;                  !!!next-token;
5366                  redo B;                  next B;
5367                } else {                } else {
5368                  !!!cp ('t265');                  !!!cp ('t265');
5369                  pop @{$self->{open_elements}}; # colgroup                  pop @{$self->{open_elements}}; # colgroup
5370                  $self->{insertion_mode} = IN_TABLE_IM;                  $self->{insertion_mode} = IN_TABLE_IM;
5371                  !!!next-token;                  !!!next-token;
5372                  redo B;                              next B;            
5373                }                }
5374              } elsif ($token->{tag_name} eq 'col') {              } elsif ($token->{tag_name} eq 'col') {
5375                !!!cp ('t266');                !!!cp ('t266');
5376                !!!parse-error (type => 'unmatched end tag:col', token => $token);                !!!parse-error (type => 'unmatched end tag:col', token => $token);
5377                ## Ignore the token                ## Ignore the token
5378                !!!next-token;                !!!next-token;
5379                redo B;                next B;
5380              } else {              } else {
5381                !!!cp ('t267');                !!!cp ('t267');
5382                #                #
5383              }              }
5384        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
5385          if ($self->{open_elements}->[-1]->[1] eq 'html' or          if ($self->{open_elements}->[-1]->[1] & HTML_EL and
5386              @{$self->{open_elements}} == 1) { # redundant, maybe              @{$self->{open_elements}} == 1) { # redundant, maybe
5387            !!!cp ('t270.2');            !!!cp ('t270.2');
5388            ## Stop parsing.            ## Stop parsing.
# Line 5048  sub _tree_construction_main ($) { Line 5393  sub _tree_construction_main ($) {
5393            pop @{$self->{open_elements}}; # colgroup            pop @{$self->{open_elements}}; # colgroup
5394            $self->{insertion_mode} = IN_TABLE_IM;            $self->{insertion_mode} = IN_TABLE_IM;
5395            ## Reprocess.            ## Reprocess.
5396            redo B;            next B;
5397          }          }
5398        } else {        } else {
5399          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
5400        }        }
5401    
5402            ## As if </colgroup>            ## As if </colgroup>
5403            if ($self->{open_elements}->[-1]->[1] eq 'html') {            if ($self->{open_elements}->[-1]->[1] & HTML_EL) {
5404              !!!cp ('t269');              !!!cp ('t269');
5405  ## TODO: Wrong error type?  ## TODO: Wrong error type?
5406              !!!parse-error (type => 'unmatched end tag:colgroup', token => $token);              !!!parse-error (type => 'unmatched end tag:colgroup', token => $token);
5407              ## Ignore the token              ## Ignore the token
5408                !!!nack ('t269.1');
5409              !!!next-token;              !!!next-token;
5410              redo B;              next B;
5411            } else {            } else {
5412              !!!cp ('t270');              !!!cp ('t270');
5413              pop @{$self->{open_elements}}; # colgroup              pop @{$self->{open_elements}}; # colgroup
5414              $self->{insertion_mode} = IN_TABLE_IM;              $self->{insertion_mode} = IN_TABLE_IM;
5415                !!!ack-later;
5416              ## reprocess              ## reprocess
5417              redo B;              next B;
5418            }            }
5419      } elsif ($self->{insertion_mode} & SELECT_IMS) {      } elsif ($self->{insertion_mode} & SELECT_IMS) {
5420        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
5421          !!!cp ('t271');          !!!cp ('t271');
5422          $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});          $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});
5423          !!!next-token;          !!!next-token;
5424          redo B;          next B;
5425        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
5426              if ($token->{tag_name} eq 'option') {          if ($token->{tag_name} eq 'option') {
5427                if ($self->{open_elements}->[-1]->[1] eq 'option') {            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {
5428                  !!!cp ('t272');              !!!cp ('t272');
5429                  ## As if </option>              ## As if </option>
5430                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
5431                } else {            } else {
5432                  !!!cp ('t273');              !!!cp ('t273');
5433                }            }
5434    
5435                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5436                !!!next-token;            !!!nack ('t273.1');
5437                redo B;            !!!next-token;
5438              } elsif ($token->{tag_name} eq 'optgroup') {            next B;
5439                if ($self->{open_elements}->[-1]->[1] eq 'option') {          } elsif ($token->{tag_name} eq 'optgroup') {
5440                  !!!cp ('t274');            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {
5441                  ## As if </option>              !!!cp ('t274');
5442                  pop @{$self->{open_elements}};              ## As if </option>
5443                } else {              pop @{$self->{open_elements}};
5444                  !!!cp ('t275');            } else {
5445                }              !!!cp ('t275');
5446              }
5447    
5448                if ($self->{open_elements}->[-1]->[1] eq 'optgroup') {            if ($self->{open_elements}->[-1]->[1] & OPTGROUP_EL) {
5449                  !!!cp ('t276');              !!!cp ('t276');
5450                  ## As if </optgroup>              ## As if </optgroup>
5451                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
5452                } else {            } else {
5453                  !!!cp ('t277');              !!!cp ('t277');
5454                }            }
5455    
5456                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5457                !!!next-token;            !!!nack ('t277.1');
5458                redo B;            !!!next-token;
5459              next B;
5460          } elsif ($token->{tag_name} eq 'select' or          } elsif ($token->{tag_name} eq 'select' or
5461                   $token->{tag_name} eq 'input' or                   $token->{tag_name} eq 'input' or
5462                   ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and                   ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and
# Line 5120  sub _tree_construction_main ($) { Line 5469  sub _tree_construction_main ($) {
5469            !!!parse-error (type => 'not closed:select', token => $token);            !!!parse-error (type => 'not closed:select', token => $token);
5470            ## NOTE: As if the token were </select> (<select> case) or            ## NOTE: As if the token were </select> (<select> case) or
5471            ## as if there were </select> (otherwise).            ## as if there were </select> (otherwise).
5472                ## have an element in table scope            ## have an element in table scope
5473                my $i;            my $i;
5474                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5475                  my $node = $self->{open_elements}->[$_];              my $node = $self->{open_elements}->[$_];
5476                  if ($node->[1] eq 'select') {              if ($node->[1] & SELECT_EL) {
5477                    !!!cp ('t278');                !!!cp ('t278');
5478                    $i = $_;                $i = $_;
5479                    last INSCOPE;                last INSCOPE;
5480                  } elsif ({              } elsif ($node->[1] & TABLE_SCOPING_EL) {
5481                            table => 1, html => 1,                !!!cp ('t279');
5482                           }->{$node->[1]}) {                last INSCOPE;
5483                    !!!cp ('t279');              }
5484                    last INSCOPE;            } # INSCOPE
5485                  }            unless (defined $i) {
5486                } # INSCOPE              !!!cp ('t280');
5487                unless (defined $i) {              !!!parse-error (type => 'unmatched end tag:select', token => $token);
5488                  !!!cp ('t280');              ## Ignore the token
5489                  !!!parse-error (type => 'unmatched end tag:select', token => $token);              !!!nack ('t280.1');
5490                  ## Ignore the token              !!!next-token;
5491                  !!!next-token;              next B;
5492                  redo B;            }
               }  
5493                                
5494                !!!cp ('t281');            !!!cp ('t281');
5495                splice @{$self->{open_elements}}, $i;            splice @{$self->{open_elements}}, $i;
5496    
5497                $self->_reset_insertion_mode;            $self->_reset_insertion_mode;
5498    
5499            if ($token->{tag_name} eq 'select') {            if ($token->{tag_name} eq 'select') {
5500              !!!cp ('t281.2');              !!!nack ('t281.2');
5501              !!!next-token;              !!!next-token;
5502              redo B;              next B;
5503            } else {            } else {
5504              !!!cp ('t281.1');              !!!cp ('t281.1');
5505                !!!ack-later;
5506              ## Reprocess the token.              ## Reprocess the token.
5507              redo B;              next B;
5508            }            }
5509          } else {          } else {
5510            !!!cp ('t282');            !!!cp ('t282');
5511            !!!parse-error (type => 'in select:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'in select:'.$token->{tag_name}, token => $token);
5512            ## Ignore the token            ## Ignore the token
5513              !!!nack ('t282.1');
5514            !!!next-token;            !!!next-token;
5515            redo B;            next B;
5516          }          }
5517        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
5518              if ($token->{tag_name} eq 'optgroup') {          if ($token->{tag_name} eq 'optgroup') {
5519                if ($self->{open_elements}->[-1]->[1] eq 'option' and            if ($self->{open_elements}->[-1]->[1] & OPTION_EL and
5520                    $self->{open_elements}->[-2]->[1] eq 'optgroup') {                $self->{open_elements}->[-2]->[1] & OPTGROUP_EL) {
5521                  !!!cp ('t283');              !!!cp ('t283');
5522                  ## As if </option>              ## As if </option>
5523                  splice @{$self->{open_elements}}, -2;              splice @{$self->{open_elements}}, -2;
5524                } elsif ($self->{open_elements}->[-1]->[1] eq 'optgroup') {            } elsif ($self->{open_elements}->[-1]->[1] & OPTGROUP_EL) {
5525                  !!!cp ('t284');              !!!cp ('t284');
5526                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
5527                } else {            } else {
5528                  !!!cp ('t285');              !!!cp ('t285');
5529                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5530                  ## Ignore the token              ## Ignore the token
5531                }            }
5532                !!!next-token;            !!!nack ('t285.1');
5533                redo B;            !!!next-token;
5534              } elsif ($token->{tag_name} eq 'option') {            next B;
5535                if ($self->{open_elements}->[-1]->[1] eq 'option') {          } elsif ($token->{tag_name} eq 'option') {
5536                  !!!cp ('t286');            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {
5537                  pop @{$self->{open_elements}};              !!!cp ('t286');
5538                } else {              pop @{$self->{open_elements}};
5539                  !!!cp ('t287');            } else {
5540                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);              !!!cp ('t287');
5541                  ## Ignore the token              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5542                }              ## Ignore the token
5543                !!!next-token;            }
5544                redo B;            !!!nack ('t287.1');
5545              } elsif ($token->{tag_name} eq 'select') {            !!!next-token;
5546                ## have an element in table scope            next B;
5547                my $i;          } elsif ($token->{tag_name} eq 'select') {
5548                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {            ## have an element in table scope
5549                  my $node = $self->{open_elements}->[$_];            my $i;
5550                  if ($node->[1] eq $token->{tag_name}) {            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5551                    !!!cp ('t288');              my $node = $self->{open_elements}->[$_];
5552                    $i = $_;              if ($node->[1] & SELECT_EL) {
5553                    last INSCOPE;                !!!cp ('t288');
5554                  } elsif ({                $i = $_;
5555                            table => 1, html => 1,                last INSCOPE;
5556                           }->{$node->[1]}) {              } elsif ($node->[1] & TABLE_SCOPING_EL) {
5557                    !!!cp ('t289');                !!!cp ('t289');
5558                    last INSCOPE;                last INSCOPE;
5559                  }              }
5560                } # INSCOPE            } # INSCOPE
5561                unless (defined $i) {            unless (defined $i) {
5562                  !!!cp ('t290');              !!!cp ('t290');
5563                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5564                  ## Ignore the token              ## Ignore the token
5565                  !!!next-token;              !!!nack ('t290.1');
5566                  redo B;              !!!next-token;
5567                }              next B;
5568              }
5569                                
5570                !!!cp ('t291');            !!!cp ('t291');
5571                splice @{$self->{open_elements}}, $i;            splice @{$self->{open_elements}}, $i;
5572    
5573                $self->_reset_insertion_mode;            $self->_reset_insertion_mode;
5574    
5575                !!!next-token;            !!!nack ('t291.1');
5576                redo B;            !!!next-token;
5577              next B;
5578          } elsif ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and          } elsif ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and
5579                   {                   {
5580                    caption => 1, table => 1, tbody => 1,                    caption => 1, table => 1, tbody => 1,
5581                    tfoot => 1, thead => 1, tr => 1, td => 1, th => 1,                    tfoot => 1, thead => 1, tr => 1, td => 1, th => 1,
5582                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
5583  ## TODO: The following is wrong?  ## TODO: The following is wrong?
5584                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
5585                                
5586                ## have an element in table scope            ## have an element in table scope
5587                my $i;            my $i;
5588                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5589                  my $node = $self->{open_elements}->[$_];              my $node = $self->{open_elements}->[$_];
5590                  if ($node->[1] eq $token->{tag_name}) {              if ($node->[0]->manakai_local_name eq $token->{tag_name}) {
5591                    !!!cp ('t292');                !!!cp ('t292');
5592                    $i = $_;                $i = $_;
5593                    last INSCOPE;                last INSCOPE;
5594                  } elsif ({              } elsif ($node->[1] & TABLE_SCOPING_EL) {
5595                            table => 1, html => 1,                !!!cp ('t293');
5596                           }->{$node->[1]}) {                last INSCOPE;
5597                    !!!cp ('t293');              }
5598                    last INSCOPE;            } # INSCOPE
5599                  }            unless (defined $i) {
5600                } # INSCOPE              !!!cp ('t294');
5601                unless (defined $i) {              ## Ignore the token
5602                  !!!cp ('t294');              !!!nack ('t294.1');
5603                  ## Ignore the token              !!!next-token;
5604                  !!!next-token;              next B;
5605                  redo B;            }
               }  
5606                                
5607                ## As if </select>            ## As if </select>
5608                ## have an element in table scope            ## have an element in table scope
5609                undef $i;            undef $i;
5610                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5611                  my $node = $self->{open_elements}->[$_];              my $node = $self->{open_elements}->[$_];
5612                  if ($node->[1] eq 'select') {              if ($node->[1] & SELECT_EL) {
5613                    !!!cp ('t295');                !!!cp ('t295');
5614                    $i = $_;                $i = $_;
5615                    last INSCOPE;                last INSCOPE;
5616                  } elsif ({              } elsif ($node->[1] & TABLE_SCOPING_EL) {
                           table => 1, html => 1,  
                          }->{$node->[1]}) {  
5617  ## ISSUE: Can this state be reached?  ## ISSUE: Can this state be reached?
5618                    !!!cp ('t296');                !!!cp ('t296');
5619                    last INSCOPE;                last INSCOPE;
5620                  }              }
5621                } # INSCOPE            } # INSCOPE
5622                unless (defined $i) {            unless (defined $i) {
5623                  !!!cp ('t297');              !!!cp ('t297');
5624  ## TODO: The following error type is correct?  ## TODO: The following error type is correct?
5625                  !!!parse-error (type => 'unmatched end tag:select', token => $token);              !!!parse-error (type => 'unmatched end tag:select', token => $token);
5626                  ## Ignore the </select> token              ## Ignore the </select> token
5627                  !!!next-token; ## TODO: ok?              !!!nack ('t297.1');
5628                  redo B;              !!!next-token; ## TODO: ok?
5629                }              next B;
5630              }
5631                                
5632                !!!cp ('t298');            !!!cp ('t298');
5633                splice @{$self->{open_elements}}, $i;            splice @{$self->{open_elements}}, $i;
5634    
5635                $self->_reset_insertion_mode;            $self->_reset_insertion_mode;
5636    
5637                ## reprocess            !!!ack-later;
5638                redo B;            ## reprocess
5639              next B;
5640          } else {          } else {
5641            !!!cp ('t299');            !!!cp ('t299');
5642            !!!parse-error (type => 'in select:/'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'in select:/'.$token->{tag_name}, token => $token);
5643            ## Ignore the token            ## Ignore the token
5644              !!!nack ('t299.3');
5645            !!!next-token;            !!!next-token;
5646            redo B;            next B;
5647          }          }
5648        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
5649          unless ($self->{open_elements}->[-1]->[1] eq 'html' and          unless ($self->{open_elements}->[-1]->[1] & HTML_EL and
5650                  @{$self->{open_elements}} == 1) { # redundant, maybe                  @{$self->{open_elements}} == 1) { # redundant, maybe
5651            !!!cp ('t299.1');            !!!cp ('t299.1');
5652            !!!parse-error (type => 'in body:#eof', token => $token);            !!!parse-error (type => 'in body:#eof', token => $token);
# Line 5319  sub _tree_construction_main ($) { Line 5671  sub _tree_construction_main ($) {
5671            unless (length $token->{data}) {            unless (length $token->{data}) {
5672              !!!cp ('t300');              !!!cp ('t300');
5673              !!!next-token;              !!!next-token;
5674              redo B;              next B;
5675            }            }
5676          }          }
5677                    
# Line 5337  sub _tree_construction_main ($) { Line 5689  sub _tree_construction_main ($) {
5689    
5690          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
5691          ## reprocess          ## reprocess
5692          redo B;          next B;
5693        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
5694          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
5695            !!!cp ('t303');            !!!cp ('t303');
# Line 5352  sub _tree_construction_main ($) { Line 5704  sub _tree_construction_main ($) {
5704          !!!parse-error (type => 'after body:'.$token->{tag_name}, token => $token);          !!!parse-error (type => 'after body:'.$token->{tag_name}, token => $token);
5705    
5706          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
5707            !!!ack-later;
5708          ## reprocess          ## reprocess
5709          redo B;          next B;
5710        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
5711          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
5712            !!!cp ('t305');            !!!cp ('t305');
# Line 5372  sub _tree_construction_main ($) { Line 5725  sub _tree_construction_main ($) {
5725              !!!parse-error (type => 'unmatched end tag:html', token => $token);              !!!parse-error (type => 'unmatched end tag:html', token => $token);
5726              ## Ignore the token              ## Ignore the token
5727              !!!next-token;              !!!next-token;
5728              redo B;              next B;
5729            } else {            } else {
5730              !!!cp ('t308');              !!!cp ('t308');
5731              $self->{insertion_mode} = AFTER_HTML_BODY_IM;              $self->{insertion_mode} = AFTER_HTML_BODY_IM;
5732              !!!next-token;              !!!next-token;
5733              redo B;              next B;
5734            }            }
5735          } else {          } else {
5736            !!!cp ('t309');            !!!cp ('t309');
# Line 5385  sub _tree_construction_main ($) { Line 5738  sub _tree_construction_main ($) {
5738    
5739            $self->{insertion_mode} = IN_BODY_IM;            $self->{insertion_mode} = IN_BODY_IM;
5740            ## reprocess            ## reprocess
5741            redo B;            next B;
5742          }          }
5743        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
5744          !!!cp ('t309.2');          !!!cp ('t309.2');
# Line 5402  sub _tree_construction_main ($) { Line 5755  sub _tree_construction_main ($) {
5755            unless (length $token->{data}) {            unless (length $token->{data}) {
5756              !!!cp ('t310');              !!!cp ('t310');
5757              !!!next-token;              !!!next-token;
5758              redo B;              next B;
5759            }            }
5760          }          }
5761                    
# Line 5430  sub _tree_construction_main ($) { Line 5783  sub _tree_construction_main ($) {
5783              !!!cp ('t315');              !!!cp ('t315');
5784              !!!next-token;              !!!next-token;
5785            }            }
5786            redo B;            next B;
5787          }          }
5788                    
5789          die qq[$0: Character "$token->{data}"];          die qq[$0: Character "$token->{data}"];
# Line 5449  sub _tree_construction_main ($) { Line 5802  sub _tree_construction_main ($) {
5802              $self->{insertion_mode} == IN_FRAMESET_IM) {              $self->{insertion_mode} == IN_FRAMESET_IM) {
5803            !!!cp ('t318');            !!!cp ('t318');
5804            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5805              !!!nack ('t318.1');
5806            !!!next-token;            !!!next-token;
5807            redo B;            next B;
5808          } elsif ($token->{tag_name} eq 'frame' and          } elsif ($token->{tag_name} eq 'frame' and
5809                   $self->{insertion_mode} == IN_FRAMESET_IM) {                   $self->{insertion_mode} == IN_FRAMESET_IM) {
5810            !!!cp ('t319');            !!!cp ('t319');
5811            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5812            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
5813              !!!ack ('t319.1');
5814            !!!next-token;            !!!next-token;
5815            redo B;            next B;
5816          } elsif ($token->{tag_name} eq 'noframes') {          } elsif ($token->{tag_name} eq 'noframes') {
5817            !!!cp ('t320');            !!!cp ('t320');
5818            ## NOTE: As if in body.            ## NOTE: As if in body.
5819            $parse_rcdata->(CDATA_CONTENT_MODEL);            $parse_rcdata->(CDATA_CONTENT_MODEL);
5820            redo B;            next B;
5821          } else {          } else {
5822            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
5823              !!!cp ('t321');              !!!cp ('t321');
# Line 5472  sub _tree_construction_main ($) { Line 5827  sub _tree_construction_main ($) {
5827              !!!parse-error (type => 'after frameset:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'after frameset:'.$token->{tag_name}, token => $token);
5828            }            }
5829            ## Ignore the token            ## Ignore the token
5830              !!!nack ('t322.1');
5831            !!!next-token;            !!!next-token;
5832            redo B;            next B;
5833          }          }
5834        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
5835          if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {          if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {
# Line 5488  sub _tree_construction_main ($) { Line 5844  sub _tree_construction_main ($) {
5844    
5845          if ($token->{tag_name} eq 'frameset' and          if ($token->{tag_name} eq 'frameset' and
5846              $self->{insertion_mode} == IN_FRAMESET_IM) {              $self->{insertion_mode} == IN_FRAMESET_IM) {
5847            if ($self->{open_elements}->[-1]->[1] eq 'html' and            if ($self->{open_elements}->[-1]->[1] & HTML_EL and
5848                @{$self->{open_elements}} == 1) {                @{$self->{open_elements}} == 1) {
5849              !!!cp ('t325');              !!!cp ('t325');
5850              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
# Line 5501  sub _tree_construction_main ($) { Line 5857  sub _tree_construction_main ($) {
5857            }            }
5858    
5859            if (not defined $self->{inner_html_node} and            if (not defined $self->{inner_html_node} and
5860                $self->{open_elements}->[-1]->[1] ne 'frameset') {                not ($self->{open_elements}->[-1]->[1] & FRAMESET_EL)) {
5861              !!!cp ('t327');              !!!cp ('t327');
5862              $self->{insertion_mode} = AFTER_FRAMESET_IM;              $self->{insertion_mode} = AFTER_FRAMESET_IM;
5863            } else {            } else {
5864              !!!cp ('t328');              !!!cp ('t328');
5865            }            }
5866            redo B;            next B;
5867          } elsif ($token->{tag_name} eq 'html' and          } elsif ($token->{tag_name} eq 'html' and
5868                   $self->{insertion_mode} == AFTER_FRAMESET_IM) {                   $self->{insertion_mode} == AFTER_FRAMESET_IM) {
5869            !!!cp ('t329');            !!!cp ('t329');
5870            $self->{insertion_mode} = AFTER_HTML_FRAMESET_IM;            $self->{insertion_mode} = AFTER_HTML_FRAMESET_IM;
5871            !!!next-token;            !!!next-token;
5872            redo B;            next B;
5873          } else {          } else {
5874            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
5875              !!!cp ('t330');              !!!cp ('t330');
# Line 5524  sub _tree_construction_main ($) { Line 5880  sub _tree_construction_main ($) {
5880            }            }
5881            ## Ignore the token            ## Ignore the token
5882            !!!next-token;            !!!next-token;
5883            redo B;            next B;
5884          }          }
5885        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
5886          unless ($self->{open_elements}->[-1]->[1] eq 'html' and          unless ($self->{open_elements}->[-1]->[1] & HTML_EL and
5887                  @{$self->{open_elements}} == 1) { # redundant, maybe                  @{$self->{open_elements}} == 1) { # redundant, maybe
5888            !!!cp ('t331.1');            !!!cp ('t331.1');
5889            !!!parse-error (type => 'in body:#eof', token => $token);            !!!parse-error (type => 'in body:#eof', token => $token);
# Line 5552  sub _tree_construction_main ($) { Line 5908  sub _tree_construction_main ($) {
5908          !!!cp ('t332');          !!!cp ('t332');
5909          ## NOTE: This is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone
5910          $script_start_tag->();          $script_start_tag->();
5911          redo B;          next B;
5912        } elsif ($token->{tag_name} eq 'style') {        } elsif ($token->{tag_name} eq 'style') {
5913          !!!cp ('t333');          !!!cp ('t333');
5914          ## NOTE: This is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone
5915          $parse_rcdata->(CDATA_CONTENT_MODEL);          $parse_rcdata->(CDATA_CONTENT_MODEL);
5916          redo B;          next B;
5917        } elsif ({        } elsif ({
5918                  base => 1, link => 1,                  base => 1, link => 1,
5919                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 5565  sub _tree_construction_main ($) { Line 5921  sub _tree_construction_main ($) {
5921          ## 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
5922          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
5923          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
5924            !!!ack ('t334.1');
5925          !!!next-token;          !!!next-token;
5926          redo B;          next B;
5927        } elsif ($token->{tag_name} eq 'meta') {        } elsif ($token->{tag_name} eq 'meta') {
5928          ## 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
5929          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
# Line 5615  sub _tree_construction_main ($) { Line 5972  sub _tree_construction_main ($) {
5972            }            }
5973          }          }
5974    
5975            !!!ack ('t338.1');
5976          !!!next-token;          !!!next-token;
5977          redo B;          next B;
5978        } elsif ($token->{tag_name} eq 'title') {        } elsif ($token->{tag_name} eq 'title') {
5979          !!!cp ('t341');          !!!cp ('t341');
5980          ## NOTE: This is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone
5981          $parse_rcdata->(RCDATA_CONTENT_MODEL);          $parse_rcdata->(RCDATA_CONTENT_MODEL);
5982          redo B;          next B;
5983        } elsif ($token->{tag_name} eq 'body') {        } elsif ($token->{tag_name} eq 'body') {
5984          !!!parse-error (type => 'in body:body', token => $token);          !!!parse-error (type => 'in body:body', token => $token);
5985                                
5986          if (@{$self->{open_elements}} == 1 or          if (@{$self->{open_elements}} == 1 or
5987              $self->{open_elements}->[1]->[1] ne 'body') {              not ($self->{open_elements}->[1]->[1] & BODY_EL)) {
5988            !!!cp ('t342');            !!!cp ('t342');
5989            ## Ignore the token            ## Ignore the token
5990          } else {          } else {
# Line 5640  sub _tree_construction_main ($) { Line 5998  sub _tree_construction_main ($) {
5998              }              }
5999            }            }
6000          }          }
6001            !!!nack ('t343.1');
6002          !!!next-token;          !!!next-token;
6003          redo B;          next B;
6004        } elsif ({        } elsif ({
6005                  address => 1, blockquote => 1, center => 1, dir => 1,                  address => 1, blockquote => 1, center => 1, dir => 1,
6006                  div => 1, dl => 1, fieldset => 1,                  div => 1, dl => 1, fieldset => 1,
# Line 5656  sub _tree_construction_main ($) { Line 6015  sub _tree_construction_main ($) {
6015            !!!cp ('t350');            !!!cp ('t350');
6016            !!!parse-error (type => 'in form:form', token => $token);            !!!parse-error (type => 'in form:form', token => $token);
6017            ## Ignore the token            ## Ignore the token
6018              !!!nack ('t350.1');
6019            !!!next-token;            !!!next-token;
6020            redo B;            next B;
6021          }          }
6022    
6023          ## has a p element in scope          ## has a p element in scope
6024          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
6025            if ($_->[1] eq 'p') {            if ($_->[1] & P_EL) {
6026              !!!cp ('t344');              !!!cp ('t344');
6027              !!!back-token;              !!!back-token; # <form>
6028              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
6029                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
6030              redo B;              next B;
6031            } elsif ({            } elsif ($_->[1] & SCOPING_EL) {
                     applet => 1, table => 1, caption => 1, td => 1, th => 1,  
                     button => 1, marquee => 1, object => 1, html => 1,  
                    }->{$_->[1]}) {  
6032              !!!cp ('t345');              !!!cp ('t345');
6033              last INSCOPE;              last INSCOPE;
6034            }            }
# Line 5679  sub _tree_construction_main ($) { Line 6036  sub _tree_construction_main ($) {
6036                        
6037          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6038          if ($token->{tag_name} eq 'pre' or $token->{tag_name} eq 'listing') {          if ($token->{tag_name} eq 'pre' or $token->{tag_name} eq 'listing') {
6039              !!!nack ('t346.1');
6040            !!!next-token;            !!!next-token;
6041            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
6042              $token->{data} =~ s/^\x0A//;              $token->{data} =~ s/^\x0A//;
# Line 5695  sub _tree_construction_main ($) { Line 6053  sub _tree_construction_main ($) {
6053            !!!cp ('t347.1');            !!!cp ('t347.1');
6054            $self->{form_element} = $self->{open_elements}->[-1]->[0];            $self->{form_element} = $self->{open_elements}->[-1]->[0];
6055    
6056              !!!nack ('t347.2');
6057            !!!next-token;            !!!next-token;
6058          } elsif ($token->{tag_name} eq 'table') {          } elsif ($token->{tag_name} eq 'table') {
6059            !!!cp ('t382');            !!!cp ('t382');
# Line 5702  sub _tree_construction_main ($) { Line 6061  sub _tree_construction_main ($) {
6061                        
6062            $self->{insertion_mode} = IN_TABLE_IM;            $self->{insertion_mode} = IN_TABLE_IM;
6063    
6064              !!!nack ('t382.1');
6065            !!!next-token;            !!!next-token;
6066          } elsif ($token->{tag_name} eq 'hr') {          } elsif ($token->{tag_name} eq 'hr') {
6067            !!!cp ('t386');            !!!cp ('t386');
6068            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
6069                    
6070              !!!nack ('t386.1');
6071            !!!next-token;            !!!next-token;
6072          } else {          } else {
6073            !!!cp ('t347');            !!!nack ('t347.1');
6074            !!!next-token;            !!!next-token;
6075          }          }
6076          redo B;          next B;
6077        } elsif ({li => 1, dt => 1, dd => 1}->{$token->{tag_name}}) {        } elsif ({li => 1, dt => 1, dd => 1}->{$token->{tag_name}}) {
6078          ## has a p element in scope          ## has a p element in scope
6079          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
6080            if ($_->[1] eq 'p') {            if ($_->[1] & P_EL) {
6081              !!!cp ('t353');              !!!cp ('t353');
6082              !!!back-token;              !!!back-token; # <x>
6083              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
6084                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
6085              redo B;              next B;
6086            } elsif ({            } elsif ($_->[1] & SCOPING_EL) {
                     applet => 1, table => 1, caption => 1, td => 1, th => 1,  
                     button => 1, marquee => 1, object => 1, html => 1,  
                    }->{$_->[1]}) {  
6087              !!!cp ('t354');              !!!cp ('t354');
6088              last INSCOPE;              last INSCOPE;
6089            }            }
# Line 5739  sub _tree_construction_main ($) { Line 6097  sub _tree_construction_main ($) {
6097                            dd => {dt => 1, dd => 1}}->{$token->{tag_name}};                            dd => {dt => 1, dd => 1}}->{$token->{tag_name}};
6098          LI: {          LI: {
6099            ## Step 2            ## Step 2
6100            if ($li_or_dtdd->{$node->[1]}) {            if ($li_or_dtdd->{$node->[0]->manakai_local_name}) {
6101              if ($i != -1) {              if ($i != -1) {
6102                !!!cp ('t355');                !!!cp ('t355');
6103                !!!parse-error (type => 'end tag missing:'.                !!!parse-error (type => 'not closed',
6104                                $self->{open_elements}->[-1]->[1], token => $token);                                value => $self->{open_elements}->[-1]->[0]
6105                                      ->manakai_local_name,
6106                                  token => $token);
6107              } else {              } else {
6108                !!!cp ('t356');                !!!cp ('t356');
6109              }              }
# Line 5754  sub _tree_construction_main ($) { Line 6114  sub _tree_construction_main ($) {
6114            }            }
6115                        
6116            ## Step 3            ## Step 3
6117            if (not $formatting_category->{$node->[1]} and            if (not ($node->[1] & FORMATTING_EL) and
6118                #not $phrasing_category->{$node->[1]} and                #not $phrasing_category->{$node->[1]} and
6119                ($special_category->{$node->[1]} or                ($node->[1] & SPECIAL_EL or
6120                 $scoping_category->{$node->[1]}) and                 $node->[1] & SCOPING_EL) and
6121                $node->[1] ne 'address' and $node->[1] ne 'div') {                not ($node->[1] & ADDRESS_EL) and
6122                  not ($node->[1] & DIV_EL)) {
6123              !!!cp ('t358');              !!!cp ('t358');
6124              last LI;              last LI;
6125            }            }
# Line 5771  sub _tree_construction_main ($) { Line 6132  sub _tree_construction_main ($) {
6132          } # LI          } # LI
6133                        
6134          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6135            !!!nack ('t359.1');
6136          !!!next-token;          !!!next-token;
6137          redo B;          next B;
6138        } elsif ($token->{tag_name} eq 'plaintext') {        } elsif ($token->{tag_name} eq 'plaintext') {
6139          ## has a p element in scope          ## has a p element in scope
6140          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
6141            if ($_->[1] eq 'p') {            if ($_->[1] & P_EL) {
6142              !!!cp ('t367');              !!!cp ('t367');
6143              !!!back-token;              !!!back-token; # <plaintext>
6144              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
6145                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
6146              redo B;              next B;
6147            } elsif ({            } elsif ($_->[1] & SCOPING_EL) {
                     applet => 1, table => 1, caption => 1, td => 1, th => 1,  
                     button => 1, marquee => 1, object => 1, html => 1,  
                    }->{$_->[1]}) {  
6148              !!!cp ('t368');              !!!cp ('t368');
6149              last INSCOPE;              last INSCOPE;
6150            }            }
# Line 5795  sub _tree_construction_main ($) { Line 6154  sub _tree_construction_main ($) {
6154                        
6155          $self->{content_model} = PLAINTEXT_CONTENT_MODEL;          $self->{content_model} = PLAINTEXT_CONTENT_MODEL;
6156                        
6157            !!!nack ('t368.1');
6158          !!!next-token;          !!!next-token;
6159          redo B;          next B;
6160        } elsif ($token->{tag_name} eq 'a') {        } elsif ($token->{tag_name} eq 'a') {
6161          AFE: for my $i (reverse 0..$#$active_formatting_elements) {          AFE: for my $i (reverse 0..$#$active_formatting_elements) {
6162            my $node = $active_formatting_elements->[$i];            my $node = $active_formatting_elements->[$i];
6163            if ($node->[1] eq 'a') {            if ($node->[1] & A_EL) {
6164              !!!cp ('t371');              !!!cp ('t371');
6165              !!!parse-error (type => 'in a:a', token => $token);              !!!parse-error (type => 'in a:a', token => $token);
6166                            
6167              !!!back-token;              !!!back-token; # <a>
6168              $token = {type => END_TAG_TOKEN, tag_name => 'a',              $token = {type => END_TAG_TOKEN, tag_name => 'a',
6169                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
6170              $formatting_end_tag->($token);              $formatting_end_tag->($token);
# Line 5835  sub _tree_construction_main ($) { Line 6195  sub _tree_construction_main ($) {
6195          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6196          push @$active_formatting_elements, $self->{open_elements}->[-1];          push @$active_formatting_elements, $self->{open_elements}->[-1];
6197    
6198            !!!nack ('t374.1');
6199          !!!next-token;          !!!next-token;
6200          redo B;          next B;
6201        } elsif ($token->{tag_name} eq 'nobr') {        } elsif ($token->{tag_name} eq 'nobr') {
6202          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
6203    
6204          ## has a |nobr| element in scope          ## has a |nobr| element in scope
6205          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6206            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
6207            if ($node->[1] eq 'nobr') {            if ($node->[1] & NOBR_EL) {
6208              !!!cp ('t376');              !!!cp ('t376');
6209              !!!parse-error (type => 'in nobr:nobr', token => $token);              !!!parse-error (type => 'in nobr:nobr', token => $token);
6210              !!!back-token;              !!!back-token; # <nobr>
6211              $token = {type => END_TAG_TOKEN, tag_name => 'nobr',              $token = {type => END_TAG_TOKEN, tag_name => 'nobr',
6212                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
6213              redo B;              next B;
6214            } elsif ({            } elsif ($node->[1] & SCOPING_EL) {
                     applet => 1, table => 1, caption => 1, td => 1, th => 1,  
                     button => 1, marquee => 1, object => 1, html => 1,  
                    }->{$node->[1]}) {  
6215              !!!cp ('t377');              !!!cp ('t377');
6216              last INSCOPE;              last INSCOPE;
6217            }            }
# Line 5862  sub _tree_construction_main ($) { Line 6220  sub _tree_construction_main ($) {
6220          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6221          push @$active_formatting_elements, $self->{open_elements}->[-1];          push @$active_formatting_elements, $self->{open_elements}->[-1];
6222                    
6223            !!!nack ('t377.1');
6224          !!!next-token;          !!!next-token;
6225          redo B;          next B;
6226        } elsif ($token->{tag_name} eq 'button') {        } elsif ($token->{tag_name} eq 'button') {
6227          ## has a button element in scope          ## has a button element in scope
6228          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6229            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
6230            if ($node->[1] eq 'button') {            if ($node->[1] & BUTTON_EL) {
6231              !!!cp ('t378');              !!!cp ('t378');
6232              !!!parse-error (type => 'in button:button', token => $token);              !!!parse-error (type => 'in button:button', token => $token);
6233              !!!back-token;              !!!back-token; # <button>
6234              $token = {type => END_TAG_TOKEN, tag_name => 'button',              $token = {type => END_TAG_TOKEN, tag_name => 'button',
6235                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
6236              redo B;              next B;
6237            } elsif ({            } elsif ($node->[1] & SCOPING_EL) {
                     applet => 1, table => 1, caption => 1, td => 1, th => 1,  
                     button => 1, marquee => 1, object => 1, html => 1,  
                    }->{$node->[1]}) {  
6238              !!!cp ('t379');              !!!cp ('t379');
6239              last INSCOPE;              last INSCOPE;
6240            }            }
# Line 5892  sub _tree_construction_main ($) { Line 6248  sub _tree_construction_main ($) {
6248    
6249          push @$active_formatting_elements, ['#marker', ''];          push @$active_formatting_elements, ['#marker', ''];
6250    
6251            !!!nack ('t379.1');
6252          !!!next-token;          !!!next-token;
6253          redo B;          next B;
6254        } elsif ({        } elsif ({
6255                  xmp => 1,                  xmp => 1,
6256                  iframe => 1,                  iframe => 1,
# Line 5909  sub _tree_construction_main ($) { Line 6266  sub _tree_construction_main ($) {
6266          }          }
6267          ## NOTE: There is an "as if in body" code clone.          ## NOTE: There is an "as if in body" code clone.
6268          $parse_rcdata->(CDATA_CONTENT_MODEL);          $parse_rcdata->(CDATA_CONTENT_MODEL);
6269          redo B;          next B;
6270        } elsif ($token->{tag_name} eq 'isindex') {        } elsif ($token->{tag_name} eq 'isindex') {
6271          !!!parse-error (type => 'isindex', token => $token);          !!!parse-error (type => 'isindex', token => $token);
6272                    
6273          if (defined $self->{form_element}) {          if (defined $self->{form_element}) {
6274            !!!cp ('t389');            !!!cp ('t389');
6275            ## Ignore the token            ## Ignore the token
6276              !!!nack ('t389'); ## NOTE: Not acknowledged.
6277            !!!next-token;            !!!next-token;
6278            redo B;            next B;
6279          } else {          } else {
6280            my $at = $token->{attributes};            my $at = $token->{attributes};
6281            my $form_attrs;            my $form_attrs;
# Line 5962  sub _tree_construction_main ($) { Line 6320  sub _tree_construction_main ($) {
6320                           line => $token->{line}, column => $token->{column}},                           line => $token->{line}, column => $token->{column}},
6321                          {type => END_TAG_TOKEN, tag_name => 'form',                          {type => END_TAG_TOKEN, tag_name => 'form',
6322                           line => $token->{line}, column => $token->{column}};                           line => $token->{line}, column => $token->{column}};
6323            $token = shift @tokens;            !!!nack ('t391.1'); ## NOTE: Not acknowledged.
6324            !!!back-token (@tokens);            !!!back-token (@tokens);
6325            redo B;            !!!next-token;
6326              next B;
6327          }          }
6328        } elsif ($token->{tag_name} eq 'textarea') {        } elsif ($token->{tag_name} eq 'textarea') {
6329          my $tag_name = $token->{tag_name};          my $tag_name = $token->{tag_name};
6330          my $el;          my $el;
6331          !!!create-element ($el, $token->{tag_name}, $token->{attributes}, $token);          !!!create-element ($el, $HTML_NS, $token->{tag_name}, $token->{attributes}, $token);
6332                    
6333          ## TODO: $self->{form_element} if defined          ## TODO: $self->{form_element} if defined
6334          $self->{content_model} = RCDATA_CONTENT_MODEL;          $self->{content_model} = RCDATA_CONTENT_MODEL;
# Line 5978  sub _tree_construction_main ($) { Line 6337  sub _tree_construction_main ($) {
6337          $insert->($el);          $insert->($el);
6338                    
6339          my $text = '';          my $text = '';
6340            !!!nack ('t392.1');
6341          !!!next-token;          !!!next-token;
6342          if ($token->{type} == CHARACTER_TOKEN) {          if ($token->{type} == CHARACTER_TOKEN) {
6343            $token->{data} =~ s/^\x0A//;            $token->{data} =~ s/^\x0A//;
# Line 6011  sub _tree_construction_main ($) { Line 6371  sub _tree_construction_main ($) {
6371            !!!parse-error (type => 'in RCDATA:#'.$token->{type}, token => $token);            !!!parse-error (type => 'in RCDATA:#'.$token->{type}, token => $token);
6372          }          }
6373          !!!next-token;          !!!next-token;
6374          redo B;          next B;
6375          } elsif ($token->{tag_name} eq 'math' or
6376                   $token->{tag_name} eq 'svg') {
6377            $reconstruct_active_formatting_elements->($insert_to_current);
6378            
6379            !!!insert-element-f ($token->{tag_name} eq 'math' ? $MML_NS : $SVG_NS, $token);
6380            
6381            if ($self->{self_closing}) {
6382              pop @{$self->{open_elements}};
6383              !!!ack ('t398.1');
6384            } else {
6385              !!!cp ('t398.2');
6386              $self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM;
6387              ## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion
6388              ## mode, "in body" (not "in foreign content") secondary insertion
6389              ## mode, maybe.
6390            }
6391    
6392            !!!next-token;
6393            next B;
6394        } elsif ({        } elsif ({
6395                  caption => 1, col => 1, colgroup => 1, frame => 1,                  caption => 1, col => 1, colgroup => 1, frame => 1,
6396                  frameset => 1, head => 1, option => 1, optgroup => 1,                  frameset => 1, head => 1, option => 1, optgroup => 1,
# Line 6021  sub _tree_construction_main ($) { Line 6400  sub _tree_construction_main ($) {
6400          !!!cp ('t401');          !!!cp ('t401');
6401          !!!parse-error (type => 'in body:'.$token->{tag_name}, token => $token);          !!!parse-error (type => 'in body:'.$token->{tag_name}, token => $token);
6402          ## Ignore the token          ## Ignore the token
6403            !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.
6404          !!!next-token;          !!!next-token;
6405          redo B;          next B;
6406                    
6407          ## ISSUE: An issue on HTML5 new elements in the spec.          ## ISSUE: An issue on HTML5 new elements in the spec.
6408        } else {        } else {
# Line 6044  sub _tree_construction_main ($) { Line 6424  sub _tree_construction_main ($) {
6424              }->{$token->{tag_name}}) {              }->{$token->{tag_name}}) {
6425            !!!cp ('t380');            !!!cp ('t380');
6426            push @$active_formatting_elements, ['#marker', ''];            push @$active_formatting_elements, ['#marker', ''];
6427              !!!nack ('t380.1');
6428          } elsif ({          } elsif ({
6429                    b => 1, big => 1, em => 1, font => 1, i => 1,                    b => 1, big => 1, em => 1, font => 1, i => 1,
6430                    s => 1, small => 1, strile => 1,                    s => 1, small => 1, strile => 1,
# Line 6051  sub _tree_construction_main ($) { Line 6432  sub _tree_construction_main ($) {
6432                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
6433            !!!cp ('t375');            !!!cp ('t375');
6434            push @$active_formatting_elements, $self->{open_elements}->[-1];            push @$active_formatting_elements, $self->{open_elements}->[-1];
6435              !!!nack ('t375.1');
6436          } elsif ($token->{tag_name} eq 'input') {          } elsif ($token->{tag_name} eq 'input') {
6437            !!!cp ('t388');            !!!cp ('t388');
6438            ## TODO: associate with $self->{form_element} if defined            ## TODO: associate with $self->{form_element} if defined
6439            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
6440              !!!ack ('t388.2');
6441          } elsif ({          } elsif ({
6442                    area => 1, basefont => 1, bgsound => 1, br => 1,                    area => 1, basefont => 1, bgsound => 1, br => 1,
6443                    embed => 1, img => 1, param => 1, spacer => 1, wbr => 1,                    embed => 1, img => 1, param => 1, spacer => 1, wbr => 1,
# Line 6062  sub _tree_construction_main ($) { Line 6445  sub _tree_construction_main ($) {
6445                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
6446            !!!cp ('t388.1');            !!!cp ('t388.1');
6447            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
6448              !!!ack ('t388.3');
6449          } elsif ($token->{tag_name} eq 'select') {          } elsif ($token->{tag_name} eq 'select') {
6450            ## TODO: associate with $self->{form_element} if defined            ## TODO: associate with $self->{form_element} if defined
6451                    
# Line 6074  sub _tree_construction_main ($) { Line 6458  sub _tree_construction_main ($) {
6458              !!!cp ('t400.2');              !!!cp ('t400.2');
6459              $self->{insertion_mode} = IN_SELECT_IM;              $self->{insertion_mode} = IN_SELECT_IM;
6460            }            }
6461              !!!nack ('t400.3');
6462          } else {          } else {
6463            !!!cp ('t402');            !!!nack ('t402');
6464          }          }
6465                    
6466          !!!next-token;          !!!next-token;
6467          redo B;          next B;
6468        }        }
6469      } elsif ($token->{type} == END_TAG_TOKEN) {      } elsif ($token->{type} == END_TAG_TOKEN) {
6470        if ($token->{tag_name} eq 'body') {        if ($token->{tag_name} eq 'body') {
# Line 6087  sub _tree_construction_main ($) { Line 6472  sub _tree_construction_main ($) {
6472          my $i;          my $i;
6473          INSCOPE: {          INSCOPE: {
6474            for (reverse @{$self->{open_elements}}) {            for (reverse @{$self->{open_elements}}) {
6475              if ($_->[1] eq 'body') {              if ($_->[1] & BODY_EL) {
6476                !!!cp ('t405');                !!!cp ('t405');
6477                $i = $_;                $i = $_;
6478                last INSCOPE;                last INSCOPE;
6479              } elsif ({              } elsif ($_->[1] & SCOPING_EL) {
                       applet => 1, table => 1, caption => 1, td => 1, th => 1,  
                       button => 1, marquee => 1, object => 1, html => 1,  
                      }->{$_->[1]}) {  
6480                !!!cp ('t405.1');                !!!cp ('t405.1');
6481                last;                last;
6482              }              }
# Line 6104  sub _tree_construction_main ($) { Line 6486  sub _tree_construction_main ($) {
6486                            value => $token->{tag_name}, token => $token);                            value => $token->{tag_name}, token => $token);
6487            ## NOTE: Ignore the token.            ## NOTE: Ignore the token.
6488            !!!next-token;            !!!next-token;
6489            redo B;            next B;
6490          } # INSCOPE          } # INSCOPE
6491    
6492          for (@{$self->{open_elements}}) {          for (@{$self->{open_elements}}) {
6493            unless ({            unless ($_->[1] & ALL_END_TAG_OPTIONAL_EL) {
                    dd => 1, dt => 1, li => 1, p => 1, td => 1,  
                    th => 1, tr => 1, body => 1, html => 1,  
                    tbody => 1, tfoot => 1, thead => 1,  
                   }->{$_->[1]}) {  
6494              !!!cp ('t403');              !!!cp ('t403');
6495              !!!parse-error (type => 'not closed:'.$_->[1], token => $token);              !!!parse-error (type => 'not closed',
6496                                value => $_->[0]->manakai_local_name,
6497                                token => $token);
6498              last;              last;
6499            } else {            } else {
6500              !!!cp ('t404');              !!!cp ('t404');
# Line 6123  sub _tree_construction_main ($) { Line 6503  sub _tree_construction_main ($) {
6503    
6504          $self->{insertion_mode} = AFTER_BODY_IM;          $self->{insertion_mode} = AFTER_BODY_IM;
6505          !!!next-token;          !!!next-token;
6506          redo B;          next B;
6507        } elsif ($token->{tag_name} eq 'html') {        } elsif ($token->{tag_name} eq 'html') {
6508          if (@{$self->{open_elements}} > 1 and $self->{open_elements}->[1]->[1] eq 'body') {          ## TODO: Update this code.  It seems that the code below is not
6509            ## up-to-date, though it has same effect as speced.
6510            if (@{$self->{open_elements}} > 1 and
6511                $self->{open_elements}->[1]->[1] & BODY_EL) {
6512            ## ISSUE: There is an issue in the spec.            ## ISSUE: There is an issue in the spec.
6513            if ($self->{open_elements}->[-1]->[1] ne 'body') {            unless ($self->{open_elements}->[-1]->[1] & BODY_EL) {
6514              !!!cp ('t406');              !!!cp ('t406');
6515              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[1]->[1], token => $token);              !!!parse-error (type => 'not closed',
6516                                value => $self->{open_elements}->[1]->[0]
6517                                    ->manakai_local_name,
6518                                token => $token);
6519            } else {            } else {
6520              !!!cp ('t407');              !!!cp ('t407');
6521            }            }
6522            $self->{insertion_mode} = AFTER_BODY_IM;            $self->{insertion_mode} = AFTER_BODY_IM;
6523            ## reprocess            ## reprocess
6524            redo B;            next B;
6525          } else {          } else {
6526            !!!cp ('t408');            !!!cp ('t408');
6527            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
6528            ## Ignore the token            ## Ignore the token
6529            !!!next-token;            !!!next-token;
6530            redo B;            next B;
6531          }          }
6532        } elsif ({        } elsif ({
6533                  address => 1, blockquote => 1, center => 1, dir => 1,                  address => 1, blockquote => 1, center => 1, dir => 1,
# Line 6154  sub _tree_construction_main ($) { Line 6540  sub _tree_construction_main ($) {
6540          my $i;          my $i;
6541          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6542            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
6543            if ($node->[1] eq $token->{tag_name}) {            if ($node->[0]->manakai_local_name eq $token->{tag_name}) {
6544              !!!cp ('t410');              !!!cp ('t410');
6545              $i = $_;              $i = $_;
6546              last INSCOPE;              last INSCOPE;
6547            } elsif ({            } elsif ($node->[1] & SCOPING_EL) {
                     applet => 1, table => 1, caption => 1, td => 1, th => 1,  
                     button => 1, marquee => 1, object => 1, html => 1,  
                    }->{$node->[1]}) {  
6548              !!!cp ('t411');              !!!cp ('t411');
6549              last INSCOPE;              last INSCOPE;
6550            }            }
# Line 6177  sub _tree_construction_main ($) { Line 6560  sub _tree_construction_main ($) {
6560                    dt => ($token->{tag_name} ne 'dt'),                    dt => ($token->{tag_name} ne 'dt'),
6561                    li => ($token->{tag_name} ne 'li'),                    li => ($token->{tag_name} ne 'li'),
6562                    p => 1,                    p => 1,
6563                   }->{$self->{open_elements}->[-1]->[1]}) {                   }->{$self->{open_elements}->[-1]->[0]->manakai_local_name}) {
6564              !!!cp ('t409');              !!!cp ('t409');
6565              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
6566            }            }
6567    
6568            ## Step 2.            ## Step 2.
6569            if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {            if ($self->{open_elements}->[-1]->[0]->manakai_local_name
6570                      ne $token->{tag_name}) {
6571              !!!cp ('t412');              !!!cp ('t412');
6572              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);              !!!parse-error (type => 'not closed',
6573                                value => $self->{open_elements}->[-1]->[0]
6574                                    ->manakai_local_name,
6575                                token => $token);
6576            } else {            } else {
6577              !!!cp ('t414');              !!!cp ('t414');
6578            }            }
# Line 6200  sub _tree_construction_main ($) { Line 6587  sub _tree_construction_main ($) {
6587                }->{$token->{tag_name}};                }->{$token->{tag_name}};
6588          }          }
6589          !!!next-token;          !!!next-token;
6590          redo B;          next B;
6591        } elsif ($token->{tag_name} eq 'form') {        } elsif ($token->{tag_name} eq 'form') {
6592          undef $self->{form_element};          undef $self->{form_element};
6593    
# Line 6208  sub _tree_construction_main ($) { Line 6595  sub _tree_construction_main ($) {
6595          my $i;          my $i;
6596          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6597            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
6598            if ($node->[1] eq $token->{tag_name}) {            if ($node->[1] & FORM_EL) {
6599              !!!cp ('t418');              !!!cp ('t418');
6600              $i = $_;              $i = $_;
6601              last INSCOPE;              last INSCOPE;
6602            } elsif ({            } elsif ($node->[1] & SCOPING_EL) {
                     applet => 1, table => 1, caption => 1, td => 1, th => 1,  
                     button => 1, marquee => 1, object => 1, html => 1,  
                    }->{$node->[1]}) {  
6603              !!!cp ('t419');              !!!cp ('t419');
6604              last INSCOPE;              last INSCOPE;
6605            }            }
# Line 6226  sub _tree_construction_main ($) { Line 6610  sub _tree_construction_main ($) {
6610            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
6611          } else {          } else {
6612            ## Step 1. generate implied end tags            ## Step 1. generate implied end tags
6613            while ({            while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
                   dd => 1, dt => 1, li => 1, p => 1,  
                  }->{$self->{open_elements}->[-1]->[1]}) {  
6614              !!!cp ('t417');              !!!cp ('t417');
6615              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
6616            }            }
6617                        
6618            ## Step 2.            ## Step 2.
6619            if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {            if ($self->{open_elements}->[-1]->[0]->manakai_local_name
6620                      ne $token->{tag_name}) {
6621              !!!cp ('t417.1');              !!!cp ('t417.1');
6622              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);              !!!parse-error (type => 'not closed',
6623                                value => $self->{open_elements}->[-1]->[0]
6624                                    ->manakai_local_name,
6625                                token => $token);
6626            } else {            } else {
6627              !!!cp ('t420');              !!!cp ('t420');
6628            }              }  
# Line 6246  sub _tree_construction_main ($) { Line 6632  sub _tree_construction_main ($) {
6632          }          }
6633    
6634          !!!next-token;          !!!next-token;
6635          redo B;          next B;
6636        } elsif ({        } elsif ({
6637                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,
6638                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 6254  sub _tree_construction_main ($) { Line 6640  sub _tree_construction_main ($) {
6640          my $i;          my $i;
6641          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6642            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
6643            if ({            if ($node->[1] & HEADING_EL) {
                h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,  
               }->{$node->[1]}) {  
6644              !!!cp ('t423');              !!!cp ('t423');
6645              $i = $_;              $i = $_;
6646              last INSCOPE;              last INSCOPE;
6647            } elsif ({            } elsif ($node->[1] & SCOPING_EL) {
                     applet => 1, table => 1, caption => 1, td => 1, th => 1,  
                     button => 1, marquee => 1, object => 1, html => 1,  
                    }->{$node->[1]}) {  
6648              !!!cp ('t424');              !!!cp ('t424');
6649              last INSCOPE;              last INSCOPE;
6650            }            }
# Line 6274  sub _tree_construction_main ($) { Line 6655  sub _tree_construction_main ($) {
6655            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
6656          } else {          } else {
6657            ## Step 1. generate implied end tags            ## Step 1. generate implied end tags
6658            while ({            while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
                   dd => 1, dt => 1, li => 1, p => 1,  
                  }->{$self->{open_elements}->[-1]->[1]}) {  
6659              !!!cp ('t422');              !!!cp ('t422');
6660              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
6661            }            }
6662                        
6663            ## Step 2.            ## Step 2.
6664            if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {            if ($self->{open_elements}->[-1]->[0]->manakai_local_name
6665                      ne $token->{tag_name}) {
6666              !!!cp ('t425');              !!!cp ('t425');
6667              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
6668            } else {            } else {
# Line 6294  sub _tree_construction_main ($) { Line 6674  sub _tree_construction_main ($) {
6674          }          }
6675                    
6676          !!!next-token;          !!!next-token;
6677          redo B;          next B;
6678        } elsif ($token->{tag_name} eq 'p') {        } elsif ($token->{tag_name} eq 'p') {
6679          ## has an element in scope          ## has an element in scope
6680          my $i;          my $i;
6681          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6682            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
6683            if ($node->[1] eq $token->{tag_name}) {            if ($node->[1] & P_EL) {
6684              !!!cp ('t410.1');              !!!cp ('t410.1');
6685              $i = $_;              $i = $_;
6686              last INSCOPE;              last INSCOPE;
6687            } elsif ({            } elsif ($node->[1] & SCOPING_EL) {
                     applet => 1, table => 1, caption => 1, td => 1, th => 1,  
                     button => 1, marquee => 1, object => 1, html => 1,  
                    }->{$node->[1]}) {  
6688              !!!cp ('t411.1');              !!!cp ('t411.1');
6689              last INSCOPE;              last INSCOPE;
6690            }            }
6691          } # INSCOPE          } # INSCOPE
6692    
6693          if (defined $i) {          if (defined $i) {
6694            if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {            if ($self->{open_elements}->[-1]->[0]->manakai_local_name
6695                      ne $token->{tag_name}) {
6696              !!!cp ('t412.1');              !!!cp ('t412.1');
6697              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);              !!!parse-error (type => 'not closed',
6698                                value => $self->{open_elements}->[-1]->[0]
6699                                    ->manakai_local_name,
6700                                token => $token);
6701            } else {            } else {
6702              !!!cp ('t414.1');              !!!cp ('t414.1');
6703            }            }
# Line 6329  sub _tree_construction_main ($) { Line 6710  sub _tree_construction_main ($) {
6710            !!!cp ('t415.1');            !!!cp ('t415.1');
6711            ## As if <p>, then reprocess the current token            ## As if <p>, then reprocess the current token
6712            my $el;            my $el;
6713            !!!create-element ($el, 'p',, $token);            !!!create-element ($el, $HTML_NS, 'p',, $token);
6714            $insert->($el);            $insert->($el);
6715            ## NOTE: Not inserted into |$self->{open_elements}|.            ## NOTE: Not inserted into |$self->{open_elements}|.
6716          }          }
6717    
6718          !!!next-token;          !!!next-token;
6719          redo B;          next B;
6720        } elsif ({        } elsif ({
6721                  a => 1,                  a => 1,
6722                  b => 1, big => 1, em => 1, font => 1, i => 1,                  b => 1, big => 1, em => 1, font => 1, i => 1,
# Line 6344  sub _tree_construction_main ($) { Line 6725  sub _tree_construction_main ($) {
6725                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
6726          !!!cp ('t427');          !!!cp ('t427');
6727          $formatting_end_tag->($token);          $formatting_end_tag->($token);
6728          redo B;          next B;
6729        } elsif ($token->{tag_name} eq 'br') {        } elsif ($token->{tag_name} eq 'br') {
6730          !!!cp ('t428');          !!!cp ('t428');
6731          !!!parse-error (type => 'unmatched end tag:br', token => $token);          !!!parse-error (type => 'unmatched end tag:br', token => $token);
# Line 6353  sub _tree_construction_main ($) { Line 6734  sub _tree_construction_main ($) {
6734          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
6735                    
6736          my $el;          my $el;
6737          !!!create-element ($el, 'br',, $token);          !!!create-element ($el, $HTML_NS, 'br',, $token);
6738          $insert->($el);          $insert->($el);
6739                    
6740          ## Ignore the token.          ## Ignore the token.
6741          !!!next-token;          !!!next-token;
6742          redo B;          next B;
6743        } elsif ({        } elsif ({
6744                  caption => 1, col => 1, colgroup => 1, frame => 1,                  caption => 1, col => 1, colgroup => 1, frame => 1,
6745                  frameset => 1, head => 1, option => 1, optgroup => 1,                  frameset => 1, head => 1, option => 1, optgroup => 1,
# Line 6375  sub _tree_construction_main ($) { Line 6756  sub _tree_construction_main ($) {
6756          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
6757          ## Ignore the token          ## Ignore the token
6758          !!!next-token;          !!!next-token;
6759          redo B;          next B;
6760                    
6761          ## ISSUE: Issue on HTML5 new elements in spec          ## ISSUE: Issue on HTML5 new elements in spec
6762                    
# Line 6386  sub _tree_construction_main ($) { Line 6767  sub _tree_construction_main ($) {
6767    
6768          ## Step 2          ## Step 2
6769          S2: {          S2: {
6770            if ($node->[1] eq $token->{tag_name}) {            if ($node->[0]->manakai_local_name eq $token->{tag_name}) {
6771              ## Step 1              ## Step 1
6772              ## generate implied end tags              ## generate implied end tags
6773              while ({              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
                     dd => 1, dt => 1, li => 1, p => 1,  
                    }->{$self->{open_elements}->[-1]->[1]}) {  
6774                !!!cp ('t430');                !!!cp ('t430');
6775                ## ISSUE: Can this case be reached?                ## ISSUE: Can this case be reached?
6776                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
6777              }              }
6778                    
6779              ## Step 2              ## Step 2
6780              if ($token->{tag_name} ne $self->{open_elements}->[-1]->[1]) {              if ($self->{open_elements}->[-1]->[0]->manakai_local_name
6781                        ne $token->{tag_name}) {
6782                !!!cp ('t431');                !!!cp ('t431');
6783                ## NOTE: <x><y></x>                ## NOTE: <x><y></x>
6784                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1], token => $token);                !!!parse-error (type => 'not closed',
6785                                  value => $self->{open_elements}->[-1]->[0]
6786                                      ->manakai_local_name,
6787                                  token => $token);
6788              } else {              } else {
6789                !!!cp ('t432');                !!!cp ('t432');
6790              }              }
# Line 6413  sub _tree_construction_main ($) { Line 6796  sub _tree_construction_main ($) {
6796              last S2;              last S2;
6797            } else {            } else {
6798              ## Step 3              ## Step 3
6799              if (not $formatting_category->{$node->[1]} and              if (not ($node->[1] & FORMATTING_EL) and
6800                  #not $phrasing_category->{$node->[1]} and                  #not $phrasing_category->{$node->[1]} and
6801                  ($special_category->{$node->[1]} or                  ($node->[1] & SPECIAL_EL or
6802                   $scoping_category->{$node->[1]})) {                   $node->[1] & SCOPING_EL)) {
6803                !!!cp ('t433');                !!!cp ('t433');
6804                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
6805                ## Ignore the token                ## Ignore the token
# Line 6434  sub _tree_construction_main ($) { Line 6817  sub _tree_construction_main ($) {
6817            ## Step 5;            ## Step 5;
6818            redo S2;            redo S2;
6819          } # S2          } # S2
6820          redo B;          next B;
6821        }        }
6822      }      }
6823      redo B;      next B;
6824      } continue { # B
6825        if ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM) {
6826          ## NOTE: The code below is executed in cases where it does not have
6827          ## to be, but it it is harmless even in those cases.
6828          ## has an element in scope
6829          INSCOPE: {
6830            for (reverse 0..$#{$self->{open_elements}}) {
6831              my $node = $self->{open_elements}->[$_];
6832              if ($node->[1] & FOREIGN_EL) {
6833                last INSCOPE;
6834              } elsif ($node->[1] & SCOPING_EL) {
6835                last;
6836              }
6837            }
6838            
6839            ## NOTE: No foreign element in scope.
6840            $self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM;
6841          } # INSCOPE
6842        }
6843    } # B    } # B
6844    
6845    ## Stop parsing # MUST    ## Stop parsing # MUST
# Line 6554  sub set_inner_html ($$$) { Line 6956  sub set_inner_html ($$$) {
6956          unless defined $p->{content_model};          unless defined $p->{content_model};
6957          ## ISSUE: What is "the name of the element"? local name?          ## ISSUE: What is "the name of the element"? local name?
6958    
6959      $p->{inner_html_node} = [$node, $node_ln];      $p->{inner_html_node} = [$node, $el_category->{$node_ln}];
6960          ## TODO: Foreign element OK?
6961    
6962      ## Step 3      ## Step 3
6963      my $root = $doc->create_element_ns      my $root = $doc->create_element_ns
# Line 6564  sub set_inner_html ($$$) { Line 6967  sub set_inner_html ($$$) {
6967      $doc->append_child ($root);      $doc->append_child ($root);
6968    
6969      ## Step 5 # MUST      ## Step 5 # MUST
6970      push @{$p->{open_elements}}, [$root, 'html'];      push @{$p->{open_elements}}, [$root, $el_category->{html}];
6971    
6972      undef $p->{head_element};      undef $p->{head_element};
6973    

Legend:
Removed from v.1.121  
changed lines
  Added in v.1.127

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24