/[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.5 - (hide annotations) (download)
Fri Nov 7 08:45:28 2008 UTC (16 years, 8 months ago) by wakaba
Branch: MAIN
Changes since 1.4: +32 -25 lines
++ whatpm/t/ChangeLog	7 Nov 2008 08:45:01 -0000
	* SWML-Parser.t: Test file |swml/blocks-1.dat| added.

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

++ whatpm/t/swml/ChangeLog	7 Nov 2008 08:45:13 -0000
	* structs-1.dat: More test data added.

	* blocks-1.dat: New file.

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

++ whatpm/Whatpm/ChangeLog	7 Nov 2008 08:43:32 -0000
2008-11-07  Wakaba  <wakaba@suika.fam.cx>

	* NanoDOM.pm (text_content): Don't create a Text node if the new
	value is empty.

++ whatpm/Whatpm/HTML/ChangeLog	7 Nov 2008 08:43:49 -0000
2008-11-07  Wakaba  <wakaba@suika.fam.cx>

	* Dumper.pm (dumptree): Support for namespace abbreviation for
	SWML namespaces.

++ whatpm/Whatpm/SWML/ChangeLog	7 Nov 2008 08:44:20 -0000
	* Parser.pm: Bug fixes - both parser implementation bugs and spec
	bugs.

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24