~ubuntu-branches/ubuntu/maverick/webkit/maverick

« back to all changes in this revision

Viewing changes to WebCore/bindings/scripts/IDLParser.pm

  • Committer: Bazaar Package Importer
  • Author(s): Mike Hommey
  • Date: 2007-08-19 15:54:12 UTC
  • Revision ID: james.westby@ubuntu.com-20070819155412-uxxg1h9plpghmtbi
Tags: upstream-0~svn25144
ImportĀ upstreamĀ versionĀ 0~svn25144

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
2
# KDOM IDL parser
 
3
#
 
4
# Copyright (C) 2005 Nikolas Zimmermann <wildfox@kde.org>
 
5
 
6
# This file is part of the KDE project
 
7
 
8
# This library is free software; you can redistribute it and/or
 
9
# modify it under the terms of the GNU Library General Public
 
10
# License as published by the Free Software Foundation; either
 
11
# version 2 of the License, or (at your option) any later version.
 
12
 
13
# This library is distributed in the hope that it will be useful,
 
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
# Library General Public License for more details.
 
17
 
18
# You should have received a copy of the GNU Library General Public License
 
19
# aint with this library; see the file COPYING.LIB.  If not, write to
 
20
# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
21
# Boston, MA 02111-1307, USA.
 
22
 
23
 
 
24
package IDLParser;
 
25
 
 
26
use IDLStructure;
 
27
 
 
28
use constant MODE_UNDEF    => 0; # Default mode.
 
29
 
 
30
use constant MODE_MODULE  => 10; # 'module' section
 
31
use constant MODE_INTERFACE  => 11; # 'interface' section
 
32
use constant MODE_EXCEPTION  => 12; # 'exception' section
 
33
use constant MODE_ALIAS    => 13; # 'alias' section
 
34
 
 
35
# Helper variables
 
36
my @temporaryContent = "";
 
37
 
 
38
my $parseMode = MODE_UNDEF;
 
39
my $preservedParseMode = MODE_UNDEF;
 
40
 
 
41
my $beQuiet; # Should not display anything on STDOUT?
 
42
my $document = 0; # Will hold the resulting 'idlDocument'
 
43
 
 
44
# Default Constructor
 
45
sub new
 
46
{
 
47
    my $object = shift;
 
48
    my $reference = { };
 
49
 
 
50
    $document = 0;
 
51
    $beQuiet = shift;
 
52
 
 
53
    bless($reference, $object);
 
54
    return $reference;
 
55
}
 
56
 
 
57
# Returns the parsed 'idlDocument'
 
58
sub Parse
 
