/[suikacvs]/markup/html/whatpm/Whatpm/SWML/Parser.pm
Suika

Contents of /markup/html/whatpm/Whatpm/SWML/Parser.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (hide annotations) (download)
Fri Nov 7 12:35:39 2008 UTC (16 years ago) by wakaba
Branch: MAIN
Changes since 1.5: +56 -42 lines
++ whatpm/t/ChangeLog	7 Nov 2008 12:35:08 -0000
	* SWML-Parser.t: New test data files added.

2008-11-07  Wakaba  <wakaba@suika.fam.cx>

++ whatpm/t/swml/ChangeLog	7 Nov 2008 12:35:27 -0000
	* blocks-1.dat: Test result updated.

	* inlines-1.dat, forms-specific.dat-1, forms-generic-1.dat,
	tables-1.dat: New files.

2008-11-07  Wakaba  <wakaba@suika.fam.cx>

++ whatpm/Whatpm/SWML/ChangeLog	7 Nov 2008 12:34:42 -0000
	* Parser.pm: More bug fixes, both impl bugs and spec bugs, again.

2008-11-07  Wakaba  <wakaba@suika.fam.cx>

1 wakaba 1.1 package Whatpm::SWML::Parser;
2     use strict;
3    
4 wakaba 1.2 sub AA_NS () { q<http://pc5.2ch.net/test/read.cgi/hp/1096723178/aavocab#> }
5     sub HTML_NS () { q<http://www.w3.org/1999/xhtml> }
6     sub SW09_NS () { q<urn:x-suika-fam-cx:markup:suikawiki:0:9:> }
7     sub SW10_NS () { q<urn:x-suika-fam-cx:markup:suikawiki:0:10:> }
8     sub XML_NS () { q<http://www.w3.org/XML/1998/namespace> }
9    
10     sub IN_SECTION_IM () { 0 }
11     sub IN_TABLE_ROW_IM () { 1 }
12     sub IN_PARAGRAPH_IM () { 2 }
13    
14     sub BLOCK_START_TAG_TOKEN () { 1 }
15     sub BLOCK_END_TAG_TOKEN () { 2 }
16     sub CHARACTER_TOKEN () { 3 }
17     sub COMMENT_PARAGRAPH_START_TOKEN () { 4 }
18     sub EDITORIAL_NOTE_START_TOKEN () { 5 }
19     sub ELEMENT_TOKEN () { 6 }
20     sub EMPHASIS_TOKEN () { 7 }
21     sub EMPTY_LINE_TOKEN () { 8 }
22     sub END_OF_FILE_TOKEN () { 9 }
23     sub FORM_TOKEN () { 10 }
24     sub HEADING_START_TOKEN () { 11 }
25     sub HEADING_END_TOKEN () { 12 }
26     sub INLINE_START_TAG_TOKEN () { 13 }
27     sub INLINE_MIDDLE_TAG_TOKEN () { 14 }
28     sub INLINE_END_TAG_TOKEN () { 15 }
29     sub LABELED_LIST_START_TOKEN () { 16 }
30     sub LABELED_LIST_MIDDLE_TOKEN () { 17 }
31     sub LIST_START_TOKEN () { 18 }
32     sub PREFORMATTED_START_TOKEN () { 19 }
33     sub PREFORMATTED_END_TOKEN () { 20 }
34     sub QUOTATION_START_TOKEN () { 21 }
35     sub STRONG_TOKEN () { 22 }
36     sub TABLE_ROW_START_TOKEN () { 23 }
37     sub TABLE_ROW_END_TOKEN () { 24 }
38     sub TABLE_CELL_START_TOKEN () { 25 }
39     sub TABLE_CELL_END_TOKEN () { 26 }
40     sub TABLE_COLSPAN_CELL_TOKEN () { 27 }
41 wakaba 1.1
42     sub new ($) {
43     my $self = bless {
44     }, $_[0];
45     return $self;
46     } # new
47    
48     sub parse_char_string ($$$;$) {
49     my $self = shift;
50     my @s = split /\x0D\x0A?|\x0A/, ref $_[0] ? ${$_[0]} : $_[0], -1;
51    
52     my $doc = $_[1];
53 wakaba 1.4 @{$doc->child_nodes} = ();
54     my $html_el = $doc->create_element_ns (HTML_NS, [undef, 'html']);
55     $doc->append_child ($html_el);
56     $html_el->set_attribute_ns
57     ('http://www.w3.org/2000/xmlns/', [undef, 'xmlns'] => HTML_NS);
58     my $head_el = $doc->create_element_ns (HTML_NS, [undef, 'head']);
59     $html_el->append_child ($head_el);
60     my $body_el = $doc->create_element_ns (HTML_NS, [undef, 'body']);
61     $html_el->append_child ($body_el);
62     for ($doc, $html_el, $head_el, $body_el) {
63 wakaba 1.1 $_->set_user_data (manakai_source_line => 1);
64     $_->set_user_data (manakai_source_column => 1);
65     }
66    
67     my $_onerror = $_[2] || sub {
68     my %opt = @_;
69     my $r = 'Line ' . $opt{line} . ' column ' . $opt{column} . ': ';
70    
71     if ($opt{token}) {
72     $r .= 'Token ' . (defined $opt{token}->{value}
73     ? $opt{token}->{value} : $opt{token}->{type}) . ': ';
74     }
75    
76     $r .= $opt{type} . ';' . $opt{level};
77    
78     warn $r . "\n";
79     }; # $_onerror
80    
81     my $line = 0;
82     my $column = 0;
83     my $token;
84     my @nt;
85    
86     my $onerror = sub {
87     $_onerror->(line => $line, column => $column, token => $token, @_);
88     }; # $onerror
89    
90     my $continuous_line;
91    
92     my $tokenize_text = sub {
93     my $s = shift; # ref
94    
95 wakaba 1.6 my $nest_level = 0;
96    
97 wakaba 1.1 if ($$s =~ s/^\[([0-9]+)\]//) {
98     push @nt, {type => ELEMENT_TOKEN,
99 wakaba 1.2 local_name => 'anchor-end', namespace => SW09_NS,
100 wakaba 1.1 anchor => $1, content => '[' . $1 . ']'};
101     $column += $+[0] - $-[0];
102     }
103    
104     while (length $$s) {
105 wakaba 1.2 if ($$s =~ s/^\[\[#([a-z-]+)//) {
106 wakaba 1.1 $column = $+[0] - $-[0];
107     my $t = {type => FORM_TOKEN, name => $1,
108     line => $line, column => $column};
109     if ($$s =~ s/^\(([^()\\]*)\)//) {
110     $t->{id} = $1;
111     $column += $+[0] - $-[0];
112     }
113     my @param;
114 wakaba 1.2 while ($$s =~ s/^://) {
115 wakaba 1.1 if ($$s =~ s/^'((?>[^'\\]|\\.)*)//) {
116     $column += 1 + $+[0] - $-[0];
117     my $n = $1;
118     $n =~ tr/\\//d;
119     push @param, $n;
120     $column++ if $$s =~ s/\A\\\z//;
121     $column++ if $$s =~ s/^'//;
122 wakaba 1.6 } elsif ($$s =~ s/^([^':\]][^:\]]*)//) {
123 wakaba 1.1 $column += 1 + $+[0] - $-[0];
124     push @param, $1;
125     }
126     }
127     $t->{parameters} = \@param;
128     $column += 2 if $$s =~ s/^\]\]//;
129     push @nt, $t;
130     } elsif ($$s =~ s/^\[\[//) {
131     push @nt, {type => INLINE_START_TAG_TOKEN};
132     $column += 2;
133 wakaba 1.6 $nest_level++;
134     } elsif ($$s =~ s/^\[([A-Z]+)(?>\(([^()\\]*)\))?(?>\@([0-9A-Za-z-]*))?\[//) {
135 wakaba 1.1 push @nt, {type => INLINE_START_TAG_TOKEN,
136     tag_name => $1, classes => $2, language => $3,
137     line => $line, column => $column};
138     $column += $+[0] - $-[0];
139 wakaba 1.6 $nest_level++;
140 wakaba 1.1 } elsif ($$s =~ s/^\]\]//) {
141     push @nt, {type => INLINE_END_TAG_TOKEN,
142     line => $line, column => $column};
143     $column += 2;
144 wakaba 1.6 $nest_level-- if $nest_level > 0;
145 wakaba 1.1 } elsif ($$s =~ s/^(\]?)<([0-9A-Za-z%+._-]+)://) {
146     my $t = {type => $1 ? INLINE_END_TAG_TOKEN : ELEMENT_TOKEN,
147     res_scheme => $2, res_parameter => '',
148     line => $line, column => $column};
149     $column += $+[0] - $-[0];
150    
151     while (length $$s) {
152     if ($$s =~ s/^([^>"]+)//) {
153     $t->{res_parameter} .= $1;
154     $column += $+[0] - $-[0];
155     } elsif ($$s =~ s/^("(?>[^"\\]|\\.)*)//) {
156     $t->{res_parameter} .= $1;
157     $column += $+[0] - $-[0];
158     $column++ if $$s =~ s/\A\\\z//;
159 wakaba 1.6 $t->{res_parameter} .= '"' and $column++ if $$s =~ s/^"//;
160 wakaba 1.1 } else {
161     last;
162     }
163     }
164    
165     $column++ if $$s =~ s/^>//;
166    
167     $t->{content} = $t->{res_scheme} . ':' . $t->{res_parameter};
168     if ($t->{res_scheme} !~ /[A-Z]/) {
169     $t->{res_parameter} = $t->{content};
170     $t->{res_scheme} = 'URI';
171     }
172    
173     if ($t->{type} == INLINE_END_TAG_TOKEN) {
174     $column++ if $$s =~ s/^\]//;
175 wakaba 1.6 $nest_level-- if $nest_level > 0;
176 wakaba 1.1 } else {
177     $t->{local_name} = 'anchor-external';
178 wakaba 1.2 $t->{namespace} = SW09_NS;
179 wakaba 1.1 }
180     push @nt, $t;
181     } elsif ($$s =~ s/^\]>>([0-9]+)\]//) {
182     push @nt, {type => INLINE_END_TAG_TOKEN,
183     anchor => $1,
184     line => $line, column => $column};
185     $column += $+[0] - $-[0];
186 wakaba 1.6 $nest_level-- if $nest_level > 0;
187     } elsif ($nest_level > 0 and
188     $$s =~ s/^\][\x09\x20]*(?>\@([0-9a-zA-Z-]*))?\[//) {
189 wakaba 1.1 push @nt, {type => INLINE_MIDDLE_TAG_TOKEN,
190     language => $1,
191     line => $line, column => $column};
192     $column += $+[0] - $-[0];
193 wakaba 1.6 } elsif ($$s =~ s/^''('?)//) {
194 wakaba 1.1 push @nt, {type => $1 ? STRONG_TOKEN : EMPHASIS_TOKEN,
195     line => $line, column => $column};
196     $column += $+[0] - $-[0];
197     } elsif ($$s =~ s/^>>([0-9]+)//) {
198     push @nt, {type => ELEMENT_TOKEN,
199 wakaba 1.2 local_name => 'anchor-internal', namespace => SW09_NS,
200 wakaba 1.6 anchor => $1, content => '>>' . $1,
201 wakaba 1.1 line => $line, column => $column};
202     $column += $+[0] - $-[0];
203     } elsif ($$s =~ s/^__&&//) {
204     if ($$s =~ s/^(.+?)&&__//) {
205     push @nt, {type => ELEMENT_TOKEN,
206 wakaba 1.2 local_name => 'replace', namespace => SW09_NS,
207 wakaba 1.1 by => $1,
208     line => $line, column => $column};
209     $column += 4 + $+[0] - $-[0];
210     } else {
211     push @nt, {type => CHARACTER_TOKEN,
212     data => '__&&',
213     line => $line, column => $column};
214     $column += 4;
215     }
216 wakaba 1.5 } elsif ($$s =~ s/^([^<>\[\]'_]+)//) {
217 wakaba 1.1 push @nt, {type => CHARACTER_TOKEN, data => $1,
218     line => $line, column => $column};
219     $column += $+[0] - $-[0];
220     } else {
221     push @nt, {type => CHARACTER_TOKEN, data => substr ($$s, 0, 1),
222     line => $line, column => $column};
223     substr ($$s, 0, 1) = '';
224     $column++;
225     }
226     }
227     }; # $tokenize_text
228    
229     my $get_next_token = sub {
230     if (@nt) {
231     return shift @nt;
232     }
233    
234     if (not @s) {
235     return {type => END_OF_FILE_TOKEN, line => $line, column => $column};
236     }
237    
238     my $s = shift @s;
239     ($line, $column) = ($line + 1, 1);
240     if ($s eq '') {
241     undef $continuous_line;
242     return {type => EMPTY_LINE_TOKEN, line => $line, column => $column};
243     } elsif ($s =~ /^[\x09\x20]/) {
244     push @nt, {type => PREFORMATTED_START_TOKEN,
245     line => $line, column => $column};
246     $tokenize_text->(\$s);
247     while (@s) {
248     my $s = shift @s;
249     ($line, $column) = ($line + 1, 1);
250     if ($s eq '') {
251     push @nt, {type => PREFORMATTED_END_TOKEN,
252     line => $line, column => $column};
253     unshift @s, $s;
254     $line--;
255     last;
256     } elsif ($s =~ /\A\](INS|DEL)\][\x09\x20]*\z/) {
257     push @nt, {type => PREFORMATTED_END_TOKEN,
258     line => $line, column => $column};
259     push @nt, {type => BLOCK_END_TAG_TOKEN, tag_name => $1,
260     line => $line, column => $column};
261     last;
262     } else {
263     push @nt, {type => CHARACTER_TOKEN, data => "\x0A",
264     line => $line, column => $column};
265     $tokenize_text->(\$s);
266     }
267     }
268     return shift @nt;
269 wakaba 1.3 } elsif ($s =~ s/^(\*+)[\x09\x20]*//) {
270 wakaba 1.1 push @nt, {type => HEADING_START_TOKEN, depth => length $1,
271     line => $line, column => $column};
272     $column += $+[0] - $-[0];
273     $tokenize_text->(\$s);
274     push @nt, {type => HEADING_END_TOKEN,
275     line => $line, column => $column};
276     undef $continuous_line;
277     return shift @nt;
278 wakaba 1.3 } elsif ($s =~ s/^([-=]+)[\x09\x20]*//) {
279 wakaba 1.1 push @nt, {type => LIST_START_TOKEN, depth => $1,
280     line => $line, column => $column};
281     $column += $+[0] - $-[0];
282     $tokenize_text->(\$s);
283     $continuous_line = 1;
284     return shift @nt;
285     } elsif ($s =~ s/^:([^:]*)//) {
286     my $name = $1;
287     if ($s eq '') {
288     push @nt, {type => CHARACTER_TOKEN, data => ':',
289     line => $line, column => $column};
290     $column++;
291     $tokenize_text->(\$name);
292     } else {
293     my $real_column = $column + 1 + length $name;
294     push @nt, {type => LABELED_LIST_START_TOKEN,
295     line => $line, column => $column};
296     $name =~ s/\A[\x09\x20]*//;
297     $column += 1 + $+[0] - $-[0];
298     $name =~ s/[\x09\x20]+\z//;
299 wakaba 1.5 $tokenize_text->(\$name);
300 wakaba 1.1 $column = $real_column;
301     push @nt, {type => LABELED_LIST_MIDDLE_TOKEN,
302     line => $line, column => $column};
303 wakaba 1.2 $column += $+[0] - $-[0] if $s =~ s/^:[\x09\x20]*//;
304 wakaba 1.1 $tokenize_text->(\$s);
305     }
306     $continuous_line = 1;
307     return shift @nt;
308     } elsif ($s =~ s/^(>+)//) {
309     my $depth = length $1;
310     if ($depth == 2 and $s =~ /^[0-9]/) {
311     push @nt, {type => CHARACTER_TOKEN, data => "\x0A",
312     line => $line, column => $column}
313     if $continuous_line;
314     $s = '>>' . $s;
315     $tokenize_text->(\$s);
316 wakaba 1.5 $continuous_line = 1;
317 wakaba 1.1 } else {
318     push @nt, {type => QUOTATION_START_TOKEN, depth => $depth,
319     line => $line, column => $column};
320     $column += $depth;
321     $column += $+[0] - $-[0] if $s =~ s/^[\x09\x20]+//;
322     if ($s =~ s/^\@\@[\x09\x20]*//) {
323     push @nt, {type => EDITORIAL_NOTE_START_TOKEN,
324     line => $line, column => $column};
325     $column += $+[0] - $-[0];
326 wakaba 1.5 $continuous_line = 1;
327 wakaba 1.1 } elsif ($s =~ s/^;;[\x09\x20]*//) {
328     push @nt, {type => COMMENT_PARAGRAPH_START_TOKEN,
329     line => $line, column => $column};
330     $column += $+[0] - $-[0];
331 wakaba 1.5 $continuous_line = 1;
332     } elsif (length $s) {
333     $continuous_line = 1;
334     } else {
335     $continuous_line = 0;
336 wakaba 1.1 }
337     $tokenize_text->(\$s);
338     }
339     return shift @nt;
340     } elsif ($s =~ /\A\[(INS|DEL)(?>\(([^()\\]*)\))?\[[\x09\x20]*\z/) {
341     undef $continuous_line;
342     return {type => BLOCK_START_TAG_TOKEN, tag_name => $1,
343     classes => $2,
344     line => $line, column => $column};
345     } elsif ($s =~ /\A\[PRE(?>\(([^()\\]*)\))?\[[\x09\x20]*\z/) {
346     undef $continuous_line;
347     push @nt, {type => BLOCK_START_TAG_TOKEN, tag_name => 'PRE',
348     classes => $1,
349     line => $line, column => $column};
350     while (@s) {
351     my $s = shift @s;
352     ($line, $column) = ($line + 1, 1);
353     if ($s =~ /\A\]PRE\][\x09\x20]*\z/) {
354     push @nt, {type => BLOCK_END_TAG_TOKEN, tag_name => 'PRE',
355     line => $line, column => $column};
356     undef $continuous_line;
357 wakaba 1.2 last;
358 wakaba 1.1 } else {
359     push @nt, {type => CHARACTER_TOKEN, data => "\x0A",
360     line => $line, column => $column}
361     if $continuous_line;
362     $tokenize_text->(\$s);
363     $continuous_line = 1;
364     }
365     }
366     return shift @nt;
367     } elsif ($s =~ s/^\@\@[\x09\x20]*//) {
368     push @nt, {type => EDITORIAL_NOTE_START_TOKEN,
369     line => $line, column => $column};
370     $column += $+[0] - $-[0];
371     $tokenize_text->(\$s);
372     $continuous_line = 1;
373     return shift @nt;
374     } elsif ($s =~ s/^;;[\x09\x20]*//) {
375     push @nt, {type => COMMENT_PARAGRAPH_START_TOKEN,
376     line => $line, column => $column};
377     $column += $+[0] - $-[0];
378     $tokenize_text->(\$s);
379 wakaba 1.5 $continuous_line = 1;
380 wakaba 1.1 return shift @nt;
381     } elsif ($s =~ /\A\](INS|DEL)\][\x09\x20]*\z/) {
382     $continuous_line = 1;
383     return {type => BLOCK_END_TAG_TOKEN, tag_name => $1,
384     line => $line, column => $column};
385     } elsif ($s =~ /^,/) {
386     push @nt, {type => TABLE_ROW_START_TOKEN,
387     line => $line, column => $column};
388     while ($s =~ s/^,[\x09\x20]*//) {
389     $column += $+[0] - $-[0];
390     my $cell;
391     my $cell_quoted;
392     my $column_quoted = $column;
393     my $column_cell = $column;
394     if ($s =~ s/^"//) {
395     $s =~ s/^((?>[^"\\]|\\.)*)//;
396     $cell_quoted = $1;
397     $column += 1 + length $cell_quoted;
398     $cell_quoted =~ tr/\\//d;
399     $column++ if $s =~ s/\A\\\z//;
400     $column++ if $s =~ s/^"//;
401     }
402     if ($s =~ s/^([^,]+)//) {
403     $cell = $1;
404     $column += length $cell;
405     $cell =~ s/[\x09\x20]+\z//;
406     }
407     if (not defined $cell_quoted and defined $cell and
408     $cell eq '==') {
409     push @nt, {type => TABLE_COLSPAN_CELL_TOKEN,
410     line => $line, column => $column_cell};
411     } else {
412     push @nt, {type => TABLE_CELL_START_TOKEN,
413     line => $line,
414     column => defined $column_quoted ? $column_quoted: $column_cell};
415     my $real_column = $column;
416     $column = $column_quoted + 1;
417     $tokenize_text->(\$cell_quoted) if defined $cell_quoted;
418     ## NOTE: When a quoted-pair is used, column numbers
419     ## reported in this $tokenize_text call might be wrong.
420     $column = $column_cell;
421     $tokenize_text->(\$cell) if defined $cell;
422     $column = $column_quoted;
423     push @nt, {type => TABLE_CELL_END_TOKEN,
424     line => $line,
425     column => $column};
426     }
427     }
428     push @nt, {type => TABLE_ROW_END_TOKEN,
429     line => $line, column => $column};
430     undef $continuous_line;
431     return shift @nt;
432     } elsif ($s eq '__IMAGE__') {
433 wakaba 1.4 my $image = $doc->create_element_ns (SW09_NS, [undef, 'image']);
434 wakaba 1.2 $image->set_user_data (manakai_source_line => $line);
435     $image->set_user_data (manakai_source_column => 1);
436 wakaba 1.1 $image->text_content (join "\x0A", $s, @s);
437     ($line, $column) = ($line + @s, 1);
438     @s = ();
439     $doc->document_element->append_child ($image);
440     return {type => END_OF_FILE_TOKEN,
441     line => $line, column => $column};
442     } else {
443     push @nt, {type => CHARACTER_TOKEN, data => "\x0A",
444     line => $line, column => $column} if $continuous_line;
445     $tokenize_text->(\$s);
446     $continuous_line = 1;
447     return shift @nt;
448     }
449 wakaba 1.3 }; # $get_next_token
450 wakaba 1.1
451     ## NOTE: The "initial" mode.
452 wakaba 1.5 if (@s and $s[0] =~ s/^#\?//) {
453 wakaba 1.1 ## NOTE: "Parse a magic line".
454    
455     my $s = shift @s;
456 wakaba 1.2 if ($s =~ s/^([^\x09\x20]+)//) {
457     $column += $+[0] - $-[0];
458     my ($name, $version) = split m#/#, $1, 2;
459     my $el = $doc->document_element;
460 wakaba 1.4 $el->set_attribute_ns (SW09_NS, ['sw', 'Name'] => $name);
461     $el->set_attribute_ns (SW09_NS, ['sw', 'Version'] => $version)
462 wakaba 1.2 if defined $version;
463     }
464 wakaba 1.1
465 wakaba 1.2 while (length $s) {
466 wakaba 1.5 $column += $+[0] - $-[0] and next if $s =~ s/^[\x09\x20]+//;
467 wakaba 1.2 my $name = '';
468     if ($s =~ s/^([^=]*)=//) {
469     $name = $1;
470     $column += length $name + 1;
471     }
472 wakaba 1.4 my $param = $doc->create_element_ns (SW09_NS, [undef, 'parameter']);
473     $param->set_attribute_ns (undef, [undef, 'name'] => $name);
474 wakaba 1.2 $param->set_user_data (manakai_source_line => $line);
475     $param->set_user_data (manakai_source_column => $column);
476 wakaba 1.4 $head_el->append_child ($param);
477 wakaba 1.2
478     $column++ if $s =~ s/^"//;
479 wakaba 1.5 if ($s =~ s/^([^"]*)//) {
480 wakaba 1.2 my $values = $1;
481     $column += length $values;
482     $values =~ tr/\\//d;
483 wakaba 1.5 my @values = split /,/, $values, -1;
484     push @values, '' unless length $values;
485     for (@values) {
486 wakaba 1.4 my $value = $doc->create_element_ns (SW09_NS, [undef, 'value']);
487 wakaba 1.2 $value->text_content ($_);
488     $value->set_user_data (manakai_source_line => $line);
489     $value->set_user_data (manakai_source_column => $column);
490     $param->append_child ($value);
491     }
492     }
493     $column++ if $s =~ s/^"//;
494     }
495 wakaba 1.1
496     $line = 2;
497 wakaba 1.2 $column = 1;
498 wakaba 1.1 }
499    
500     ## NOTE: Switched to the "body" mode.
501 wakaba 1.2
502 wakaba 1.4 my $oe = [{node => $body_el,
503 wakaba 1.2 section_depth => 0,
504     quotation_depth => 0,
505     list_depth => 0}];
506     my $structural_elements = {
507     body => 1, section => 1, insert => 1, delete => 1, blockquote => 1,
508     h1 => 1, ul => 1, ol => 1, dl => 1, li => 1, dt => 1, dd => 1,
509     table => 1, tbody => 1, tr => 1, td => 1, p => 1, 'comment-p' => 1,
510     ed => 1, pre => 1,
511     };
512    
513     my $im = IN_SECTION_IM;
514 wakaba 1.3 $token = $get_next_token->();
515 wakaba 1.1
516 wakaba 1.2 A: {
517     if ($im == IN_PARAGRAPH_IM) {
518     if ($token->{type} == CHARACTER_TOKEN) {
519     $oe->[-1]->{node}->manakai_append_text ($token->{data});
520 wakaba 1.3 $token = $get_next_token->();
521 wakaba 1.2 redo A;
522     } elsif ($token->{type} == INLINE_START_TAG_TOKEN) {
523     if (not defined $token->{tag_name}) {
524 wakaba 1.4 my $el = $doc->create_element_ns (SW09_NS, [undef, 'anchor']);
525 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
526     push @$oe, {%{$oe->[-1]}, node => $el};
527     $el->set_user_data (manakai_source_line => $token->{line});
528     $el->set_user_data (manakai_source_column => $token->{column});
529    
530 wakaba 1.3 $token = $get_next_token->();
531 wakaba 1.2 redo A;
532     } else {
533     my $type = {
534     AA => [AA_NS, 'aa'],
535     ABBR => [HTML_NS, 'abbr'],
536     CITE => [HTML_NS, 'cite'],
537     CODE => [HTML_NS, 'code'],
538     CSECTION => [SW10_NS, 'csection'],
539     DEL => [HTML_NS, 'del'],
540     DFN => [HTML_NS, 'dfn'],
541     INS => [HTML_NS, 'ins'],
542     KBD => [HTML_NS, 'kbd'],
543     KEY => [SW10_NS, 'key'],
544     Q => [HTML_NS, 'q'],
545     QN => [SW10_NS, 'qn'],
546     RUBY => [HTML_NS, 'ruby'],
547     RUBYB => [HTML_NS, 'rubyb'],
548     SAMP => [HTML_NS, 'samp'],
549     SPAN => [HTML_NS, 'span'],
550     SRC => [SW10_NS, 'src'],
551     SUB => [HTML_NS, 'sub'],
552     SUP => [HTML_NS, 'sup'],
553     TIME => [HTML_NS, 'time'],
554     VAR => [HTML_NS, 'var'],
555     WEAK => [SW09_NS, 'weak'],
556     }->{$token->{tag_name}} || [SW10_NS, $token->{tag_name}];
557 wakaba 1.5 my $el = $doc->create_element_ns ($type->[0], [undef, $type->[1]]);
558 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
559     push @$oe, {%{$oe->[-1]}, node => $el};
560     $el->set_user_data (manakai_source_line => $token->{line});
561     $el->set_user_data (manakai_source_column => $token->{column});
562    
563 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'class'] => $token->{classes})
564 wakaba 1.2 if defined $token->{classes};
565 wakaba 1.4 $el->set_attribute_ns (XML_NS, ['xml', 'lang'] => $token->{language})
566 wakaba 1.2 if defined $token->{language};
567    
568 wakaba 1.3 $token = $get_next_token->();
569 wakaba 1.2 redo A;
570     }
571     } elsif ($token->{type} == INLINE_MIDDLE_TAG_TOKEN) {
572     my ($ns, $ln, $pop) = @{{
573 wakaba 1.3 rt => [HTML_NS, 'rt', 1],
574 wakaba 1.2 title => [SW10_NS, 'attrvalue', 1],
575     nsuri => [SW10_NS, 'attrvalue', 1],
576     qn => [SW10_NS, 'nsuri'],
577     ruby => [HTML_NS, 'rt'],
578     rubyb => [HTML_NS, 'rt'],
579     }->{$oe->[-1]->{node}->manakai_local_name} || [SW10_NS, 'title']};
580     pop @$oe if $pop;
581    
582 wakaba 1.4 my $el = $doc->create_element_ns ($ns, [undef, $ln]);
583 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
584     push @$oe, {%{$oe->[-1]}, node => $el};
585     $el->set_user_data (manakai_source_line => $token->{line});
586     $el->set_user_data (manakai_source_column => $token->{column});
587    
588 wakaba 1.4 $el->set_attribute_ns (XML_NS, ['xml', 'lang'] => $token->{language})
589 wakaba 1.2 if defined $token->{language};
590    
591 wakaba 1.3 $token = $get_next_token->();
592 wakaba 1.2 redo A;
593     } elsif ($token->{type} == INLINE_END_TAG_TOKEN) {
594     pop @$oe if {
595     rt => 1, title => 1, nsuri => 1, attrvalue => 1,
596     }->{$oe->[-1]->{node}->manakai_local_name};
597    
598     if ({%$structural_elements,
599     strong => 1, em => 1}->{$oe->[-1]->{node}->manakai_local_name}) {
600 wakaba 1.6 unless (defined $token->{res_scheme} or defined $token->{anchor}) {
601     $oe->[-1]->{node}->manakai_append_text (']]');
602     push @$oe, $oe->[-1];
603     } else {
604     my $el = $doc->create_element_ns
605     (SW09_NS,
606     [undef, defined $token->{res_scheme}
607     ? 'anchor-external' : 'anchor-internal']);
608     $oe->[-1]->{node}->append_child ($el);
609     push @$oe, {%{$oe->[-1]}, node => $el};
610     $el->set_user_data (manakai_source_line => $token->{line});
611     $el->set_user_data (manakai_source_column => $token->{column});
612     $el->text_content (']]');
613     }
614 wakaba 1.2 }
615    
616 wakaba 1.4 $oe->[-1]->{node}->set_attribute_ns (SW09_NS, ['sw', 'anchor'],
617 wakaba 1.2 $token->{anchor})
618     if defined $token->{anchor};
619 wakaba 1.4 $oe->[-1]->{node}->set_attribute_ns (SW09_NS, ['sw', 'resScheme'],
620 wakaba 1.2 $token->{res_scheme})
621     if defined $token->{res_scheme};
622 wakaba 1.4 $oe->[-1]->{node}->set_attribute_ns (SW09_NS, ['sw', 'resParameter'],
623 wakaba 1.2 $token->{res_parameter})
624     if defined $token->{res_parameter};
625    
626     pop @$oe;
627    
628 wakaba 1.3 $token = $get_next_token->();
629 wakaba 1.2 redo A;
630     } elsif ($token->{type} == STRONG_TOKEN) {
631 wakaba 1.6 if ($oe->[-1]->{node}->manakai_local_name eq 'strong') {
632     pop @$oe;
633     } else {
634     my $el = $doc->create_element_ns (HTML_NS, [undef, 'strong']);
635     $oe->[-1]->{node}->append_child ($el);
636     push @$oe, {%{$oe->[-1]}, node => $el};
637     $el->set_user_data (manakai_source_line => $token->{line});
638     $el->set_user_data (manakai_source_column => $token->{column});
639     }
640 wakaba 1.3 $token = $get_next_token->();
641 wakaba 1.2 redo A;
642     } elsif ($token->{type} == EMPHASIS_TOKEN) {
643 wakaba 1.6 if ($oe->[-1]->{node}->manakai_local_name eq 'em') {
644     pop @$oe;
645     } else {
646     my $el = $doc->create_element_ns (HTML_NS, [undef, 'em']);
647     $oe->[-1]->{node}->append_child ($el);
648     push @$oe, {%{$oe->[-1]}, node => $el};
649     $el->set_user_data (manakai_source_line => $token->{line});
650     $el->set_user_data (manakai_source_column => $token->{column});
651     }
652 wakaba 1.3 $token = $get_next_token->();
653 wakaba 1.2 redo A;
654     } elsif ($token->{type} == FORM_TOKEN) {
655     ## There is an exact code clone.
656     if ($token->{name} eq 'form') {
657 wakaba 1.4 my $el = $doc->create_element_ns (SW09_NS, [undef, 'form']);
658 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
659     $el->set_user_data (manakai_source_line => $token->{line});
660     $el->set_user_data (manakai_source_column => $token->{column});
661    
662 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'id']
663     => $token->{id}) if defined $token->{id};
664     $el->set_attribute_ns (undef, [undef, 'input']
665     => shift @{$token->{parameters}})
666 wakaba 1.6 if @{$token->{parameters}};
667 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'template']
668     => shift @{$token->{parameters}})
669 wakaba 1.6 if @{$token->{parameters}};
670 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'option']
671     => shift @{$token->{parameters}})
672 wakaba 1.6 if @{$token->{parameters}};
673 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'parameter']
674     => join ':', @{$token->{parameters}})
675 wakaba 1.6 if @{$token->{parameters}};
676 wakaba 1.2
677 wakaba 1.3 $token = $get_next_token->();
678 wakaba 1.2 redo A;
679     } else {
680 wakaba 1.4 my $el = $doc->create_element_ns (SW09_NS, [undef, 'form']);
681 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
682     $el->set_user_data (manakai_source_line => $token->{line});
683     $el->set_user_data (manakai_source_column => $token->{column});
684    
685 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'ref']
686     => $token->{name});
687     $el->set_attribute_ns (undef, [undef, 'id']
688     => $token->{id}) if defined $token->{id};
689     $el->set_attribute_ns (undef, [undef, 'parameter']
690     => join ':', @{$token->{parameters}})
691 wakaba 1.5 if @{$token->{parameters}};
692 wakaba 1.2
693 wakaba 1.3 $token = $get_next_token->();
694 wakaba 1.2 redo A;
695     }
696     } elsif ($token->{type} == ELEMENT_TOKEN) {
697     ## NOTE: There is an exact code clone.
698     my $el = $doc->create_element_ns
699 wakaba 1.4 ($token->{namespace}, [undef, $token->{local_name}]);
700 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
701     $el->set_user_data (manakai_source_line => $token->{line});
702     $el->set_user_data (manakai_source_column => $token->{column});
703    
704 wakaba 1.4 $el->set_attribute_ns (SW09_NS, ['sw', 'anchor'], $token->{anchor})
705 wakaba 1.2 if defined $token->{anchor};
706 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'by']
707     => $token->{by}) if defined $token->{by};
708     $el->set_attribute_ns (SW09_NS, ['sw', 'resScheme'],
709     $token->{res_scheme})
710 wakaba 1.2 if defined $token->{res_scheme};
711 wakaba 1.4 $el->set_attribute_ns (SW09_NS, ['sw', 'resParameter'],
712 wakaba 1.2 $token->{res_parameter})
713     if defined $token->{res_parameter};
714     $el->text_content ($token->{content}) if defined $token->{content};
715    
716 wakaba 1.3 $token = $get_next_token->();
717 wakaba 1.2 redo A;
718     } elsif ($token->{type} == LABELED_LIST_MIDDLE_TOKEN) {
719     pop @$oe while not $structural_elements
720     ->{$oe->[-1]->{node}->manakai_local_name};
721     pop @$oe if $oe->[-1]->{node}->manakai_local_name eq 'dt';
722    
723 wakaba 1.5 my $el = $doc->create_element_ns (HTML_NS, [undef, 'dd']);
724 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
725     push @$oe, {%{$oe->[-1]}, node => $el};
726     $el->set_user_data (manakai_source_line => $token->{line});
727     $el->set_user_data (manakai_source_column => $token->{column});
728    
729 wakaba 1.3 $token = $get_next_token->();
730 wakaba 1.2 redo A;
731     } elsif ($token->{type} == HEADING_END_TOKEN) {
732     pop @$oe while not $structural_elements
733     ->{$oe->[-1]->{node}->manakai_local_name};
734     pop @$oe if $oe->[-1]->{node}->manakai_local_name eq 'h1';
735    
736     $im = IN_SECTION_IM;
737 wakaba 1.3 $token = $get_next_token->();
738 wakaba 1.2 redo A;
739     } elsif ($token->{type} == TABLE_CELL_END_TOKEN) {
740     pop @$oe while not $structural_elements
741     ->{$oe->[-1]->{node}->manakai_local_name};
742     pop @$oe if $oe->[-1]->{node}->manakai_local_name eq 'td';
743    
744     $im = IN_TABLE_ROW_IM;
745 wakaba 1.3 $token = $get_next_token->();
746 wakaba 1.2 redo A;
747     } elsif (($token->{type} == BLOCK_END_TAG_TOKEN and
748     $token->{tag_name} eq 'PRE') or
749     $token->{type} == PREFORMATTED_END_TOKEN) {
750     pop @$oe while not $structural_elements
751     ->{$oe->[-1]->{node}->manakai_local_name};
752     pop @$oe if $oe->[-1]->{node}->manakai_local_name eq 'pre';
753    
754     $im = IN_SECTION_IM;
755 wakaba 1.3 $token = $get_next_token->();
756 wakaba 1.2 redo A;
757     } else {
758     pop @$oe while not $structural_elements
759     ->{$oe->[-1]->{node}->manakai_local_name};
760    
761     $im = IN_SECTION_IM;
762 wakaba 1.3 ## Reconsume.
763 wakaba 1.2 redo A;
764     }
765     } elsif ($im == IN_SECTION_IM) {
766     if ($token->{type} == HEADING_START_TOKEN) {
767     B: {
768     pop @$oe and redo B
769 wakaba 1.3 if not {body => 1, section => 1, insert => 1, delete => 1}
770 wakaba 1.2 ->{$oe->[-1]->{node}->manakai_local_name} or
771     $token->{depth} <= $oe->[-1]->{section_depth};
772     if ($token->{depth} > $oe->[-1]->{section_depth} + 1) {
773 wakaba 1.4 my $el = $doc->create_element_ns (HTML_NS, [undef, 'section']);
774 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
775     push @$oe, {node => $el,
776     section_depth => $oe->[-1]->{section_depth} + 1,
777     quotation_depth => 0, list_depth => 0};
778     redo B;
779     }
780     } # B
781    
782 wakaba 1.4 my $el = $doc->create_element_ns (HTML_NS, [undef, 'section']);
783 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
784     push @$oe, {node => $el,
785     section_depth => $oe->[-1]->{section_depth} + 1,
786     quotation_depth => 0, list_depth => 0};
787    
788 wakaba 1.4 my $el2 = $doc->create_element_ns (HTML_NS, [undef, 'h1']);
789 wakaba 1.2 $oe->[-1]->{node}->append_child ($el2);
790     push @$oe, {%{$oe->[-1]}, node => $el2};
791    
792     $im = IN_PARAGRAPH_IM;
793 wakaba 1.3 $token = $get_next_token->();
794 wakaba 1.2 redo A;
795     } elsif ($token->{type} == BLOCK_START_TAG_TOKEN and
796     ($token->{tag_name} eq 'INS' or
797     $token->{tag_name} eq 'DEL')) {
798     my $el = $doc->create_element_ns
799 wakaba 1.4 (SW09_NS,
800     [undef, $token->{tag_name} eq 'INS' ? 'insert' : 'delete']);
801 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
802     push @$oe, {node => $el, section_depth => 0,
803     quotation_depth => 0, list_depth => 0};
804 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'class'] => $token->{classes})
805 wakaba 1.2 if defined $token->{classes};
806 wakaba 1.3 $token = $get_next_token->();
807 wakaba 1.2 redo A;
808     } elsif ($token->{type} == QUOTATION_START_TOKEN) {
809     B: {
810     pop @$oe and redo B
811 wakaba 1.3 if not {body => 1, section => 1, insert => 1, delete => 1,
812 wakaba 1.2 blockquote => 1}
813     ->{$oe->[-1]->{node}->manakai_local_name} or
814 wakaba 1.5 $token->{depth} < $oe->[-1]->{quotation_depth};
815     if ($token->{depth} > $oe->[-1]->{quotation_depth}) {
816 wakaba 1.4 my $el = $doc->create_element_ns (HTML_NS, [undef, 'blockquote']);
817 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
818     push @$oe, {node => $el, section_depth => 0,
819     quotation_depth => $oe->[-1]->{quotation_depth} + 1,
820     list_depth => 0};
821     redo B;
822     }
823     } # B
824    
825 wakaba 1.3 $token = $get_next_token->();
826 wakaba 1.2 redo A;
827     } elsif ($token->{type} == LIST_START_TOKEN) {
828     my $depth = length $token->{depth};
829 wakaba 1.3 my $list_type = substr ($token->{depth}, -1, 1) eq '-' ? 'ul' : 'ol';
830 wakaba 1.2 B: {
831     pop @$oe and redo B if $oe->[-1]->{list_depth} > $depth;
832 wakaba 1.3 pop @$oe and redo B if $oe->[-1]->{list_depth} == $depth and
833     $list_type ne $oe->[-1]->{node}->manakai_local_name;
834 wakaba 1.2 if ($oe->[-1]->{list_depth} < $depth) {
835 wakaba 1.3 my $type = substr $token->{depth}, $oe->[-1]->{list_depth}, 1;
836 wakaba 1.2 my $el = $doc->create_element_ns
837 wakaba 1.4 (HTML_NS, [undef, $type eq '-' ? 'ul' : 'ol']);
838 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
839     push @$oe, {%{$oe->[-1]}, node => $el,
840     list_depth => $oe->[-1]->{list_depth} + 1};
841     if ($oe->[-1]->{list_depth} < $depth) {
842 wakaba 1.4 my $el = $doc->create_element_ns (HTML_NS, [undef, 'li']);
843 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
844     push @$oe, {%{$oe->[-1]}, node => $el};
845     }
846     redo B;
847     }
848     } # B
849    
850 wakaba 1.4 my $el = $doc->create_element_ns (HTML_NS, [undef, 'li']);
851 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
852     push @$oe, {%{$oe->[-1]}, node => $el};
853    
854     $im = IN_PARAGRAPH_IM;
855 wakaba 1.3 $token = $get_next_token->();
856 wakaba 1.2 redo A;
857     } elsif ($token->{type} == LABELED_LIST_START_TOKEN) {
858     pop @$oe if $oe->[-1]->{node}->manakai_local_name eq 'dd';
859     if ($oe->[-1]->{node}->manakai_local_name ne 'dl') {
860 wakaba 1.4 my $el = $doc->create_element_ns (HTML_NS, [undef, 'dl']);
861 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
862     push @$oe, {%{$oe->[-1]}, node => $el};
863     }
864    
865 wakaba 1.4 my $el = $doc->create_element_ns (HTML_NS, [undef, 'dt']);
866 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
867     push @$oe, {%{$oe->[-1]}, node => $el};
868    
869     $im = IN_PARAGRAPH_IM;
870 wakaba 1.3 $token = $get_next_token->();
871 wakaba 1.2 redo A;
872     } elsif ($token->{type} == TABLE_ROW_START_TOKEN) {
873 wakaba 1.4 my $el = $doc->create_element_ns (HTML_NS, [undef, 'table']);
874 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
875     push @$oe, {%{$oe->[-1]}, node => $el};
876    
877 wakaba 1.4 $el = $doc->create_element_ns (HTML_NS, [undef, 'tbody']);
878 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
879     push @$oe, {%{$oe->[-1]}, node => $el};
880    
881 wakaba 1.4 $el = $doc->create_element_ns (HTML_NS, [undef, 'tr']);
882 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
883     push @$oe, {%{$oe->[-1]}, node => $el};
884    
885     $im = IN_TABLE_ROW_IM;
886 wakaba 1.3 $token = $get_next_token->();
887 wakaba 1.2 redo A;
888     } elsif (($token->{type} == BLOCK_START_TAG_TOKEN and
889     $token->{tag_name} eq 'PRE') or
890     $token->{type} == PREFORMATTED_START_TOKEN) {
891 wakaba 1.4 my $el = $doc->create_element_ns (HTML_NS, [undef, 'pre']);
892 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
893     push @$oe, {%{$oe->[-1]}, node => $el};
894    
895 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'class'] => $token->{classes})
896 wakaba 1.2 if defined $token->{classes};
897    
898     $im = IN_PARAGRAPH_IM;
899 wakaba 1.3 $token = $get_next_token->();
900 wakaba 1.2 redo A;
901     } elsif ($token->{type} == COMMENT_PARAGRAPH_START_TOKEN) {
902 wakaba 1.4 my $el = $doc->create_element_ns (SW10_NS, [undef, 'comment-p']);
903 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
904     push @$oe, {%{$oe->[-1]}, node => $el};
905    
906     $im = IN_PARAGRAPH_IM;
907 wakaba 1.3 $token = $get_next_token->();
908 wakaba 1.2 redo A;
909     } elsif ($token->{type} == EDITORIAL_NOTE_START_TOKEN) {
910 wakaba 1.4 my $el = $doc->create_element_ns (SW10_NS, [undef, 'ed']);
911 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
912     push @$oe, {%{$oe->[-1]}, node => $el};
913    
914     $im = IN_PARAGRAPH_IM;
915 wakaba 1.3 $token = $get_next_token->();
916 wakaba 1.2 redo A;
917     } elsif ($token->{type} == EMPTY_LINE_TOKEN) {
918 wakaba 1.3 pop @$oe while not {body => 1, section => 1, insert => 1, delete => 1}
919 wakaba 1.2 ->{$oe->[-1]->{node}->manakai_local_name};
920 wakaba 1.3 $token = $get_next_token->();
921 wakaba 1.2 redo A;
922     } elsif ($token->{type} == BLOCK_END_TAG_TOKEN) {
923 wakaba 1.3 if ($token->{tag_name} eq 'INS') {
924 wakaba 1.2 for (reverse 1..$#$oe) {
925     if ($oe->[$_]->{node}->manakai_local_name eq 'insert') {
926     splice @$oe, $_;
927     last;
928     }
929     }
930 wakaba 1.3 } elsif ($token->{tag_name} eq 'DEL') {
931 wakaba 1.2 for (reverse 1..$#$oe) {
932     if ($oe->[$_]->{node}->manakai_local_name eq 'delete') {
933     splice @$oe, $_;
934     last;
935     }
936     }
937     } else {
938     ## NOTE: Ignore the token.
939     }
940 wakaba 1.5 undef $continuous_line;
941 wakaba 1.3 $token = $get_next_token->();
942     redo A;
943 wakaba 1.2 } elsif ($token->{type} == FORM_TOKEN) {
944     ## There is an exact code clone.
945     if ($token->{name} eq 'form') {
946 wakaba 1.4 my $el = $doc->create_element_ns (SW09_NS, [undef, 'form']);
947 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
948     $el->set_user_data (manakai_source_line => $token->{line});
949     $el->set_user_data (manakai_source_column => $token->{column});
950    
951 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'id']
952     => $token->{id}) if defined $token->{id};
953     $el->set_attribute_ns (undef, [undef, 'input']
954     => shift @{$token->{parameters}})
955 wakaba 1.6 if @{$token->{parameters}};
956 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'template']
957     => shift @{$token->{parameters}})
958 wakaba 1.6 if @{$token->{parameters}};
959 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'option']
960     => shift @{$token->{parameters}})
961 wakaba 1.6 if @{$token->{parameters}};
962 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'parameter']
963     => join ':', @{$token->{parameters}})
964 wakaba 1.6 if @{$token->{parameters}};
965 wakaba 1.2
966 wakaba 1.3 $token = $get_next_token->();
967 wakaba 1.2 redo A;
968     } else {
969 wakaba 1.4 my $el = $doc->create_element_ns (SW09_NS, [undef, 'form']);
970 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
971     $el->set_user_data (manakai_source_line => $token->{line});
972     $el->set_user_data (manakai_source_column => $token->{column});
973    
974 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'ref'] => $token->{name});
975     $el->set_attribute_ns (undef, [undef, 'id']
976     => $token->{id}) if defined $token->{id};
977     $el->set_attribute_ns (undef, [undef, 'parameter']
978     => join ':', @{$token->{parameters}})
979 wakaba 1.6 if @{$token->{parameters}};
980 wakaba 1.2
981 wakaba 1.3 $token = $get_next_token->();
982 wakaba 1.2 redo A;
983     }
984     } elsif ($token->{type} == ELEMENT_TOKEN and
985     $token->{local_name} eq 'replace') {
986     ## NOTE: There is an exact code clone.
987     my $el = $doc->create_element_ns
988 wakaba 1.4 ($token->{namespace}, [undef, $token->{local_name}]);
989 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
990     $el->set_user_data (manakai_source_line => $token->{line});
991     $el->set_user_data (manakai_source_column => $token->{column});
992    
993 wakaba 1.4 $el->set_attribute_ns (SW09_NS, ['sw', 'anchor'], $token->{anchor})
994 wakaba 1.2 if defined $token->{anchor};
995 wakaba 1.4 $el->set_attribute_ns (undef, [undef, 'by']
996     => $token->{by}) if defined $token->{by};
997     $el->set_attribute_ns (SW09_NS, ['sw', 'resScheme'],
998     $token->{res_scheme})
999 wakaba 1.2 if defined $token->{res_scheme};
1000 wakaba 1.4 $el->set_attribute_ns (SW09_NS, ['sw', 'resParameter'],
1001 wakaba 1.2 $token->{res_parameter})
1002     if defined $token->{res_parameter};
1003     $el->text_content ($token->{content}) if defined $token->{content};
1004    
1005 wakaba 1.3 $token = $get_next_token->();
1006 wakaba 1.2 redo A;
1007     } elsif ($token->{type} == END_OF_FILE_TOKEN) {
1008     return;
1009     } elsif ({LABELED_LIST_MIDDLE_TOKEN => 1,
1010     HEADING_END_TOKEN => 1,
1011     PREFORMATTED_END_TOKEN => 1,
1012     TABLE_ROW_END_TOKEN => 1,
1013     TABLE_CELL_START_TOKEN => 1,
1014     TABLE_CELL_END_TOKEN => 1,
1015     TABLE_COLSPAN_CELL_TOKEN => 1}->{$token->{type}}) {
1016     ## NOTE: Ignore the token.
1017     } else {
1018 wakaba 1.5 unless ({dd => 1,
1019     li => 1,
1020     'comment-p' => 1,
1021     ed => 1}->{$oe->[-1]->{node}->manakai_local_name}) {
1022     my $el = $doc->create_element_ns (HTML_NS, [undef, 'p']);
1023     $oe->[-1]->{node}->append_child ($el);
1024     push @$oe, {%{$oe->[-1]}, node => $el};
1025     }
1026    
1027 wakaba 1.2 $im = IN_PARAGRAPH_IM;
1028     ## Reprocess.
1029     redo A;
1030     }
1031     } elsif ($im == IN_TABLE_ROW_IM) {
1032     if ($token->{type} == TABLE_CELL_START_TOKEN) {
1033 wakaba 1.4 my $el = $doc->create_element_ns (HTML_NS, [undef, 'td']);
1034 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
1035     push @$oe, {%{$oe->[-1]}, node => $el};
1036     $el->set_user_data (manakai_source_line => $token->{line});
1037     $el->set_user_data (manakai_source_column => $token->{column});
1038    
1039     $im = IN_PARAGRAPH_IM;
1040 wakaba 1.3 $token = $get_next_token->();
1041 wakaba 1.2 redo A;
1042     } elsif ($token->{type} == TABLE_COLSPAN_CELL_TOKEN) {
1043     my $lc = $oe->[-1]->{node}->last_child;
1044     if ($lc and $lc->manakai_local_name eq 'td') {
1045 wakaba 1.4 $lc->set_attribute_ns
1046     (undef, [undef, 'colspan'],
1047 wakaba 1.6 ($lc->get_attribute_ns (undef, 'colspan') || 1) + 1);
1048 wakaba 1.2 } else {
1049 wakaba 1.5 my $el = $doc->create_element_ns (HTML_NS, [undef, 'td']);
1050 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
1051     $el->set_user_data (manakai_source_line => $token->{line});
1052     $el->set_user_data (manakai_source_column => $token->{column});
1053     }
1054    
1055 wakaba 1.3 $token = $get_next_token->();
1056 wakaba 1.2 redo A;
1057     } elsif ($token->{type} == TABLE_ROW_END_TOKEN) {
1058     pop @$oe if $oe->[-1]->{node}->manakai_local_name eq 'tr';
1059 wakaba 1.3 $token = $get_next_token->();
1060 wakaba 1.2 redo A;
1061     } elsif ($token->{type} == TABLE_ROW_START_TOKEN) {
1062 wakaba 1.4 my $el = $doc->create_element_ns (HTML_NS, [undef, 'tr']);
1063 wakaba 1.2 $oe->[-1]->{node}->append_child ($el);
1064     push @$oe, {%{$oe->[-1]}, node => $el};
1065     $el->set_user_data (manakai_source_line => $token->{line});
1066     $el->set_user_data (manakai_source_column => $token->{column});
1067    
1068 wakaba 1.3 $token = $get_next_token->();
1069 wakaba 1.2 redo A;
1070     } else {
1071     $im = IN_SECTION_IM;
1072     ## Reprocess.
1073     redo A;
1074     }
1075     } else {
1076     die "$0: Unknown insertion mode: $im";
1077     }
1078     } # A
1079 wakaba 1.1 } # parse_char_string
1080    
1081     1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24