/[suikacvs]/messaging/manakai/bin/idl2dis.pl
Suika

Contents of /messaging/manakai/bin/idl2dis.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations) (download)
Sun Oct 10 00:01:08 2004 UTC (20 years, 10 months ago) by wakaba
Branch: MAIN
CVS Tags: before-dis2-200411
File MIME type: text/plain
Some files moved; DOM Level 3 LS configuration parameters and errors definition added

1 wakaba 1.1 #!/usr/bin/perl -w
2     use strict;
3     use Message::Markup::SuikaWikiConfig20::Node;
4    
5     my $LastCategory = '';
6     my $LastComment = '';
7     my $LastAttr;
8     my $NAME = qr/[\w:.]+/;
9     my $Status;
10     sub err ($);
11     sub level ($);
12     sub raises ($$$);
13    
14     my $tree = Message::Markup::SuikaWikiConfig20::Node->new (type => '#document');
15    
16     sub fws ($) {
17     my $s = shift;
18     while ($$s =~ m{\G(?=[#\s]|/[/\*])}gc) {
19     if ($$s =~ /\G\s+/gc) {
20     #
21     } elsif ($$s =~ /\G\#(.+)(?:\n|$)/gc) {
22     my $l = $1;
23     my $m = $tree->get_attribute ('Module');
24     if ($l =~ /^include\s+"([^"]+)"/) {
25     my $f = $1;
26     my $c = $m->get_attribute ('Require', make_new_node => 1)
27     ->append_new_node (type => '#element',
28     local_name => 'Module');
29     $c->set_attribute (Name => undef);
30     $c->set_attribute (FileName => $f)
31     ->set_attribute (For => 'lang:IDL-DOM');
32     $f =~ s/\.idl$//;
33     $c->set_attribute (Name => $f);
34     $c->set_attribute (Namespace => q<:: TBD ::>);
35     } elsif ($l =~ /^pragma\s+prefix\s+"([^"]+)"/) {
36     $m->get_element_by (sub {
37     my ($me, $you) = @_;
38     $you->local_name eq 'BindingName' and
39     $you->get_attribute_value ('Type', default => '')
40     eq 'lang:IDL-DOM'
41     }, make_new_node => sub {
42     my ($me, $you) = @_;
43     $you->local_name ('BindingName');
44     $you->set_attribute (Type => 'lang:IDL-DOM');
45     })
46     ->set_attribute (prefix => $1);
47     } else {
48     $tree->append_new_node (type => '#comment', value => ' #'.$l);
49     }
50     } elsif ($$s =~ m#\G//\s*(\w+)\s*\n#gc) {
51     $LastComment = $LastCategory = $1;
52     } elsif ($$s =~ m#\G//(.+\n(?:\s*//.+\n)*)#gc) {
53     $LastComment = $1;
54     $LastComment =~ s#\n\s*//\s*# #g;
55     $LastComment =~ s/^\s+//;
56     $LastComment =~ s/\s+$//;
57     if ($LastComment =~ /raises\s*(\([^()]+\)|[^()\s]+)\s+on\s+setting/) {
58     my ($x, $t) = ($1, $2);
59     if ($LastAttr) {
60     raises \$x => $LastAttr, 'Set';
61     } else {
62     warn "Unassociated attribute exception comment found: $LastComment";
63     }
64     }
65     if ($LastComment =~ /raises\s*(\([^()]+\)|[^()\s]+)\s+on\s+retrieval/) {
66     my ($x, $t) = ($1, $2);
67     if ($LastAttr) {
68     raises \$x => $LastAttr, 'Get';
69     } else {
70     warn "Unassociated attribute exception comment found: $LastComment";
71     }
72     }
73     } elsif ($$s =~ m#\G(/\*(?>(?!\*/).)*\*/)#gcs) {
74     $tree->append_new_node (type => '#comment', value => $1);
75     } else {
76     err $s;
77     }
78     }
79     }
80    
81     sub type ($) {
82     my $s = shift;
83     $$s =~ /\G($NAME)/gc or return 0;
84     my $type = $1;
85     if ($type eq 'unsigned' or $type eq 'signed') {
86     fws $s;
87     $$s =~ /\G($NAME)/gc or err $s;
88     $type .= '-' . $1;
89     if ($1 eq 'long' and $$s =~ /\G\s+long\b/gc) {
90     $type .= '-long';
91     }
92     }
93     if ($type =~ /:/) {
94     $type =~ s/::/:/;
95     if ($type =~ /^([^:]+):/) {
96     register_required_module (Name => $1);
97     }
98     }
99     if ($type !~ /[^a-z-]/ and
100     not {qw/attribute 1 readonly 1 in 1 const 1 void 1/}->{$type}) {
101     $type = 'DOMMain:' . $type;
102     } elsif ({DOMString => 1, Object => 1}->{$type}) {
103     unless ($Status->{datatype_defined}->{$type}) {
104     $type = 'DOMMain:' . $type;
105     }
106     }
107     return $type;
108     }
109    
110     my $CONST = qr/^Constants|Types$|[oe]rs$|Values$|Options$|^Exception/;
111    
112     sub const ($$) {
113     my ($s, $parent) = @_;
114     if ($LastCategory or $LastComment =~ /$CONST/) {
115     if ($parent->child_nodes->[-1] and
116     $parent->child_nodes->[-1]->local_name eq 'ConstGroup' and
117     ($parent->child_nodes->[-1]->get_attribute_value ('Name', default => ' ')
118     eq $LastCategory or
119     $parent->child_nodes->[-1]->get_attribute_value ('FullName',
120     default => ' ')
121     eq $LastComment)) {
122     $parent = $parent->child_nodes->[-1];
123     } elsif ($parent->child_nodes->[-1] and
124     $parent->child_nodes->[-1]->local_name eq 'Exception') {
125     $parent = $parent->child_nodes->[-1];
126     if ($parent->child_nodes->[-1] and
127     $parent->child_nodes->[-1]->local_name eq 'ConstGroup' and
128     ($parent->child_nodes->[-1]->get_attribute_value ('Name', default => ' ')
129     eq $LastCategory or
130     $parent->child_nodes->[-1]->get_attribute_value ('FullName',
131     default => ' ')
132     eq $LastComment)) {
133     $parent = $parent->child_nodes->[-1];
134     } else {
135     $parent = $parent->append_new_node (type => '#element', local_name => 'ConstGroup');
136     if ($LastCategory) {
137     $parent->set_attribute (Name => $LastCategory);
138     } else {
139     $parent->set_attribute (FullName => $LastComment)
140     ->set_attribute (lang => 'en');
141     }
142     }
143     } else {
144     $parent = $parent->append_new_node (type => '#element', local_name => 'ConstGroup');
145     if ($LastCategory) {
146     $parent->set_attribute (Name => $LastCategory);
147     } else {
148     $parent->set_attribute (FullName => $LastComment)
149     ->set_attribute (lang => 'en');
150     }
151     }
152     }
153    
154     fws $s;
155     my $type = type $s or err $s;
156     fws $s;
157     if ($parent->node_type eq '#element' and
158     $parent->local_name eq 'ConstGroup' and
159     not $parent->get_attribute ('Type')) {
160     $parent->set_attribute (Type => $type);
161     }
162     my $const = $parent->append_new_node (type => '#element', local_name => 'Const');
163     $$s =~ /\G($NAME)/gc or err $s;
164     $const->set_attribute (Name => $1);
165     $const->set_attribute (Type => $type);
166     fws $s;
167     $$s =~ /\G=/gc or err $s;
168     fws $s;
169     $$s =~ /\G([^\s;]+)/gc or err $s;
170     $const->set_attribute (Value => $1);
171     level $const;
172     }
173    
174     sub idlname2name ($) {
175     my $s = shift;
176     $s =~ s/^_//;
177     $s;
178     }
179    
180     sub semicolon ($) {
181     my $s = shift;
182     $$s =~ /\G;/gc or return 0;
183     $LastComment = '' unless $LastComment =~ /$CONST/;
184     return 1;
185     }
186    
187     sub clear_comment () {
188     $LastComment = '';
189     $LastCategory = '';
190     }
191    
192     sub level ($) {
193     my $n = shift;
194     if ($LastComment =~ /Introduced in DOM Level (\d+)/) {
195     my $l = $1;
196     my $p = $n->get_attribute_value ('Level', default => [], as_array => 1);
197     $n->set_attribute (Level => [@$p, $l]);
198     $n->set_attribute (SpecLevel => [@$p, $l]);
199     } elsif ($LastComment =~ /Modified in DOM Level (\d+)/) {
200     my $l = $1;
201     my $p = $n->get_attribute_value ('Level', default => [':: TBD ::'],
202     as_array => 1);
203     $n->set_attribute (Level => [@$p, $l]);
204     $n->set_attribute (SpecLevel => [@$p, $l]);
205     }
206     }
207    
208     sub raises ($$$) {
209     my ($s, $n, $nm) = @_;
210     $$s =~ /\G\(/gc;
211     fws $s;
212     my $p = $n->get_attribute ($nm, make_new_node => 1);
213     while ($$s =~ /\G($NAME)/gc) {
214     my $name = $1;
215     $name =~ s/::/:/g;
216     $name = 'DOMCore:'.$name if $name eq 'DOMException' and
217     not $Status->{datatype_defined}->{$name};
218     if ($name =~ /^([^:]+):/) {
219     register_required_module (Name => $1);
220     }
221     for my $except ($p->append_new_node (type => '#element',
222     local_name => 'Exception')) {
223     $except->set_attribute (Name => '** TBD **');
224     $except->set_attribute (Type => $name);
225     }
226     fws $s;
227     $$s =~ /\G,/gc;
228     fws $s;
229     }
230     $$s =~ /\G\)/gc;
231     return 1;
232     }
233    
234     sub err ($) {
235     use Carp;
236     my $s = shift;
237     print $tree->stringify;
238     Carp::croak "Invalid input (either input is broken or struct not implemented found): ",
239     substr $$s, pos $$s, 100;
240     }
241    
242     sub register_required_module (%) {
243     my %opt = @_;
244     my $mod = $tree->get_attribute ('Module')
245     ->get_attribute ('Require', make_new_node => 1)
246     ->get_element_by (sub {
247     my ($me, $you) = @_;
248     $you->local_name eq 'Module' and
249     $you->get_attribute_value ('Name', default => '') eq $opt{Name};
250     }, make_new_node => sub {
251     my ($me, $you) = @_;
252     $you->local_name ('Module');
253     $you->set_attribute (Name => $opt{Name});
254     });
255     $mod->set_attribute (Namespace => $opt{Namespace} || q<:: TBD ::>);
256     if ($opt{PerlRequire}) {
257     unless ($mod->get_element_by (sub {
258     my ($me, $you) = @_;
259     $you->local_name eq 'Def' and
260     $you->get_attribute_value ('Type', default => '') eq q<lang:Perl>;
261     })) {
262     for ($mod->append_new_node (type => '#element', local_name => 'Def')) {
263     $_->set_attribute (Type => q<lang:Perl>);
264     $_->set_attribute (require => $opt{PerlRequire});
265     }
266     }
267     }
268     }
269    
270     sub supply_incase ($$) {
271     my ($type, $node) = @_;
272     if ($type eq 'DOMMain:boolean') {
273     for my $b ('true', 'false') {
274     for ($node->append_new_node (type => '#element',
275     local_name => 'InCase')) {
276     $_->set_attribute (Value => $b);
277     }
278     }
279     }
280     } # supply_incase
281    
282     my $s;
283     {
284     local $/ = undef;
285     $s = \(<> or die "$0: $ARGV: $!");
286     }
287    
288     pos $$s = 0;
289    
290     for my $ns ($tree->get_attribute ('Namespace', make_new_node => 1)) {
291     $ns->set_attribute (lang => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/lang#>);
292     $ns->set_attribute (license => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/license#>);
293     }
294    
295     for my $module ($tree->append_new_node (type => '#element',
296     local_name => 'Module')) {
297     $module->set_attribute (Name => q<## TBD ##>);
298     $module->set_attribute (Namespace => q<:: TBD ::>);
299     $module->set_attribute (BindingName => q<** TBD **>)
300     ->set_attribute (Type => q<lang:IDL-DOM>);
301     for ($module->set_attribute (Author => undef)) {
302     $_->set_attribute (FullName => q<** TBD **>);
303     $_->set_attribute (Mail => q<** TBD **>);
304     }
305     $module->set_attribute (License => q<license:Perl+MPL>);
306     $module->set_attribute ('Date.RCS' => q<$Date: 2004/09/27 12:11:53 $>);
307     }
308    
309     fws $s;
310     if ($$s =~ /\Gpragma\s+prefix\s+"([^"]+)"\s*/gc) {
311     for ($tree->get_attribute ('Module')
312     ->get_element_by (sub {
313     my ($me, $you) = @_;
314     $you->local_name eq 'BindingName' and
315     $you->get_attribute_value ('Type', default => '') eq 'lang:IDL-DOM';
316     }, make_new_node => sub {
317     my ($me, $you) = @_;
318     $you->local_name ('BindingName');
319     $you->set_attribute (Type => 'lang:IDL-DOM');
320     })) {
321     $_->set_attribute (prefix => $1);
322     $_->set_attribute (Type => 'lang:IDL-DOM');
323     }
324     }
325     if ($$s =~ /\Gmodule\b/gc) {
326     fws $s;
327     $$s =~ /\G($NAME)/gc or err $s;
328     for ($tree->get_attribute ('Module')) {
329     $_->get_element_by (sub {
330     my ($me, $you) = @_;
331     $you->local_name eq 'BindingName' and
332     $you->get_attribute_value ('Type', default => '') eq 'lang:IDL-DOM';
333     }, make_new_node => sub {
334     my ($me, $you) = @_;
335     $you->local_name ('BindingName');
336     $you->set_attribute (Type => 'lang:IDL-DOM');
337     })->inner_text (new_value => $1);
338     $_->set_attribute (Name => $1);
339     }
340     fws $s;
341     $$s =~ /\G\{/gc;
342     fws $s;
343     }
344    
345    
346     while (pos $$s < length $$s) {
347     my $r = $tree;
348     if ($$s =~ /\Ginterface\b/gc) {
349     fws $s;
350     $$s =~ /\G($NAME)/gc or err $s;
351     my $name = $1;
352     my @isa;
353     fws $s;
354     if ($$s =~ /\G:/gc) {
355     fws $s;
356     while ($$s =~ /\G($NAME)/gc) {
357     my $name = $1;
358     $name =~ s/::/:/g;
359     if ($name =~ /^([^:]+):/) {
360     register_required_module (Name => $1);
361     }
362     push @isa, $name;
363     fws $s;
364     $$s =~ /\G,/gc or last;
365     fws $s;
366     }
367     }
368     if ($$s =~ /\G\{/gc) {
369     my $if = $r->append_new_node (type => '#element', local_name => 'IF');
370     $if->set_attribute (Name => $name);
371     for (@isa) {
372     $if->append_new_node (type => '#element',
373     local_name => 'ISA',
374     value => $_);
375     }
376     level $if;
377     clear_comment;
378     fws $s;
379     while (my $type = type $s) {
380     fws $s;
381     if ($type eq 'attribute' or $type eq 'readonly') {
382     my $attr = $LastAttr = $if->append_new_node (type => '#element', local_name => 'Attr');
383     my $readonly;
384     if ($type eq 'readonly') {
385     $$s =~ /\Gattribute\b/gc or err $s;
386     fws $s;
387     $readonly = 1;
388     }
389     $type = type $s or err $s;
390     fws $s;
391     $$s =~ /\G($NAME)/gc or err $s;
392     $attr->set_attribute (Name => idlname2name $1);
393     fws $s;
394     $attr->get_attribute ('Get', make_new_node => 1)
395     ->set_attribute (Type => $type);
396     $attr->get_attribute ('Set', make_new_node => 1)
397     ->set_attribute (Type => $type) unless $readonly;
398     supply_incase ($type => $attr->get_attribute ('Get'));
399     supply_incase ($type => $attr->get_attribute ('Set'))
400     unless $readonly;
401     level $attr;
402     } elsif ($type eq 'const') {
403     const $s => $if;
404     fws $s;
405     } else {
406     my $method = $if->append_new_node (type => '#element',
407     local_name => 'Method');
408     if ($$s =~ /\G($NAME)/gc) {
409     $method->set_attribute (Name => idlname2name $1);
410     } else {
411     $method->set_attribute (Name => idlname2name $type);
412     undef $type;
413     }
414     fws $s;
415     $$s =~ /\G\(/gc or err $s;
416     {
417     fws $s;
418     my $type = type $s or last;
419     fws $s;
420     my $in;
421     if ($type eq 'in') {
422     $in = 1;
423     $type = type $s or err $s;
424     fws $s;
425     }
426     my $p = $method->append_new_node (type => '#element', local_name => 'Param');
427     $$s =~ /\G($NAME)/gc or err $s;
428     $p->set_attribute (Name => idlname2name $1);
429     $p->set_attribute (Type => $type);
430     $p->set_attribute (Write => 0) unless $in;
431     supply_incase ($type => $p);
432     fws $s;
433     $$s =~ /\G,/gc or last;
434     redo;
435     }
436     $$s =~ /\G\)/gc or err $s;
437     fws $s;
438    
439     my $return = $method->get_attribute ('Return', make_new_node => 1);
440     if ($type and $type ne 'void') {
441     $return->set_attribute (Type => $type);
442     supply_incase ($type => $return);
443     }
444     if ($$s =~ /\Graises\b/gc) {
445     raises $s => $method, 'Return' or err $s;
446     fws $s;
447     }
448     level $method;
449     } # attr or method
450     semicolon $s or err $s;
451     fws $s;
452     }
453     $$s =~ /\G\}/gc or err $s;
454     } # definition
455     fws $s;
456     } elsif ($$s =~ /\Gconst\b/gc) {
457     const $s => $r;
458     fws $s;
459     } elsif ($$s =~ /\Gexception\b/gc) {
460     my $except = $r->append_new_node (type => '#element', local_name => 'Exception');
461     fws $s;
462     $$s =~ /\G($NAME)/gc or err $s;
463     $except->set_attribute (Name => $1);
464     level $except;
465     fws $s;
466     $$s =~ /\G\{/gc or err $s;
467     clear_comment;
468     fws $s;
469     while (my $type = type $s) {
470     fws $s;
471     my $attr = $except->append_new_node (type => '#element', local_name => 'Attr');
472     $$s =~ /\G($NAME)/gc or err $s;
473     $attr->set_attribute (Name => idlname2name $1);
474     $attr->get_attribute ('Get', make_new_node => 1)
475     ->set_attribute (Type => $type);
476     fws $s;
477     semicolon $s or err $s;
478     fws $s;
479     }
480     $$s =~ /\G\}/gc or err $s;
481     fws $s;
482     } elsif ($$s =~ /\Gvaluetype\b/gc) {
483     fws $s;
484     my $valtype = $r->append_new_node (type => '#element',
485     local_name => 'DataType');
486     my $type = type $s or err $s;
487     $valtype->set_attribute (Name => $type);
488     fws $s;
489     $$s =~ /\G([^;]+)/gc or err $s;
490     $valtype->set_attribute (Def => $1)
491     ->set_attribute (Type => q<lang:IDL-DOM>);
492     fws $s;
493     } elsif ($$s =~ /\Gtypedef\b/gc) {
494     fws $s;
495     my $type = type $s or err $s;
496     fws $s;
497     my $valtype = $r->append_new_node (type => '#element',
498     local_name => 'DataTypeAlias');
499     my $name = $$s =~ /\G($NAME)/gc ? $1 : err $s;
500     $valtype->set_attribute (Name => $name);
501     $valtype->set_attribute (Type => $type);
502     $Status->{datatype_defined}->{$name} = 1;
503     fws $s;
504     } else {
505     last;
506     }
507     semicolon $s ;#or err $s;
508     fws $s;
509     }
510    
511     $$s =~ /\G\}/gc; # module name {...}
512     fws $s;
513     semicolon $s;
514     fws $s;
515    
516     $$s =~ /\G./gc and err $s;
517    
518     print $tree->stringify;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24  
Google Analytics is used in this page; Cookies are used. 忍者AdMax is used in this page; Cookies are used. Privacy policy.