59
{
 
60
    my $object = shift;
 
61
    my $fileName = shift;
 
62
    my $defines = shift;
 
63
    my $preprocessor = shift;
 
64
 
 
65
    if (!$preprocessor) {
 
66
        $preprocessor = "/usr/bin/gcc -E -P -x c++";
 
67
    }
 
68
 
 
69
    if (!$defines) {
 
70
        $defines = "";
 
71
    }
 
72
 
 
73
    print " | *** Starting to parse $fileName...\n |\n" unless $beQuiet;
 
74
 
 
75
    open FILE, $preprocessor . " " . join(" ", (map { "-D$_" } split(/ /, $defines))) . " ". $fileName . "|" or die "Could not open $fileName";
 
76
    my @documentContent = <FILE>;
 
77
    close FILE;
 
78
 
 
79
    my $dataAvailable = 0;
 
80
 
 
81
    # Simple IDL Parser (tm)
 
82
    foreach (@documentContent) {
 
83
        my $newParseMode = $object->DetermineParseMode($_);
 
84
 
 
85
        if ($newParseMode ne MODE_UNDEF) {
 
86
            if ($dataAvailable eq 0) {
 
87
                $dataAvailable = 1; # Start node building...
 
88
            } else {
 
89
                $object->ProcessSection();
 
90
            }
 
91
        }
 
92
 
 
93
        # Update detected data stream mode...
 
94
        if ($newParseMode ne MODE_UNDEF) {
 
95
            $parseMode = $newParseMode;
 
96
        }
 
97
 
 
98
        push(@temporaryContent, $_);
 
99
    }
 
100
 
 
101
    # Check if there is anything remaining to parse...
 
102
    if (($parseMode ne MODE_UNDEF) and ($#temporaryContent > 0)) {
 
103
        $object->ProcessSection();
 
104
    }
 
105
 
 
106
    print " | *** Finished parsing!\n" unless $beQuiet;
 
107
 
 
108
    $document->fileName($fileName);
 
109
 
 
110
    return $document;
 
111
}
 
112
 
 
113
sub ParseModule
 
114
{
 
115
    my $object = shift;
 
116
    my $dataNode = shift;
 
117
 
 
118
    print " |- Trying to parse module...\n" unless $beQuiet;
 
119
 
 
120
    my $data = join("", @temporaryContent);
 
121
    $data =~ /$IDLStructure::moduleSelector/;
 
122
 
 
123
    my $moduleName = (defined($1) ? $1 : die("Parsing error!\nSource:\n$data\n)"));
 
124
    $dataNode->module($moduleName);
 
125
 
 
126
    print "  |----> Module; NAME \"$moduleName\"\n |-\n |\n" unless $beQuiet;
 
127
}
 
128
 
 
129
sub dumpExtendedAttributes
 
130
{
 
131
    my $padStr = shift;
 
132
    my $attrs = shift;
 
133
 
 
134
    if (!%{$attrs}) {
 
135
        return "";
 
136
    }
 
137
 
 
138
    my @temp;
 
139
    while (($name, $value) = each(%{$attrs})) {
 
140
        push(@temp, "$name=$value");
 
141
    }
 
142
 
 
143
    return $padStr . "[" . join(", ", @temp) . "]";
 
144
}
 
145
 
 
146
sub parseExtendedAttributes
 
147
{
 
148
    my $str = shift;
 
149
    $str =~ s/\[\s*(.*)\]/$1/g;
 
150
 
 
151
    my %attrs = ();
 
152
 
 
153
    foreach my $value (split(/\s*,\s*/, $str)) {
 
154
        ($name,$value) = split(/\s*=\s*/, $value, 2);
 
155
 
 
156
        # Attributes with no value are set to be true
 
157
        $value = 1 unless defined $value;
 
158
        $attrs{$name} = $value;
 
159
    }
 
160
 
 
161
    return \%attrs;
 
162
}
 
163
 
 
164
sub ParseInterface
 
165
{
 
166
    my $object = shift;
 
167
    my $dataNode = shift;
 
168
    my $sectionName = shift;
 
169
 
 
170
    my $data = join("", @temporaryContent);
 
171
 
 
172
    # Look for end-of-interface mark
 
173
    $data =~ /};/g;
 
174
    $data = substr($data, index($data, $sectionName), pos($data) - length($data));
 
175
 
 
176
    $data =~ s/[\n\r]/ /g;
 
177
 
 
178
    # Beginning of the regexp parsing magic
 
179
    if ($sectionName eq "exception") {
 
180
        print " |- Trying to parse exception...\n" unless $beQuiet;
 
181
 
 
182
        my $exceptionName = "";
 
183
        my $exceptionData = "";
 
184
        my $exceptionDataName = "";
 
185
        my $exceptionDataType = "";
 
186
 
 
187
        # Match identifier of the exception, and enclosed data...
 
188
        $data =~ /$IDLStructure::exceptionSelector/;
 
189
        $exceptionName = (defined($1) ? $1 : die("Parsing error!\nSource:\n$data\n)"));
 
190
        $exceptionData = (defined($2) ? $2 : die("Parsing error!\nSource:\n$data\n)"));
 
191
 
 
192
        ('' =~ /^/); # Reset variables needed for regexp matching
 
193
 
 
194
        # ... parse enclosed data (get. name & type)
 
195
        $exceptionData =~ /$IDLStructure::exceptionSubSelector/;
 
196
        $exceptionDataType = (defined($1) ? $1 : die("Parsing error!\nSource:\n$data\n)"));
 
197
        $exceptionDataName = (defined($2) ? $2 : die("Parsing error!\nSource:\n$data\n)"));
 
198
 
 
199
        # Fill in domClass datastructure
 
200
        $dataNode->name($exceptionName);
 
201
 
 
202
        my $newDataNode = new domAttribute();
 
203
        $newDataNode->type("readonly attribute");
 
204
        $newDataNode->signature(new domSignature());
 
205
 
 
206
        $newDataNode->signature->name($exceptionDataName);
 
207
        $newDataNode->signature->type($exceptionDataType);
 
208
 
 
209
        my $arrayRef = $dataNode->attributes;
 
210
        push(@$arrayRef, $newDataNode);
 
211
 
 
212
        print "  |----> Exception; NAME \"$exceptionName\" DATA TYPE \"$exceptionDataType\" DATA NAME \"$exceptionDataName\"\n |-\n |\n" unless $beQuiet;
 
213
    } elsif ($sectionName eq "interface") {
 
214
        print " |- Trying to parse interface...\n" unless $beQuiet;
 
215
 
 
216
        my $interfaceName = "";
 
217
        my $interfaceData = "";
 
218
 
 
219
        # Match identifier of the interface, and enclosed data...
 
220
        $data =~ /$IDLStructure::interfaceSelector/;
 
221
 
 
222
        $interfaceExtendedAttributes = (defined($1) ? $1 : " "); chop($interfaceExtendedAttributes);
 
223
        $interfaceName = (defined($2) ? $2 : die("Parsing error!\nSource:\n$data\n)"));
 
224
        $interfaceBase = (defined($3) ? $3 : "");
 
225
        $interfaceData = (defined($4) ? $4 : die("Parsing error!\nSource:\n$data\n)"));
 
226
 
 
227
        # Fill in known parts of the domClass datastructure now...
 
228
        $dataNode->name($interfaceName);
 
229
        $dataNode->extendedAttributes(parseExtendedAttributes($interfaceExtendedAttributes));
 
230
 
 
231
        # Inheritance detection
 
232
        my @interfaceParents = split(/,/, $interfaceBase);
 
233
        foreach(@interfaceParents) {
 
234
            my $line = $_;
 
235
            $line =~ s/\s*//g;
 
236
 
 
237
            my $arrayRef = $dataNode->parents;
 
238
            push(@$arrayRef, $line);
 
239
        }
 
240
 
 
241
        $interfaceData =~ s/[\n\r]/ /g;
 
242
        my @interfaceMethods = split(/;/, $interfaceData);
 
243
 
 
244
        foreach my $line (@interfaceMethods) {
 
245
            if ($line =~ /attribute/) {
 
246
                $line =~ /$IDLStructure::interfaceAttributeSelector/;
 
247
 
 
248
                my $attributeType = (defined($1) ? $1 : die("Parsing error!\nSource:\n$line\n)"));
 
249
                my $attributeExtendedAttributes = (defined($2) ? $2 : " "); chop($attributeExtendedAttributes);
 
250
 
 
251
                my $attributeDataType = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)"));
 
252
                my $attributeDataName = (defined($4) ? $4 : die("Parsing error!\nSource:\n$line\n)"));
 
253
  
 
254
                ('' =~ /^/); # Reset variables needed for regexp matching
 
255
 
 
256
                $line =~ /$IDLStructure::getterRaisesSelector/;
 
257
                my $getterException = (defined($1) ? $1 : "");
 
258
 
 
259
                $line =~ /$IDLStructure::setterRaisesSelector/;
 
260
                my $setterException = (defined($1) ? $1 : "");
 
261
 
 
262
                my $newDataNode = new domAttribute();
 
263
                $newDataNode->type($attributeType);
 
264
                $newDataNode->signature(new domSignature());
 
265
 
 
266
                $newDataNode->signature->name($attributeDataName);
 
267
                $newDataNode->signature->type($attributeDataType);
 
268
                $newDataNode->signature->extendedAttributes(parseExtendedAttributes($attributeExtendedAttributes));
 
269
 
 
270
                my $arrayRef = $dataNode->attributes;
 
271
                push(@$arrayRef, $newDataNode);
 
272
 
 
273
                print "  |  |>  Attribute; TYPE \"$attributeType\" DATA NAME \"$attributeDataName\" DATA TYPE \"$attributeDataType\" GET EXCEPTION? \"$getterException\" SET EXCEPTION? \"$setterException\"" .
 
274
                    dumpExtendedAttributes("\n  |                 ", $newDataNode->signature->extendedAttributes) . "\n" unless $beQuiet;
 
275
 
 
276
                $getterException =~ s/\s+//g;
 
277
                $setterException =~ s/\s+//g;
 
278
                @{$newDataNode->getterExceptions} = split(/,/, $getterException);
 
279
                @{$newDataNode->setterExceptions} = split(/,/, $setterException);
 
280
            } elsif (($line !~ s/^\s*$//g) and ($line !~ /^\s*const/)) {
 
281
                $line =~ /$IDLStructure::interfaceMethodSelector/ or die "Parsing error!\nSource:\n$line\n)";
 
282
 
 
283
                my $methodExtendedAttributes = (defined($1) ? $1 : " "); chop($methodExtendedAttributes);
 
284
                my $methodType = (defined($2) ? $2 : die("Parsing error!\nSource:\n$line\n)"));
 
285
                my $methodName = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)"));
 
286
                my $methodSignature = (defined($4) ? $4 : die("Parsing error!\nSource:\n$line\n)"));
 
287
 
 
288
                ('' =~ /^/); # Reset variables needed for regexp matching
 
289
 
 
290
                $line =~ /$IDLStructure::raisesSelector/;
 
291
                my $methodException = (defined($1) ? $1 : "");
 
292
 
 
293
                my $newDataNode = new domFunction();
 
294
 
 
295
                $newDataNode->signature(new domSignature());
 
296
                $newDataNode->signature->name($methodName);
 
297
                $newDataNode->signature->type($methodType);
 
298
                $newDataNode->signature->extendedAttributes(parseExtendedAttributes($methodExtendedAttributes));
 
299
 
 
300
                print "  |  |-  Method; TYPE \"$methodType\" NAME \"$methodName\" EXCEPTION? \"$methodException\"" .
 
301
                    dumpExtendedAttributes("\n  |              ", $newDataNode->signature->extendedAttributes) . "\n" unless $beQuiet;
 
302
 
 
303
                $methodException =~ s/\s+//g;
 
304
                @{$newDataNode->raisesExceptions} = split(/,/, $methodException);
 
305
 
 
306
                my @params = split(/,/, $methodSignature);
 
307
                foreach(@params) {
 
308
                    my $line = $_;
 
309
 
 
310
                    $line =~ /$IDLStructure::interfaceParameterSelector/;
 
311
                    my $paramExtendedAttributes = (defined($1) ? $1 : " "); chop($paramExtendedAttributes);
 
312
                    my $paramType = (defined($2) ? $2 : die("Parsing error!\nSource:\n$line\n)"));
 
313
                    my $paramName = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)"));
 
314
 
 
315
                    my $paramDataNode = new domSignature();
 
316
                    $paramDataNode->name($paramName);
 
317
                    $paramDataNode->type($paramType);
 
318
                    $paramDataNode->extendedAttributes(parseExtendedAttributes($paramExtendedAttributes));
 
319
 
 
320
                    my $arrayRef = $newDataNode->parameters;
 
321
                    push(@$arrayRef, $paramDataNode);
 
322
 
 
323
                    print "  |   |>  Param; TYPE \"$paramType\" NAME \"$paramName\"" . 
 
324
                        dumpExtendedAttributes("\n  |              ", $paramDataNode->extendedAttributes) . "\n" unless $beQuiet;          
 
325
                }
 
326
 
 
327
                my $arrayRef = $dataNode->functions;
 
328
                push(@$arrayRef, $newDataNode);
 
329
            } elsif ($line =~ /^\s*const/) {
 
330
                $line =~ /$IDLStructure::constantSelector/;
 
331
                my $constType = (defined($1) ? $1 : die("Parsing error!\nSource:\n$line\n)"));
 
332
                my $constName = (defined($2) ? $2 : die("Parsing error!\nSource:\n$line\n)"));
 
333
                my $constValue = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)"));
 
334
 
 
335
                my $newDataNode = new domConstant();
 
336
                $newDataNode->name($constName);
 
337
                $newDataNode->type($constType);
 
338
                $newDataNode->value($constValue);
 
339
 
 
340
                my $arrayRef = $dataNode->constants;
 
341
                push(@$arrayRef, $newDataNode);
 
342
 
 
343
                print "  |   |>  Constant; TYPE \"$constType\" NAME \"$constName\" VALUE \"$constValue\"\n" unless $beQuiet;
 
344
            }
 
