/[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.3 - (hide annotations) (download)
Thu Nov 6 13:29:14 2008 UTC (16 years ago) by wakaba
Branch: MAIN
Changes since 1.2: +49 -47 lines
++ whatpm/Whatpm/SWML/ChangeLog	6 Nov 2008 13:28:54 -0000
	* Parser.pm: Multiple |rt| elements in a |ruby| element was not
	allowed.  Don't use \s where SWML's definition of white space is
	required.  "The head element" definition was wrong.  Typo fixed.
	List algorithm bug fixed.

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24