345
        }
 
346
 
 
347
        print "  |----> Interface; NAME \"$interfaceName\"" .
 
348
            dumpExtendedAttributes("\n  |                 ", $dataNode->extendedAttributes) . "\n |-\n |\n" unless $beQuiet;
 
349
    }
 
350
}
 
351
 
 
352
# Internal helper
 
353
sub DetermineParseMode
 
354
{
 
355
    my $object = shift;  
 
356
    my $line = shift;
 
357
 
 
358
    my $mode = MODE_UNDEF;
 
359
    if ($_ =~ /module/) {
 
360
        $mode = MODE_MODULE;
 
361
    } elsif ($_ =~ /interface/) {
 
362
        $mode = MODE_INTERFACE;
 
363
    } elsif ($_ =~ /exception/) {
 
364
        $mode = MODE_EXCEPTION;
 
365
    } elsif ($_ =~ /alias/) {
 
366
        $mode = MODE_ALIAS;
 
367
    }
 
368
 
 
369
    return $mode;
 
370
}
 
371
 
 
372
# Internal helper
 
373
sub ProcessSection
 
374
{
 
375
    my $object = shift;
 
376
  
 
377
    if ($parseMode eq MODE_MODULE) {
 
378
        die ("Two modules in one file! Fatal error!\n") if ($document ne 0);
 
379
        $document = new idlDocument();
 
380
        $object->ParseModule($document);
 
381
    } elsif ($parseMode eq MODE_INTERFACE) {
 
382
        my $node = new domClass();
 
383
        $object->ParseInterface($node, "interface");
 
384
    
 
385
        die ("No module specified! Fatal Error!\n") if ($document eq 0);
 
386
        my $arrayRef = $document->classes;
 
387
        push(@$arrayRef, $node);
 
388
    } elsif($parseMode eq MODE_EXCEPTION) {
 
389
        my $node = new domClass();
 
390
        $object->ParseInterface($node, "exception");
 
391
 
 
392
        die ("No module specified! Fatal Error!\n") if ($document eq 0);
 
393
        my $arrayRef = $document->classes;
 
394
        push(@$arrayRef, $node);
 
395
    } elsif($parseMode eq MODE_ALIAS) {
 
396
        print " |- Trying to parse alias...\n" unless $beQuiet;
 
397
    
 
398
        my $line = join("", @temporaryContent);
 
399
        $line =~ /$IDLStructure::aliasSelector/;
 
400
 
 
401
        my $interfaceName = (defined($1) ? $1 : die("Parsing error!\nSource:\n$line\n)"));
 
402
        my $wrapperName = (defined($2) ? $2 : die("Parsing error!\nSource:\n$line\n)"));
 
403
    
 
404
        print "  |----> Alias; INTERFACE \"$interfaceName\" WRAPPER \"$wrapperName\"\n |-\n |\n" unless $beQuiet;
 
405
 
 
406
        # FIXME: Check if alias is already in aliases
 
407
        my $aliases = $document->aliases;
 
408
        $aliases->{$interfaceName} = $wrapperName;
 
409
    }
 
410
 
 
411
    @temporaryContent = "";
 
412
}
 
413
 
 
414
1;