1#
2# KDOM IDL parser
3#
4# Copyright (C) 2005 Nikolas Zimmermann <wildfox@kde.org>
5#
6# This library is free software; you can redistribute it and/or
7# modify it under the terms of the GNU Library General Public
8# License as published by the Free Software Foundation; either
9# version 2 of the License, or (at your option) any later version.
10#
11# This library is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14# Library General Public License for more details.
15#
16# You should have received a copy of the GNU Library General Public License
17# along with this library; see the file COPYING.LIB.  If not, write to
18# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19# Boston, MA 02110-1301, USA.
20#
21
22package IDLParser;
23
24use strict;
25
26use preprocessor;
27use Class::Struct;
28
29use constant StringToken => 0;
30use constant IntegerToken => 1;
31use constant FloatToken => 2;
32use constant IdentifierToken => 3;
33use constant OtherToken => 4;
34use constant EmptyToken => 5;
35
36# Used to represent a parsed IDL document
37struct( idlDocument => {
38    interfaces => '@', # All parsed interfaces
39    enumerations => '@', # All parsed enumerations
40    fileName => '$', # file name
41});
42
43# Used to represent 'interface' blocks
44struct( domInterface => {
45    name => '$',      # Class identifier
46    parents => '@',      # List of strings
47    constants => '@',    # List of 'domConstant'
48    functions => '@',    # List of 'domFunction'
49    anonymousFunctions => '@', # List of 'domFunction'
50    attributes => '@',    # List of 'domAttribute'
51    extendedAttributes => '$', # Extended attributes
52    constructors => '@', # Constructors, list of 'domFunction'
53    customConstructors => '@', # Custom constructors, list of 'domFunction'
54    isException => '$', # Used for exception interfaces
55    isCallback => '$', # Used for callback interfaces
56    isPartial => '$', # Used for partial interfaces
57});
58
59# Used to represent domInterface contents (name of method, signature)
60struct( domFunction => {
61    isStatic => '$',
62    signature => '$',    # Return type/Object name/extended attributes
63    parameters => '@',    # List of 'domSignature'
64});
65
66# Used to represent domInterface contents (name of attribute, signature)
67struct( domAttribute => {
68    type => '$',              # Attribute type (including namespace)
69    isStatic => '$',
70    isReadOnly => '$',
71    signature => '$',         # Attribute signature
72});
73
74# Used to represent a map of 'variable name' <-> 'variable type'
75struct( domSignature => {
76    direction => '$', # Variable direction (in or out)
77    name => '$',      # Variable name
78    type => '$',      # Variable type
79    specials => '@',  # Specials
80    extendedAttributes => '$', # Extended attributes
81    isNullable => '$', # Is variable type Nullable (T?)
82    isVariadic => '$', # Is variable variadic (long... numbers)
83    isOptional => '$', # Is variable optional (optional T)
84});
85
86# Used to represent string constants
87struct( domConstant => {
88    name => '$',      # DOM Constant identifier
89    type => '$',      # Type of data
90    value => '$',      # Constant value
91    extendedAttributes => '$', # Extended attributes
92});
93
94# Used to represent 'enum' definitions
95struct( domEnum => {
96    name => '$', # Enumeration identifier
97    values => '@', # Enumeration values (list of unique strings)
98});
99
100struct( Token => {
101    type => '$', # type of token
102    value => '$' # value of token
103});
104
105struct( Typedef => {
106    extendedAttributes => '$', # Extended attributes
107    type => '$', # Type of data
108});
109
110# Maps 'typedef name' -> Typedef
111my %typedefs = ();
112
113sub new {
114    my $class = shift;
115
116    my $emptyToken = Token->new();
117    $emptyToken->type(EmptyToken);
118    $emptyToken->value("empty");
119
120    my $self = {
121        DocumentContent => "",
122        EmptyToken => $emptyToken,
123        NextToken => $emptyToken,
124        Token => $emptyToken,
125        Line => "",
126        LineNumber => 1
127    };
128    return bless $self, $class;
129}
130
131sub assertTokenValue
132{
133    my $self = shift;
134    my $token = shift;
135    my $value = shift;
136    my $line = shift;
137    my $msg = "Next token should be " . $value . ", but " . $token->value() . " at " . $self->{Line};
138    if (defined ($line)) {
139        $msg .= " IDLParser.pm:" . $line;
140    }
141    die $msg unless $token->value() eq $value;
142}
143
144sub assertTokenType
145{
146    my $self = shift;
147    my $token = shift;
148    my $type = shift;
149    die "Next token's type should be " . $type . ", but " . $token->type() . " at " . $self->{Line} unless $token->type() eq $type;
150}
151
152sub assertUnexpectedToken
153{
154    my $self = shift;
155    my $token = shift;
156    my $line = shift;
157    my $msg = "Unexpected token " . $token . " at " . $self->{Line};
158    if (defined ($line)) {
159        $msg .= " IDLParser.pm:" . $line;
160    }
161    die $msg;
162}
163
164sub assertNoExtendedAttributesInTypedef
165{
166    my $self = shift;
167    my $name = shift;
168    my $line = shift;
169    my $typedef = $typedefs{$name};
170    my $msg = "Unexpected extendedAttributeList in typedef \"$name\" at " . $self->{Line};
171    if (defined ($line)) {
172        $msg .= " IDLParser.pm:" . $line;
173    }
174    die $msg if %{$typedef->extendedAttributes};
175}
176
177sub Parse
178{
179    my $self = shift;
180    my $fileName = shift;
181    my $defines = shift;
182    my $preprocessor = shift;
183
184    my @definitions = ();
185
186    my @lines = applyPreprocessor($fileName, $defines, $preprocessor);
187    $self->{Line} = $lines[0];
188    $self->{DocumentContent} = join(' ', @lines);
189
190    $self->getToken();
191    eval {
192        my $result = $self->parseDefinitions();
193        push(@definitions, @{$result});
194
195        my $next = $self->nextToken();
196        $self->assertTokenType($next, EmptyToken);
197    };
198    die $@ . " in $fileName" if $@;
199
200    my $document = idlDocument->new();
201    $document->fileName($fileName);
202    foreach my $definition (@definitions) {
203        if (ref($definition) eq "domInterface") {
204            push(@{$document->interfaces}, $definition);
205        } elsif (ref($definition) eq "domEnum") {
206            push(@{$document->enumerations}, $definition);
207        } else {
208            die "Unrecognized IDL definition kind: \"" . ref($definition) . "\"";
209        }
210    }
211    return $document;
212}
213
214sub nextToken
215{
216    my $self = shift;
217    return $self->{NextToken};
218}
219
220sub getToken
221{
222    my $self = shift;
223    $self->{Token} = $self->{NextToken};
224    $self->{NextToken} = $self->getTokenInternal();
225    return $self->{Token};
226}
227
228my $whitespaceTokenPattern = '^[\t\n\r ]*[\n\r]';
229my $floatTokenPattern = '^(-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+))';
230my $integerTokenPattern = '^(-?[1-9][0-9]*|-?0[Xx][0-9A-Fa-f]+|-?0[0-7]*)';
231my $stringTokenPattern = '^(\"[^\"]*\")';
232my $identifierTokenPattern = '^([A-Z_a-z][0-9A-Z_a-z]*)';
233my $otherTokenPattern = '^(::|\.\.\.|[^\t\n\r 0-9A-Z_a-z])';
234
235sub getTokenInternal
236{
237    my $self = shift;
238
239    if ($self->{DocumentContent} =~ /$whitespaceTokenPattern/) {
240        $self->{DocumentContent} =~ s/($whitespaceTokenPattern)//;
241        my $skipped = $1;
242        $self->{LineNumber}++ while ($skipped =~ /\n/g);
243        if ($self->{DocumentContent} =~ /^([^\n\r]+)/) {
244            $self->{Line} = $self->{LineNumber} . ":" . $1;
245        } else {
246            $self->{Line} = "Unknown";
247        }
248    }
249    $self->{DocumentContent} =~ s/^([\t\n\r ]+)//;
250    if ($self->{DocumentContent} eq "") {
251        return $self->{EmptyToken};
252    }
253
254    my $token = Token->new();
255    if ($self->{DocumentContent} =~ /$floatTokenPattern/) {
256        $token->type(FloatToken);
257        $token->value($1);
258        $self->{DocumentContent} =~ s/$floatTokenPattern//;
259        return $token;
260    }
261    if ($self->{DocumentContent} =~ /$integerTokenPattern/) {
262        $token->type(IntegerToken);
263        $token->value($1);
264        $self->{DocumentContent} =~ s/$integerTokenPattern//;
265        return $token;
266    }
267    if ($self->{DocumentContent} =~ /$stringTokenPattern/) {
268        $token->type(StringToken);
269        $token->value($1);
270        $self->{DocumentContent} =~ s/$stringTokenPattern//;
271        return $token;
272    }
273    if ($self->{DocumentContent} =~ /$identifierTokenPattern/) {
274        $token->type(IdentifierToken);
275        $token->value($1);
276        $self->{DocumentContent} =~ s/$identifierTokenPattern//;
277        return $token;
278    }
279    if ($self->{DocumentContent} =~ /$otherTokenPattern/) {
280        $token->type(OtherToken);
281        $token->value($1);
282        $self->{DocumentContent} =~ s/$otherTokenPattern//;
283        return $token;
284    }
285    die "Failed in tokenizing at " . $self->{Line};
286}
287
288sub unquoteString
289{
290    my $self = shift;
291    my $quotedString = shift;
292    if ($quotedString =~ /^"([^"]*)"$/) {
293        return $1;
294    }
295    die "Failed to parse string (" . $quotedString . ") at " . $self->{Line};
296}
297
298sub typeHasNullableSuffix
299{
300    my $type = shift;
301    return $type =~ /\?$/;
302}
303
304sub typeRemoveNullableSuffix
305{
306    my $type = shift;
307    $type =~ s/\?//g;
308    return $type;
309}
310
311my $nextAttribute_1 = '^(attribute|inherit|readonly)$';
312my $nextPrimitiveType_1 = '^(int|long|short|unsigned)$';
313my $nextPrimitiveType_2 = '^(double|float|unrestricted)$';
314my $nextArgumentList_1 = '^(\(|::|ByteString|DOMString|Date|\[|any|boolean|byte|double|float|in|int|long|object|octet|optional|sequence|short|unrestricted|unsigned)$';
315my $nextNonAnyType_1 = '^(boolean|byte|double|float|int|long|octet|short|unrestricted|unsigned)$';
316my $nextInterfaceMember_1 = '^(\(|::|ByteString|DOMString|Date|any|attribute|boolean|byte|creator|deleter|double|float|getter|inherit|int|legacycaller|long|object|octet|readonly|sequence|serializer|setter|short|static|stringifier|unrestricted|unsigned|void)$';
317my $nextOptionalIteratorInterfaceOrObject_1 = '^(;|=)$';
318my $nextAttributeOrOperationOrIterator_1 = '^(static|stringifier)$';
319my $nextAttributeOrOperationOrIterator_2 = '^(\(|::|ByteString|DOMString|Date|any|boolean|byte|creator|deleter|double|float|getter|int|legacycaller|long|object|octet|sequence|setter|short|unrestricted|unsigned|void)$';
320my $nextUnrestrictedFloatType_1 = '^(double|float)$';
321my $nextExtendedAttributeRest3_1 = '^(\,|::|\])$';
322my $nextExceptionField_1 = '^(\(|::|ByteString|DOMString|Date|any|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned)$';
323my $nextType_1 = '^(::|ByteString|DOMString|Date|any|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned)$';
324my $nextSpecials_1 = '^(creator|deleter|getter|legacycaller|setter)$';
325my $nextDefinitions_1 = '^(::|callback|dictionary|enum|exception|interface|partial|typedef)$';
326my $nextExceptionMembers_1 = '^(\(|::|ByteString|DOMString|Date|\[|any|boolean|byte|const|double|float|int|long|object|octet|optional|sequence|short|unrestricted|unsigned)$';
327my $nextAttributeRest_1 = '^(attribute|readonly)$';
328my $nextInterfaceMembers_1 = '^(\(|::|ByteString|DOMString|Date|any|attribute|boolean|byte|const|creator|deleter|double|float|getter|inherit|int|legacycaller|long|object|octet|readonly|sequence|serializer|setter|short|static|stringifier|unrestricted|unsigned|void)$';
329my $nextSingleType_1 = '^(::|ByteString|DOMString|Date|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned)$';
330my $nextArgumentName_1 = '^(attribute|callback|const|creator|deleter|dictionary|enum|exception|getter|implements|inherit|interface|legacycaller|partial|serializer|setter|static|stringifier|typedef|unrestricted)$';
331my $nextConstValue_1 = '^(false|true)$';
332my $nextConstValue_2 = '^(-|Infinity|NaN)$';
333my $nextDefinition_1 = '^(callback|interface)$';
334my $nextAttributeOrOperationRest_1 = '^(\(|::|ByteString|DOMString|Date|any|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned|void)$';
335my $nextUnsignedIntegerType_1 = '^(int|long|short)$';
336my $nextDefaultValue_1 = '^(-|Infinity|NaN|false|null|true)$';
337
338
339sub parseDefinitions
340{
341    my $self = shift;
342    my @definitions = ();
343
344    while (1) {
345        my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty();
346        my $next = $self->nextToken();
347        my $definition;
348        if ($next->type() == IdentifierToken || $next->value() =~ /$nextDefinitions_1/) {
349            $definition = $self->parseDefinition($extendedAttributeList);
350        } else {
351            last;
352        }
353        if (defined ($definition)) {
354            push(@definitions, $definition);
355        }
356    }
357    $self->applyTypedefs(\@definitions);
358    return \@definitions;
359}
360
361sub applyTypedefs
362{
363    my $self = shift;
364    my $definitions = shift;
365
366    if (!%typedefs) {
367        return;
368    }
369    foreach my $definition (@$definitions) {
370        if (ref($definition) eq "domInterface") {
371            foreach my $constant (@{$definition->constants}) {
372                if (exists $typedefs{$constant->type}) {
373                    my $typedef = $typedefs{$constant->type};
374                    $self->assertNoExtendedAttributesInTypedef($constant->type, __LINE__);
375                    $constant->type($typedef->type);
376                }
377            }
378            foreach my $attribute (@{$definition->attributes}) {
379                $self->applyTypedefsForSignature($attribute->signature);
380            }
381            foreach my $function (@{$definition->functions}, @{$definition->anonymousFunctions}, @{$definition->constructors}, @{$definition->customConstructors}) {
382                $self->applyTypedefsForSignature($function->signature);
383                foreach my $signature (@{$function->parameters}) {
384                    $self->applyTypedefsForSignature($signature);
385                }
386            }
387        }
388    }
389}
390
391sub applyTypedefsForSignature
392{
393    my $self = shift;
394    my $signature = shift;
395
396    if (!defined ($signature->type)) {
397        return;
398    }
399
400    my $type = $signature->type;
401    $type =~ s/[\?\[\]]+$//g;
402    my $typeSuffix = $signature->type;
403    $typeSuffix =~ s/^[^\?\[\]]+//g;
404    if (exists $typedefs{$type}) {
405        my $typedef = $typedefs{$type};
406        $signature->type($typedef->type . $typeSuffix);
407        copyExtendedAttributes($signature->extendedAttributes, $typedef->extendedAttributes);
408    }
409
410    # Handle union types, sequences and etc.
411    foreach my $name (%typedefs) {
412        if (!exists $typedefs{$name}) {
413            next;
414        }
415        my $typedef = $typedefs{$name};
416        my $regex = '\\b' . $name . '\\b';
417        my $replacement = $typedef->type;
418        my $type = $signature->type;
419        $type =~ s/($regex)/$replacement/g;
420        $signature->type($type);
421    }
422}
423
424sub parseDefinition
425{
426    my $self = shift;
427    my $extendedAttributeList = shift;
428
429    my $next = $self->nextToken();
430    if ($next->value() =~ /$nextDefinition_1/) {
431        return $self->parseCallbackOrInterface($extendedAttributeList);
432    }
433    if ($next->value() eq "partial") {
434        return $self->parsePartial($extendedAttributeList);
435    }
436    if ($next->value() eq "dictionary") {
437        return $self->parseDictionary($extendedAttributeList);
438    }
439    if ($next->value() eq "exception") {
440        return $self->parseException($extendedAttributeList);
441    }
442    if ($next->value() eq "enum") {
443        return $self->parseEnum($extendedAttributeList);
444    }
445    if ($next->value() eq "typedef") {
446        return $self->parseTypedef($extendedAttributeList);
447    }
448    if ($next->type() == IdentifierToken || $next->value() eq "::") {
449        return $self->parseImplementsStatement($extendedAttributeList);
450    }
451    $self->assertUnexpectedToken($next->value(), __LINE__);
452}
453
454sub parseCallbackOrInterface
455{
456    my $self = shift;
457    my $extendedAttributeList = shift;
458
459    my $next = $self->nextToken();
460    if ($next->value() eq "callback") {
461        $self->assertTokenValue($self->getToken(), "callback", __LINE__);
462        return $self->parseCallbackRestOrInterface($extendedAttributeList);
463    }
464    if ($next->value() eq "interface") {
465        return $self->parseInterface($extendedAttributeList);
466    }
467    $self->assertUnexpectedToken($next->value(), __LINE__);
468}
469
470sub parseCallbackRestOrInterface
471{
472    my $self = shift;
473    my $extendedAttributeList = shift;
474
475    my $next = $self->nextToken();
476    if ($next->value() eq "interface") {
477        my $interface = $self->parseInterface($extendedAttributeList);
478        $interface->isCallback(1);
479        return $interface;
480    }
481    if ($next->type() == IdentifierToken) {
482        return $self->parseCallbackRest($extendedAttributeList);
483    }
484    $self->assertUnexpectedToken($next->value(), __LINE__);
485}
486
487sub parseInterface
488{
489    my $self = shift;
490    my $extendedAttributeList = shift;
491
492    my $next = $self->nextToken();
493    if ($next->value() eq "interface") {
494        my $interface = domInterface->new();
495        $self->assertTokenValue($self->getToken(), "interface", __LINE__);
496        my $interfaceNameToken = $self->getToken();
497        $self->assertTokenType($interfaceNameToken, IdentifierToken);
498        $interface->name($interfaceNameToken->value());
499        push(@{$interface->parents}, @{$self->parseInheritance()});
500        $self->assertTokenValue($self->getToken(), "{", __LINE__);
501        my $interfaceMembers = $self->parseInterfaceMembers();
502        $self->assertTokenValue($self->getToken(), "}", __LINE__);
503        $self->assertTokenValue($self->getToken(), ";", __LINE__);
504        applyMemberList($interface, $interfaceMembers);
505        applyExtendedAttributeList($interface, $extendedAttributeList);
506        return $interface;
507    }
508    $self->assertUnexpectedToken($next->value(), __LINE__);
509}
510
511sub parsePartial
512{
513    my $self = shift;
514    my $extendedAttributeList = shift;
515
516    my $next = $self->nextToken();
517    if ($next->value() eq "partial") {
518        $self->assertTokenValue($self->getToken(), "partial", __LINE__);
519        return $self->parsePartialDefinition($extendedAttributeList);
520    }
521    $self->assertUnexpectedToken($next->value(), __LINE__);
522}
523
524sub parsePartialDefinition
525{
526    my $self = shift;
527    my $extendedAttributeList = shift;
528
529    my $next = $self->nextToken();
530    if ($next->value() eq "interface") {
531        my $interface = $self->parseInterface($extendedAttributeList);
532        $interface->isPartial(1);
533        return $interface;
534    }
535    if ($next->value() eq "dictionary") {
536        return $self->parsePartialDictionary($extendedAttributeList);
537    }
538    $self->assertUnexpectedToken($next->value(), __LINE__);
539}
540
541sub parsePartialInterface
542{
543    my $self = shift;
544    my $extendedAttributeList = shift;
545
546    my $next = $self->nextToken();
547    if ($next->value() eq "interface") {
548        $self->assertTokenValue($self->getToken(), "interface", __LINE__);
549        $self->assertTokenType($self->getToken(), IdentifierToken);
550        $self->assertTokenValue($self->getToken(), "{", __LINE__);
551        $self->parseInterfaceMembers();
552        $self->assertTokenValue($self->getToken(), "}", __LINE__);
553        $self->assertTokenValue($self->getToken(), ";", __LINE__);
554        return;
555    }
556    $self->assertUnexpectedToken($next->value(), __LINE__);
557}
558
559sub parseInterfaceMembers
560{
561    my $self = shift;
562    my @interfaceMembers = ();
563
564    while (1) {
565        my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty();
566        my $next = $self->nextToken();
567        my $interfaceMember;
568
569        if ($next->type() == IdentifierToken || $next->value() =~ /$nextInterfaceMembers_1/) {
570            $interfaceMember = $self->parseInterfaceMember($extendedAttributeList);
571        } else {
572            last;
573        }
574        if (defined $interfaceMember) {
575            push(@interfaceMembers, $interfaceMember);
576        }
577    }
578    return \@interfaceMembers;
579}
580
581sub parseInterfaceMember
582{
583    my $self = shift;
584    my $extendedAttributeList = shift;
585
586    my $next = $self->nextToken();
587    if ($next->value() eq "const") {
588        return $self->parseConst($extendedAttributeList);
589    }
590    if ($next->type() == IdentifierToken || $next->value() =~ /$nextInterfaceMember_1/) {
591        return $self->parseAttributeOrOperationOrIterator($extendedAttributeList);
592    }
593    $self->assertUnexpectedToken($next->value(), __LINE__);
594}
595
596sub parseDictionary
597{
598    my $self = shift;
599    my $extendedAttributeList = shift;
600
601    my $next = $self->nextToken();
602    if ($next->value() eq "dictionary") {
603        $self->assertTokenValue($self->getToken(), "dictionary", __LINE__);
604        $self->assertTokenType($self->getToken(), IdentifierToken);
605        $self->parseInheritance();
606        $self->assertTokenValue($self->getToken(), "{", __LINE__);
607        $self->parseDictionaryMembers();
608        $self->assertTokenValue($self->getToken(), "}", __LINE__);
609        $self->assertTokenValue($self->getToken(), ";", __LINE__);
610        return;
611    }
612    $self->assertUnexpectedToken($next->value(), __LINE__);
613}
614
615sub parseDictionaryMembers
616{
617    my $self = shift;
618
619    while (1) {
620        my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty();
621        my $next = $self->nextToken();
622        if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) {
623            $self->parseDictionaryMember($extendedAttributeList);
624        } else {
625            last;
626        }
627    }
628}
629
630sub parseDictionaryMember
631{
632    my $self = shift;
633    my $extendedAttributeList = shift;
634
635    my $next = $self->nextToken();
636    if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) {
637        $self->parseType();
638        $self->assertTokenType($self->getToken(), IdentifierToken);
639        $self->parseDefault();
640        $self->assertTokenValue($self->getToken(), ";", __LINE__);
641        return;
642    }
643    $self->assertUnexpectedToken($next->value(), __LINE__);
644}
645
646sub parsePartialDictionary
647{
648    my $self = shift;
649    my $next = $self->nextToken();
650    if ($next->value() eq "dictionary") {
651        $self->assertTokenValue($self->getToken(), "dictionary", __LINE__);
652        $self->assertTokenType($self->getToken(), IdentifierToken);
653        $self->assertTokenValue($self->getToken(), "{", __LINE__);
654        $self->parseDictionaryMembers();
655        $self->assertTokenValue($self->getToken(), "}", __LINE__);
656        $self->assertTokenValue($self->getToken(), ";", __LINE__);
657        return;
658    }
659    $self->assertUnexpectedToken($next->value(), __LINE__);
660}
661
662sub parseDefault
663{
664    my $self = shift;
665    my $next = $self->nextToken();
666    if ($next->value() eq "=") {
667        $self->assertTokenValue($self->getToken(), "=", __LINE__);
668        return $self->parseDefaultValue();
669    }
670}
671
672sub parseDefaultValue
673{
674    my $self = shift;
675    my $next = $self->nextToken();
676    if ($next->type() == FloatToken || $next->type() == IntegerToken || $next->value() =~ /$nextDefaultValue_1/) {
677        return $self->parseConstValue();
678    }
679    if ($next->type() == StringToken) {
680        return $self->getToken()->value();
681    }
682    $self->assertUnexpectedToken($next->value(), __LINE__);
683}
684
685sub parseException
686{
687    my $self = shift;
688    my $extendedAttributeList = shift;
689
690    my $next = $self->nextToken();
691    if ($next->value() eq "exception") {
692        my $interface = domInterface->new();
693        $self->assertTokenValue($self->getToken(), "exception", __LINE__);
694        my $exceptionNameToken = $self->getToken();
695        $self->assertTokenType($exceptionNameToken, IdentifierToken);
696        $interface->name($exceptionNameToken->value());
697        $interface->isException(1);
698        push(@{$interface->parents}, @{$self->parseInheritance()});
699        $self->assertTokenValue($self->getToken(), "{", __LINE__);
700        my $exceptionMembers = $self->parseExceptionMembers();
701        $self->assertTokenValue($self->getToken(), "}", __LINE__);
702        $self->assertTokenValue($self->getToken(), ";", __LINE__);
703        applyMemberList($interface, $exceptionMembers);
704        applyExtendedAttributeList($interface, $extendedAttributeList);
705        return $interface;
706    }
707    $self->assertUnexpectedToken($next->value(), __LINE__);
708}
709
710sub parseExceptionMembers
711{
712    my $self = shift;
713    my @members = ();
714
715    while (1) {
716        my $next = $self->nextToken();
717        if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionMembers_1/) {
718            my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty();
719            #my $member = $self->parseExceptionMember($extendedAttributeList);
720            my $member = $self->parseInterfaceMember($extendedAttributeList);
721            if (defined ($member)) {
722                push(@members, $member);
723            }
724        } else {
725            last;
726        }
727    }
728    return \@members;
729}
730
731sub parseInheritance
732{
733    my $self = shift;
734    my @parent = ();
735
736    my $next = $self->nextToken();
737    if ($next->value() eq ":") {
738        $self->assertTokenValue($self->getToken(), ":", __LINE__);
739        my $scopedName = $self->parseScopedName();
740        push(@parent, $scopedName);
741        # Multiple inheritance?
742        push(@parent, @{$self->parseIdentifiers()});
743    }
744    return \@parent;
745}
746
747sub parseEnum
748{
749    my $self = shift;
750    my $extendedAttributeList = shift; # ignored: Extended attributes are not applicable to enumerations
751
752    my $next = $self->nextToken();
753    if ($next->value() eq "enum") {
754        my $enum = domEnum->new();
755        $self->assertTokenValue($self->getToken(), "enum", __LINE__);
756        my $enumNameToken = $self->getToken();
757        $self->assertTokenType($enumNameToken, IdentifierToken);
758        $enum->name($enumNameToken->value());
759        $self->assertTokenValue($self->getToken(), "{", __LINE__);
760        push(@{$enum->values}, @{$self->parseEnumValueList()});
761        $self->assertTokenValue($self->getToken(), "}", __LINE__);
762        $self->assertTokenValue($self->getToken(), ";", __LINE__);
763        return $enum;
764    }
765    $self->assertUnexpectedToken($next->value(), __LINE__);
766}
767
768sub parseEnumValueList
769{
770    my $self = shift;
771    my @values = ();
772    my $next = $self->nextToken();
773    if ($next->type() == StringToken) {
774        my $enumValueToken = $self->getToken();
775        $self->assertTokenType($enumValueToken, StringToken);
776        my $enumValue = $self->unquoteString($enumValueToken->value());
777        push(@values, $enumValue);
778        push(@values, @{$self->parseEnumValues()});
779        return \@values;
780    }
781    # value list must be non-empty
782    $self->assertUnexpectedToken($next->value(), __LINE__);
783}
784
785sub parseEnumValues
786{
787    my $self = shift;
788    my @values = ();
789    my $next = $self->nextToken();
790    if ($next->value() eq ",") {
791        $self->assertTokenValue($self->getToken(), ",", __LINE__);
792        my $enumValueToken = $self->getToken();
793        $self->assertTokenType($enumValueToken, StringToken);
794        my $enumValue = $self->unquoteString($enumValueToken->value());
795        push(@values, $enumValue);
796        push(@values, @{$self->parseEnumValues()});
797        return \@values;
798    }
799    return \@values; # empty list (end of enumeration-values)
800}
801
802sub parseCallbackRest
803{
804    my $self = shift;
805    my $extendedAttributeList = shift;
806
807    my $next = $self->nextToken();
808    if ($next->type() == IdentifierToken) {
809        $self->assertTokenType($self->getToken(), IdentifierToken);
810        $self->assertTokenValue($self->getToken(), "=", __LINE__);
811        $self->parseReturnType();
812        $self->assertTokenValue($self->getToken(), "(", __LINE__);
813        $self->parseArgumentList();
814        $self->assertTokenValue($self->getToken(), ")", __LINE__);
815        $self->assertTokenValue($self->getToken(), ";", __LINE__);
816        return;
817    }
818    $self->assertUnexpectedToken($next->value(), __LINE__);
819}
820
821sub parseTypedef
822{
823    my $self = shift;
824    my $extendedAttributeList = shift;
825    die "Extended attributes are not applicable to typedefs themselves: " . $self->{Line} if %{$extendedAttributeList};
826
827    my $next = $self->nextToken();
828    if ($next->value() eq "typedef") {
829        $self->assertTokenValue($self->getToken(), "typedef", __LINE__);
830        my $typedef = Typedef->new();
831        $typedef->extendedAttributes($self->parseExtendedAttributeListAllowEmpty());
832        $typedef->type($self->parseType());
833        my $nameToken = $self->getToken();
834        $self->assertTokenType($nameToken, IdentifierToken);
835        $self->assertTokenValue($self->getToken(), ";", __LINE__);
836        my $name = $nameToken->value();
837        die "typedef redefinition for " . $name . " at " . $self->{Line} if (exists $typedefs{$name} && $typedef->type ne $typedefs{$name}->type);
838        $typedefs{$name} = $typedef;
839        return;
840    }
841    $self->assertUnexpectedToken($next->value(), __LINE__);
842}
843
844sub parseImplementsStatement
845{
846    my $self = shift;
847    my $extendedAttributeList = shift;
848
849    my $next = $self->nextToken();
850    if ($next->type() == IdentifierToken) {
851        $self->parseScopedName();
852        $self->assertTokenValue($self->getToken(), "implements", __LINE__);
853        $self->parseScopedName();
854        $self->assertTokenValue($self->getToken(), ";", __LINE__);
855        return;
856    }
857    $self->assertUnexpectedToken($next->value(), __LINE__);
858}
859
860sub parseConst
861{
862    my $self = shift;
863    my $extendedAttributeList = shift;
864
865    my $next = $self->nextToken();
866    if ($next->value() eq "const") {
867        my $newDataNode = domConstant->new();
868        $self->assertTokenValue($self->getToken(), "const", __LINE__);
869        $newDataNode->type($self->parseConstType());
870        my $constNameToken = $self->getToken();
871        $self->assertTokenType($constNameToken, IdentifierToken);
872        $newDataNode->name($constNameToken->value());
873        $self->assertTokenValue($self->getToken(), "=", __LINE__);
874        $newDataNode->value($self->parseConstValue());
875        $self->assertTokenValue($self->getToken(), ";", __LINE__);
876        $newDataNode->extendedAttributes($extendedAttributeList);
877        return $newDataNode;
878    }
879    $self->assertUnexpectedToken($next->value(), __LINE__);
880}
881
882sub parseConstValue
883{
884    my $self = shift;
885    my $next = $self->nextToken();
886    if ($next->value() =~ /$nextConstValue_1/) {
887        return $self->parseBooleanLiteral();
888    }
889    if ($next->value() eq "null") {
890        $self->assertTokenValue($self->getToken(), "null", __LINE__);
891        return "null";
892    }
893    if ($next->type() == FloatToken || $next->value() =~ /$nextConstValue_2/) {
894        return $self->parseFloatLiteral();
895    }
896    # backward compatibility
897    if ($next->type() == StringToken) {
898        return $self->getToken()->value();
899    }
900    if ($next->type() == IntegerToken) {
901        return $self->getToken()->value();
902    }
903    $self->assertUnexpectedToken($next->value(), __LINE__);
904}
905
906sub parseBooleanLiteral
907{
908    my $self = shift;
909    my $next = $self->nextToken();
910    if ($next->value() eq "true") {
911        $self->assertTokenValue($self->getToken(), "true", __LINE__);
912        return "true";
913    }
914    if ($next->value() eq "false") {
915        $self->assertTokenValue($self->getToken(), "false", __LINE__);
916        return "false";
917    }
918    $self->assertUnexpectedToken($next->value(), __LINE__);
919}
920
921sub parseFloatLiteral
922{
923    my $self = shift;
924    my $next = $self->nextToken();
925    if ($next->value() eq "-") {
926        $self->assertTokenValue($self->getToken(), "-", __LINE__);
927        $self->assertTokenValue($self->getToken(), "Infinity", __LINE__);
928        return "-Infinity";
929    }
930    if ($next->value() eq "Infinity") {
931        $self->assertTokenValue($self->getToken(), "Infinity", __LINE__);
932        return "Infinity";
933    }
934    if ($next->value() eq "NaN") {
935        $self->assertTokenValue($self->getToken(), "NaN", __LINE__);
936        return "NaN";
937    }
938    if ($next->type() == FloatToken) {
939        return $self->getToken()->value();
940    }
941    $self->assertUnexpectedToken($next->value(), __LINE__);
942}
943
944sub parseAttributeOrOperationOrIterator
945{
946    my $self = shift;
947    my $extendedAttributeList = shift;
948
949    my $next = $self->nextToken();
950    if ($next->value() eq "serializer") {
951        return $self->parseSerializer($extendedAttributeList);
952    }
953    if ($next->value() =~ /$nextAttributeOrOperationOrIterator_1/) {
954        my $qualifier = $self->parseQualifier();
955        my $newDataNode = $self->parseAttributeOrOperationRest($extendedAttributeList);
956        if (defined($newDataNode) && $qualifier eq "static") {
957            $newDataNode->isStatic(1);
958        }
959        return $newDataNode;
960    }
961    if ($next->value() =~ /$nextAttribute_1/) {
962        return $self->parseAttribute($extendedAttributeList);
963    }
964    if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperationOrIterator_2/) {
965        return $self->parseOperationOrIterator($extendedAttributeList);
966    }
967    $self->assertUnexpectedToken($next->value(), __LINE__);
968}
969
970sub parseSerializer
971{
972    my $self = shift;
973    my $extendedAttributeList = shift;
974
975    my $next = $self->nextToken();
976    if ($next->value() eq "serializer") {
977        $self->assertTokenValue($self->getToken(), "serializer", __LINE__);
978        return $self->parseSerializerRest($extendedAttributeList);
979    }
980    $self->assertUnexpectedToken($next->value(), __LINE__);
981}
982
983sub parseSerializerRest
984{
985    my $self = shift;
986    my $extendedAttributeList = shift;
987
988    my $next = $self->nextToken();
989    if ($next->value() eq "=") {
990        $self->assertTokenValue($self->getToken(), "=", __LINE__);
991        return $self->parseSerializationPattern($extendedAttributeList);
992    }
993    if ($next->type() == IdentifierToken || $next->value() eq "(") {
994        return $self->parseOperationRest($extendedAttributeList);
995    }
996}
997
998sub parseSerializationPattern
999{
1000    my $self = shift;
1001    my $extendedAttributeList = shift;
1002
1003    my $next = $self->nextToken();
1004    if ($next->value() eq "{") {
1005        $self->assertTokenValue($self->getToken(), "{", __LINE__);
1006        $self->parseSerializationPatternMap();
1007        $self->assertTokenValue($self->getToken(), "}", __LINE__);
1008        return;
1009    }
1010    if ($next->value() eq "[") {
1011        $self->assertTokenValue($self->getToken(), "[", __LINE__);
1012        $self->parseSerializationPatternList();
1013        $self->assertTokenValue($self->getToken(), "]", __LINE__);
1014        return;
1015    }
1016    if ($next->type() == IdentifierToken) {
1017        $self->assertTokenType($self->getToken(), IdentifierToken);
1018        return;
1019    }
1020    $self->assertUnexpectedToken($next->value(), __LINE__);
1021}
1022
1023sub parseSerializationPatternMap
1024{
1025    my $self = shift;
1026    my $next = $self->nextToken();
1027    if ($next->value() eq "getter") {
1028        $self->assertTokenValue($self->getToken(), "getter", __LINE__);
1029        return;
1030    }
1031    if ($next->value() eq "inherit") {
1032        $self->assertTokenValue($self->getToken(), "inherit", __LINE__);
1033        $self->parseIdentifiers();
1034        return;
1035    }
1036    if ($next->type() == IdentifierToken) {
1037        $self->assertTokenType($self->getToken(), IdentifierToken);
1038        $self->parseIdentifiers();
1039    }
1040}
1041
1042sub parseSerializationPatternList
1043{
1044    my $self = shift;
1045    my $next = $self->nextToken();
1046    if ($next->value() eq "getter") {
1047        $self->assertTokenValue($self->getToken(), "getter", __LINE__);
1048        return;
1049    }
1050    if ($next->type() == IdentifierToken) {
1051        $self->assertTokenType($self->getToken(), IdentifierToken);
1052        $self->parseIdentifiers();
1053    }
1054}
1055
1056sub parseIdentifiers
1057{
1058    my $self = shift;
1059    my @idents = ();
1060
1061    while (1) {
1062        my $next = $self->nextToken();
1063        if ($next->value() eq ",") {
1064            $self->assertTokenValue($self->getToken(), ",", __LINE__);
1065            my $token = $self->getToken();
1066            $self->assertTokenType($token, IdentifierToken);
1067            push(@idents, $token->value());
1068        } else {
1069            last;
1070        }
1071    }
1072    return \@idents;
1073}
1074
1075sub parseQualifier
1076{
1077    my $self = shift;
1078
1079    my $next = $self->nextToken();
1080    if ($next->value() eq "static") {
1081        $self->assertTokenValue($self->getToken(), "static", __LINE__);
1082        return "static";
1083    }
1084    if ($next->value() eq "stringifier") {
1085        $self->assertTokenValue($self->getToken(), "stringifier", __LINE__);
1086        return "stringifier";
1087    }
1088    $self->assertUnexpectedToken($next->value(), __LINE__);
1089}
1090
1091sub parseAttributeOrOperationRest
1092{
1093    my $self = shift;
1094    my $extendedAttributeList = shift;
1095
1096    my $next = $self->nextToken();
1097    if ($next->value() =~ /$nextAttributeRest_1/) {
1098        return $self->parseAttributeRest($extendedAttributeList);
1099    }
1100    if ($next->value() eq ";") {
1101        $self->assertTokenValue($self->getToken(), ";", __LINE__);
1102        return;
1103    }
1104    if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperationRest_1/) {
1105        my $returnType = $self->parseReturnType();
1106        my $interface = $self->parseOperationRest($extendedAttributeList);
1107        if (defined ($interface)) {
1108            $interface->signature->type($returnType);
1109        }
1110        return $interface;
1111    }
1112    $self->assertUnexpectedToken($next->value(), __LINE__);
1113}
1114
1115sub parseAttribute
1116{
1117    my $self = shift;
1118    my $extendedAttributeList = shift;
1119
1120    my $next = $self->nextToken();
1121    if ($next->value() =~ /$nextAttribute_1/) {
1122        $self->parseInherit();
1123        return $self->parseAttributeRest($extendedAttributeList);
1124    }
1125    $self->assertUnexpectedToken($next->value(), __LINE__);
1126}
1127
1128sub parseAttributeRest
1129{
1130    my $self = shift;
1131    my $extendedAttributeList = shift;
1132
1133    my $next = $self->nextToken();
1134    if ($next->value() =~ /$nextAttributeRest_1/) {
1135        my $newDataNode = domAttribute->new();
1136        if ($self->parseReadOnly()) {
1137            $newDataNode->type("attribute");
1138            $newDataNode->isReadOnly(1);
1139        } else {
1140            $newDataNode->type("attribute");
1141        }
1142        $self->assertTokenValue($self->getToken(), "attribute", __LINE__);
1143        $newDataNode->signature(domSignature->new());
1144        my $type = $self->parseType();
1145        if (typeHasNullableSuffix($type)) {
1146            $newDataNode->signature->isNullable(1);
1147        } else {
1148            $newDataNode->signature->isNullable(0);
1149        }
1150        # Remove all "?" in the type declaration, e.g. "double?" -> "double".
1151        $newDataNode->signature->type(typeRemoveNullableSuffix($type));
1152        my $token = $self->getToken();
1153        $self->assertTokenType($token, IdentifierToken);
1154        $newDataNode->signature->name($token->value());
1155        $self->assertTokenValue($self->getToken(), ";", __LINE__);
1156        # CustomConstructor may also be used on attributes.
1157        if (defined $extendedAttributeList->{"CustomConstructors"}) {
1158            delete $extendedAttributeList->{"CustomConstructors"};
1159            $extendedAttributeList->{"CustomConstructor"} = "VALUE_IS_MISSING";
1160        }
1161        $newDataNode->signature->extendedAttributes($extendedAttributeList);
1162        return $newDataNode;
1163    }
1164    $self->assertUnexpectedToken($next->value(), __LINE__);
1165}
1166
1167sub parseInherit
1168{
1169    my $self = shift;
1170    my $next = $self->nextToken();
1171    if ($next->value() eq "inherit") {
1172        $self->assertTokenValue($self->getToken(), "inherit", __LINE__);
1173        return 1;
1174    }
1175    return 0;
1176}
1177
1178sub parseReadOnly
1179{
1180    my $self = shift;
1181    my $next = $self->nextToken();
1182    if ($next->value() eq "readonly") {
1183        $self->assertTokenValue($self->getToken(), "readonly", __LINE__);
1184        return 1;
1185    }
1186    return 0;
1187}
1188
1189sub parseOperationOrIterator
1190{
1191    my $self = shift;
1192    my $extendedAttributeList = shift;
1193
1194    my $next = $self->nextToken();
1195    if ($next->value() =~ /$nextSpecials_1/) {
1196        return $self->parseSpecialOperation($extendedAttributeList);
1197    }
1198    if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperationRest_1/) {
1199        my $returnType = $self->parseReturnType();
1200        my $interface = $self->parseOperationOrIteratorRest($extendedAttributeList);
1201        if (defined ($interface)) {
1202            $interface->signature->type($returnType);
1203        }
1204        return $interface;
1205    }
1206    $self->assertUnexpectedToken($next->value(), __LINE__);
1207}
1208
1209sub parseSpecialOperation
1210{
1211    my $self = shift;
1212    my $extendedAttributeList = shift;
1213
1214    my $next = $self->nextToken();
1215    if ($next->value() =~ /$nextSpecials_1/) {
1216        my @specials = ();
1217        push(@specials, @{$self->parseSpecials()});
1218        my $returnType = $self->parseReturnType();
1219        my $interface = $self->parseOperationRest($extendedAttributeList);
1220        if (defined ($interface)) {
1221            $interface->signature->type($returnType);
1222             $interface->signature->specials(\@specials);
1223        }
1224        return $interface;
1225    }
1226    $self->assertUnexpectedToken($next->value(), __LINE__);
1227}
1228
1229sub parseSpecials
1230{
1231    my $self = shift;
1232    my @specials = ();
1233
1234    while (1) {
1235        my $next = $self->nextToken();
1236        if ($next->value() =~ /$nextSpecials_1/) {
1237            push(@specials, $self->parseSpecial());
1238        } else {
1239            last;
1240        }
1241    }
1242    return \@specials;
1243}
1244
1245sub parseSpecial
1246{
1247    my $self = shift;
1248    my $next = $self->nextToken();
1249    if ($next->value() eq "getter") {
1250        $self->assertTokenValue($self->getToken(), "getter", __LINE__);
1251        return "getter";
1252    }
1253    if ($next->value() eq "setter") {
1254        $self->assertTokenValue($self->getToken(), "setter", __LINE__);
1255        return "setter";
1256    }
1257    if ($next->value() eq "creator") {
1258        $self->assertTokenValue($self->getToken(), "creator", __LINE__);
1259        return "creator";
1260    }
1261    if ($next->value() eq "deleter") {
1262        $self->assertTokenValue($self->getToken(), "deleter", __LINE__);
1263        return "deleter";
1264    }
1265    if ($next->value() eq "legacycaller") {
1266        $self->assertTokenValue($self->getToken(), "legacycaller", __LINE__);
1267        return "legacycaller";
1268    }
1269    $self->assertUnexpectedToken($next->value(), __LINE__);
1270}
1271
1272sub parseOperationOrIteratorRest
1273{
1274    my $self = shift;
1275    my $extendedAttributeList = shift;
1276
1277    my $next = $self->nextToken();
1278    if ($next->value() eq "iterator") {
1279        return $self->parseIteratorRest($extendedAttributeList);
1280    }
1281    if ($next->type() == IdentifierToken || $next->value() eq "(") {
1282        return $self->parseOperationRest($extendedAttributeList);
1283    }
1284    $self->assertUnexpectedToken($next->value(), __LINE__);
1285}
1286
1287sub parseIteratorRest
1288{
1289    my $self = shift;
1290    my $extendedAttributeList = shift;
1291
1292    my $next = $self->nextToken();
1293    if ($next->value() eq "iterator") {
1294        $self->assertTokenValue($self->getToken(), "iterator", __LINE__);
1295        $self->parseOptionalIteratorInterfaceOrObject($extendedAttributeList);
1296        $self->assertTokenValue($self->getToken(), ";", __LINE__);
1297        return;
1298    }
1299    $self->assertUnexpectedToken($next->value(), __LINE__);
1300}
1301
1302sub parseOptionalIteratorInterfaceOrObject
1303{
1304    my $self = shift;
1305    my $extendedAttributeList = shift;
1306
1307    my $next = $self->nextToken();
1308    if ($next->value() =~ /$nextOptionalIteratorInterfaceOrObject_1/) {
1309        return $self->parseOptionalIteratorInterface($extendedAttributeList);
1310    }
1311    if ($next->value() eq "object") {
1312        $self->assertTokenValue($self->getToken(), "object", __LINE__);
1313        return;
1314    }
1315    $self->assertUnexpectedToken($next->value(), __LINE__);
1316}
1317
1318sub parseOptionalIteratorInterface
1319{
1320    my $self = shift;
1321    my $extendedAttributeList = shift;
1322
1323    my $next = $self->nextToken();
1324    if ($next->value() eq "=") {
1325        $self->assertTokenValue($self->getToken(), "=", __LINE__);
1326        $self->assertTokenType($self->getToken(), IdentifierToken);
1327    }
1328}
1329
1330sub parseOperationRest
1331{
1332    my $self = shift;
1333    my $extendedAttributeList = shift;
1334
1335    my $next = $self->nextToken();
1336    if ($next->type() == IdentifierToken || $next->value() eq "(") {
1337        my $newDataNode = domFunction->new();
1338        $newDataNode->signature(domSignature->new());
1339        my $name = $self->parseOptionalIdentifier();
1340        $newDataNode->signature->name($name);
1341        $self->assertTokenValue($self->getToken(), "(", $name, __LINE__);
1342        push(@{$newDataNode->parameters}, @{$self->parseArgumentList()});
1343        $self->assertTokenValue($self->getToken(), ")", __LINE__);
1344        $self->assertTokenValue($self->getToken(), ";", __LINE__);
1345        $newDataNode->signature->extendedAttributes($extendedAttributeList);
1346        return $newDataNode;
1347    }
1348    $self->assertUnexpectedToken($next->value(), __LINE__);
1349}
1350
1351sub parseOptionalIdentifier
1352{
1353    my $self = shift;
1354    my $next = $self->nextToken();
1355    if ($next->type() == IdentifierToken) {
1356        my $token = $self->getToken();
1357        return $token->value();
1358    }
1359    return "";
1360}
1361
1362sub parseArgumentList
1363{
1364    my $self = shift;
1365    my @arguments = ();
1366
1367    my $next = $self->nextToken();
1368    if ($next->type() == IdentifierToken || $next->value() =~ /$nextArgumentList_1/) {
1369        push(@arguments, $self->parseArgument());
1370        push(@arguments, @{$self->parseArguments()});
1371    }
1372    return \@arguments;
1373}
1374
1375sub parseArguments
1376{
1377    my $self = shift;
1378    my @arguments = ();
1379
1380    while (1) {
1381        my $next = $self->nextToken();
1382        if ($next->value() eq ",") {
1383            $self->assertTokenValue($self->getToken(), ",", __LINE__);
1384            push(@arguments, $self->parseArgument());
1385        } else {
1386            last;
1387        }
1388    }
1389    return \@arguments;
1390}
1391
1392sub parseArgument
1393{
1394    my $self = shift;
1395    my $next = $self->nextToken();
1396    if ($next->type() == IdentifierToken || $next->value() =~ /$nextArgumentList_1/) {
1397        my $in = $self->parseIn();
1398        my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty();
1399        my $argument = $self->parseOptionalOrRequiredArgument($extendedAttributeList);
1400        $argument->direction($self->parseIn());
1401        return $argument;
1402    }
1403    $self->assertUnexpectedToken($next->value(), __LINE__);
1404}
1405
1406sub parseOptionalOrRequiredArgument
1407{
1408    my $self = shift;
1409    my $extendedAttributeList = shift;
1410
1411    my $paramDataNode = domSignature->new();
1412    $paramDataNode->extendedAttributes($extendedAttributeList);
1413
1414    my $next = $self->nextToken();
1415    if ($next->value() eq "optional") {
1416        $self->assertTokenValue($self->getToken(), "optional", __LINE__);
1417        my $type = $self->parseType();
1418        # domDataNode can only consider last "?".
1419        if (typeHasNullableSuffix($type)) {
1420            $paramDataNode->isNullable(1);
1421        } else {
1422            $paramDataNode->isNullable(0);
1423        }
1424        # Remove all "?" if exists, e.g. "object?[]?" -> "object[]".
1425        $paramDataNode->type(typeRemoveNullableSuffix($type));
1426        $paramDataNode->isOptional(1);
1427        $paramDataNode->name($self->parseArgumentName());
1428        $self->parseDefault();
1429        return $paramDataNode;
1430    }
1431    if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) {
1432        my $type = $self->parseType();
1433        # domDataNode can only consider last "?".
1434        if (typeHasNullableSuffix($type)) {
1435            $paramDataNode->isNullable(1);
1436        } else {
1437            $paramDataNode->isNullable(0);
1438        }
1439        # Remove all "?" if exists, e.g. "object?[]?" -> "object[]".
1440        $paramDataNode->type(typeRemoveNullableSuffix($type));
1441        $paramDataNode->isOptional(0);
1442        $paramDataNode->isVariadic($self->parseEllipsis());
1443        $paramDataNode->name($self->parseArgumentName());
1444        return $paramDataNode;
1445    }
1446    $self->assertUnexpectedToken($next->value(), __LINE__);
1447}
1448
1449sub parseArgumentName
1450{
1451    my $self = shift;
1452    my $next = $self->nextToken();
1453    if ($next->value() =~ /$nextArgumentName_1/) {
1454        return $self->parseArgumentNameKeyword();
1455    }
1456    if ($next->type() == IdentifierToken) {
1457        return $self->getToken()->value();
1458    }
1459    $self->assertUnexpectedToken($next->value(), __LINE__);
1460}
1461
1462sub parseEllipsis
1463{
1464    my $self = shift;
1465    my $next = $self->nextToken();
1466    if ($next->value() eq "...") {
1467        $self->assertTokenValue($self->getToken(), "...", __LINE__);
1468        return 1;
1469    }
1470    return 0;
1471}
1472
1473sub parseExceptionMember
1474{
1475    my $self = shift;
1476    my $extendedAttributeList = shift;
1477
1478    my $next = $self->nextToken();
1479    if ($next->value() eq "const") {
1480        return $self->parseConst($extendedAttributeList);
1481    }
1482    if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) {
1483        return $self->parseExceptionField($extendedAttributeList);
1484    }
1485    $self->assertUnexpectedToken($next->value(), __LINE__);
1486}
1487
1488sub parseExceptionField
1489{
1490    my $self = shift;
1491    my $extendedAttributeList = shift;
1492
1493    my $next = $self->nextToken();
1494    if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) {
1495        my $newDataNode = domAttribute->new();
1496        $newDataNode->type("attribute");
1497        $newDataNode->isReadOnly(1);
1498        $newDataNode->signature(domSignature->new());
1499        $newDataNode->signature->type($self->parseType());
1500        my $token = $self->getToken();
1501        $self->assertTokenType($token, IdentifierToken);
1502        $newDataNode->signature->name($token->value());
1503        $self->assertTokenValue($self->getToken(), ";", __LINE__);
1504        $newDataNode->signature->extendedAttributes($extendedAttributeList);
1505        return $newDataNode;
1506    }
1507    $self->assertUnexpectedToken($next->value(), __LINE__);
1508}
1509
1510sub parseExtendedAttributeListAllowEmpty
1511{
1512    my $self = shift;
1513    my $next = $self->nextToken();
1514    if ($next->value() eq "[") {
1515        return $self->parseExtendedAttributeList();
1516    }
1517    return {};
1518}
1519
1520sub copyExtendedAttributes
1521{
1522    my $extendedAttributeList = shift;
1523    my $attr = shift;
1524
1525    for my $key (keys %{$attr}) {
1526        if ($key eq "Constructor") {
1527            push(@{$extendedAttributeList->{"Constructors"}}, $attr->{$key});
1528        } elsif ($key eq "Constructors") {
1529            my @constructors = @{$attr->{$key}};
1530            foreach my $constructor (@constructors) {
1531                push(@{$extendedAttributeList->{"Constructors"}}, $constructor);
1532            }
1533        } elsif ($key eq "CustomConstructor") {
1534            push(@{$extendedAttributeList->{"CustomConstructors"}}, $attr->{$key});
1535        } elsif ($key eq "CustomConstructors") {
1536           my @customConstructors = @{$attr->{$key}};
1537            foreach my $customConstructor (@customConstructors) {
1538                push(@{$extendedAttributeList->{"CustomConstructors"}}, $customConstructor);
1539            }
1540        } else {
1541            $extendedAttributeList->{$key} = $attr->{$key};
1542        }
1543    }
1544}
1545
1546sub parseExtendedAttributeList
1547{
1548    my $self = shift;
1549    my $next = $self->nextToken();
1550    if ($next->value() eq "[") {
1551        $self->assertTokenValue($self->getToken(), "[", __LINE__);
1552        my $extendedAttributeList = {};
1553        my $attr = $self->parseExtendedAttribute();
1554        copyExtendedAttributes($extendedAttributeList, $attr);
1555        $attr = $self->parseExtendedAttributes();
1556        copyExtendedAttributes($extendedAttributeList, $attr);
1557        $self->assertTokenValue($self->getToken(), "]", __LINE__);
1558        return $extendedAttributeList;
1559    }
1560    $self->assertUnexpectedToken($next->value(), __LINE__);
1561}
1562
1563sub parseExtendedAttributes
1564{
1565    my $self = shift;
1566    my $extendedAttributeList = {};
1567
1568    while (1) {
1569        my $next = $self->nextToken();
1570        if ($next->value() eq ",") {
1571            $self->assertTokenValue($self->getToken(), ",", __LINE__);
1572            my $attr = $self->parseExtendedAttribute2();
1573            copyExtendedAttributes($extendedAttributeList, $attr);
1574        } else {
1575            last;
1576        }
1577    }
1578    return $extendedAttributeList;
1579}
1580
1581sub parseExtendedAttribute
1582{
1583    my $self = shift;
1584    my $next = $self->nextToken();
1585    if ($next->type() == IdentifierToken || $next->value() eq "::") {
1586        my $scopedName = $self->parseScopedName();
1587        return $self->parseExtendedAttributeRest($scopedName);
1588    }
1589    # backward compatibility. Spec doesn' allow "[]". But WebKit requires.
1590    if ($next->value() eq ']') {
1591        return {};
1592    }
1593    $self->assertUnexpectedToken($next->value(), __LINE__);
1594}
1595
1596sub parseExtendedAttribute2
1597{
1598    my $self = shift;
1599    my $next = $self->nextToken();
1600    if ($next->type() == IdentifierToken || $next->value() eq "::") {
1601        my $scopedName = $self->parseScopedName();
1602        return $self->parseExtendedAttributeRest($scopedName);
1603    }
1604    return {};
1605}
1606
1607sub parseExtendedAttributeRest
1608{
1609    my $self = shift;
1610    my $name = shift;
1611    my $attrs = {};
1612
1613    my $next = $self->nextToken();
1614    if ($next->value() eq "(") {
1615        $self->assertTokenValue($self->getToken(), "(", __LINE__);
1616        $attrs->{$name} = $self->parseArgumentList();
1617        $self->assertTokenValue($self->getToken(), ")", __LINE__);
1618        return $attrs;
1619    }
1620    if ($next->value() eq "=") {
1621        $self->assertTokenValue($self->getToken(), "=", __LINE__);
1622        $attrs->{$name} = $self->parseExtendedAttributeRest2();
1623        return $attrs;
1624    }
1625
1626    if ($name eq "Constructor" || $name eq "CustomConstructor") {
1627        $attrs->{$name} = [];
1628    } else {
1629        $attrs->{$name} = "VALUE_IS_MISSING";
1630    }
1631    return $attrs;
1632}
1633
1634sub parseExtendedAttributeRest2
1635{
1636    my $self = shift;
1637    my $next = $self->nextToken();
1638    if ($next->type() == IdentifierToken || $next->value() eq "::") {
1639        my $scopedName = $self->parseScopedName();
1640        return $self->parseExtendedAttributeRest3($scopedName);
1641    }
1642    if ($next->type() == IntegerToken) {
1643        my $token = $self->getToken();
1644        return $token->value();
1645    }
1646    $self->assertUnexpectedToken($next->value(), __LINE__);
1647}
1648
1649sub parseExtendedAttributeRest3
1650{
1651    my $self = shift;
1652    my $name = shift;
1653
1654    my $next = $self->nextToken();
1655    if ($next->value() eq "&") {
1656        $self->assertTokenValue($self->getToken(), "&", __LINE__);
1657        my $rightValue = $self->parseScopedName();
1658        return $name . "&" . $rightValue;
1659    }
1660    if ($next->value() eq "|") {
1661        $self->assertTokenValue($self->getToken(), "|", __LINE__);
1662        my $rightValue = $self->parseScopedName();
1663        return $name . "|" . $rightValue;
1664    }
1665    if ($next->value() eq "(") {
1666        my $attr = {};
1667        $self->assertTokenValue($self->getToken(), "(", __LINE__);
1668        $attr->{$name} = $self->parseArgumentList();
1669        $self->assertTokenValue($self->getToken(), ")", __LINE__);
1670        return $attr;
1671    }
1672    if ($next->type() == IdentifierToken || $next->value() =~ /$nextExtendedAttributeRest3_1/) {
1673        my @names = ();
1674        push(@names, $name);
1675        push(@names, @{$self->parseScopedNameListNoComma()});
1676        return join(' ', @names);
1677    }
1678    $self->assertUnexpectedToken($next->value());
1679}
1680
1681sub parseScopedNameListNoComma
1682{
1683    my $self = shift;
1684    my @names = ();
1685
1686    while (1) {
1687        my $next = $self->nextToken();
1688        if ($next->type() == IdentifierToken || $next->value() eq "::") {
1689            push(@names, $self->parseScopedName());
1690        } else {
1691            last;
1692        }
1693    }
1694    return \@names;
1695}
1696
1697sub parseArgumentNameKeyword
1698{
1699    my $self = shift;
1700    my $next = $self->nextToken();
1701    if ($next->value() eq "attribute") {
1702        return $self->getToken()->value();
1703    }
1704    if ($next->value() eq "callback") {
1705        return $self->getToken()->value();
1706    }
1707    if ($next->value() eq "const") {
1708        return $self->getToken()->value();
1709    }
1710    if ($next->value() eq "creator") {
1711        return $self->getToken()->value();
1712    }
1713    if ($next->value() eq "deleter") {
1714        return $self->getToken()->value();
1715    }
1716    if ($next->value() eq "dictionary") {
1717        return $self->getToken()->value();
1718    }
1719    if ($next->value() eq "enum") {
1720        return $self->getToken()->value();
1721    }
1722    if ($next->value() eq "exception") {
1723        return $self->getToken()->value();
1724    }
1725    if ($next->value() eq "getter") {
1726        return $self->getToken()->value();
1727    }
1728    if ($next->value() eq "implements") {
1729        return $self->getToken()->value();
1730    }
1731    if ($next->value() eq "inherit") {
1732        return $self->getToken()->value();
1733    }
1734    if ($next->value() eq "interface") {
1735        return $self->getToken()->value();
1736    }
1737    if ($next->value() eq "legacycaller") {
1738        return $self->getToken()->value();
1739    }
1740    if ($next->value() eq "partial") {
1741        return $self->getToken()->value();
1742    }
1743    if ($next->value() eq "serializer") {
1744        return $self->getToken()->value();
1745    }
1746    if ($next->value() eq "setter") {
1747        return $self->getToken()->value();
1748    }
1749    if ($next->value() eq "static") {
1750        return $self->getToken()->value();
1751    }
1752    if ($next->value() eq "stringifier") {
1753        return $self->getToken()->value();
1754    }
1755    if ($next->value() eq "typedef") {
1756        return $self->getToken()->value();
1757    }
1758    if ($next->value() eq "unrestricted") {
1759        return $self->getToken()->value();
1760    }
1761    $self->assertUnexpectedToken($next->value(), __LINE__);
1762}
1763
1764sub parseType
1765{
1766    my $self = shift;
1767    my $next = $self->nextToken();
1768    if ($next->value() eq "(") {
1769        $self->parseUnionType();
1770        $self->parseTypeSuffix();
1771        return;
1772    }
1773    if ($next->type() == IdentifierToken || $next->value() =~ /$nextType_1/) {
1774        return $self->parseSingleType();
1775    }
1776    $self->assertUnexpectedToken($next->value(), __LINE__);
1777}
1778
1779sub parseSingleType
1780{
1781    my $self = shift;
1782    my $next = $self->nextToken();
1783    if ($next->value() eq "any") {
1784        $self->assertTokenValue($self->getToken(), "any", __LINE__);
1785        return "any" . $self->parseTypeSuffixStartingWithArray();
1786    }
1787    if ($next->type() == IdentifierToken || $next->value() =~ /$nextSingleType_1/) {
1788        return $self->parseNonAnyType();
1789    }
1790    $self->assertUnexpectedToken($next->value(), __LINE__);
1791}
1792
1793sub parseUnionType
1794{
1795    my $self = shift;
1796    my $next = $self->nextToken();
1797    if ($next->value() eq "(") {
1798        $self->assertTokenValue($self->getToken(), "(", __LINE__);
1799        $self->parseUnionMemberType();
1800        $self->assertTokenValue($self->getToken(), "or", __LINE__);
1801        $self->parseUnionMemberType();
1802        $self->parseUnionMemberTypes();
1803        $self->assertTokenValue($self->getToken(), ")", __LINE__);
1804        return;
1805    }
1806    $self->assertUnexpectedToken($next->value(), __LINE__);
1807}
1808
1809sub parseUnionMemberType
1810{
1811    my $self = shift;
1812    my $next = $self->nextToken();
1813    if ($next->value() eq "(") {
1814        $self->parseUnionType();
1815        $self->parseTypeSuffix();
1816        return;
1817    }
1818    if ($next->value() eq "any") {
1819        $self->assertTokenValue($self->getToken(), "any", __LINE__);
1820        $self->assertTokenValue($self->getToken(), "[", __LINE__);
1821        $self->assertTokenValue($self->getToken(), "]", __LINE__);
1822        $self->parseTypeSuffix();
1823        return;
1824    }
1825    if ($next->type() == IdentifierToken || $next->value() =~ /$nextSingleType_1/) {
1826        $self->parseNonAnyType();
1827        return;
1828    }
1829    $self->assertUnexpectedToken($next->value(), __LINE__);
1830}
1831
1832sub parseUnionMemberTypes
1833{
1834    my $self = shift;
1835    my $next = $self->nextToken();
1836    if ($next->value() eq "or") {
1837        $self->assertTokenValue($self->getToken(), "or", __LINE__);
1838        $self->parseUnionMemberType();
1839        $self->parseUnionMemberTypes();
1840    }
1841}
1842
1843sub parseNonAnyType
1844{
1845    my $self = shift;
1846    my $next = $self->nextToken();
1847    if ($next->value() =~ /$nextNonAnyType_1/) {
1848        return $self->parsePrimitiveType() . $self->parseTypeSuffix();
1849    }
1850    if ($next->value() eq "ByteString") {
1851        $self->assertTokenValue($self->getToken(), "ByteString", __LINE__);
1852        return "ByteString" . $self->parseTypeSuffix();
1853    }
1854    if ($next->value() eq "DOMString") {
1855        $self->assertTokenValue($self->getToken(), "DOMString", __LINE__);
1856        return "DOMString" . $self->parseTypeSuffix();
1857    }
1858    if ($next->value() eq "sequence") {
1859        $self->assertTokenValue($self->getToken(), "sequence", __LINE__);
1860        $self->assertTokenValue($self->getToken(), "<", __LINE__);
1861        my $type = $self->parseType();
1862        $self->assertTokenValue($self->getToken(), ">", __LINE__);
1863        return "sequence<" . $type . ">" . $self->parseNull();
1864    }
1865    if ($next->value() eq "object") {
1866        $self->assertTokenValue($self->getToken(), "object", __LINE__);
1867        return "object" . $self->parseTypeSuffix();
1868    }
1869    if ($next->value() eq "Date") {
1870        $self->assertTokenValue($self->getToken(), "Date", __LINE__);
1871        return "Date" . $self->parseTypeSuffix();
1872    }
1873    if ($next->type() == IdentifierToken || $next->value() eq "::") {
1874        my $name = $self->parseScopedName();
1875        return $name . $self->parseTypeSuffix();
1876    }
1877    $self->assertUnexpectedToken($next->value(), __LINE__);
1878}
1879
1880sub parseConstType
1881{
1882    my $self = shift;
1883    my $next = $self->nextToken();
1884    if ($next->value() =~ /$nextNonAnyType_1/) {
1885        return $self->parsePrimitiveType() . $self->parseNull();
1886    }
1887    if ($next->type() == IdentifierToken) {
1888        my $token = $self->getToken();
1889        return $token->value() . $self->parseNull();
1890    }
1891    $self->assertUnexpectedToken($next->value(), __LINE__);
1892}
1893
1894sub parsePrimitiveType
1895{
1896    my $self = shift;
1897    my $next = $self->nextToken();
1898    if ($next->value() =~ /$nextPrimitiveType_1/) {
1899        return $self->parseUnsignedIntegerType();
1900    }
1901    if ($next->value() =~ /$nextPrimitiveType_2/) {
1902        return $self->parseUnrestrictedFloatType();
1903    }
1904    if ($next->value() eq "boolean") {
1905        $self->assertTokenValue($self->getToken(), "boolean", __LINE__);
1906        return "boolean";
1907    }
1908    if ($next->value() eq "byte") {
1909        $self->assertTokenValue($self->getToken(), "byte", __LINE__);
1910        return "byte";
1911    }
1912    if ($next->value() eq "octet") {
1913        $self->assertTokenValue($self->getToken(), "octet", __LINE__);
1914        return "octet";
1915    }
1916    $self->assertUnexpectedToken($next->value(), __LINE__);
1917}
1918
1919sub parseUnrestrictedFloatType
1920{
1921    my $self = shift;
1922    my $next = $self->nextToken();
1923    if ($next->value() eq "unrestricted") {
1924        $self->assertTokenValue($self->getToken(), "unrestricted", __LINE__);
1925        return "unrestricted " . $self->parseFloatType();
1926    }
1927    if ($next->value() =~ /$nextUnrestrictedFloatType_1/) {
1928        return $self->parseFloatType();
1929    }
1930    $self->assertUnexpectedToken($next->value(), __LINE__);
1931}
1932
1933sub parseFloatType
1934{
1935    my $self = shift;
1936    my $next = $self->nextToken();
1937    if ($next->value() eq "float") {
1938        $self->assertTokenValue($self->getToken(), "float", __LINE__);
1939        return "float";
1940    }
1941    if ($next->value() eq "double") {
1942        $self->assertTokenValue($self->getToken(), "double", __LINE__);
1943        return "double";
1944    }
1945    $self->assertUnexpectedToken($next->value(), __LINE__);
1946}
1947
1948sub parseUnsignedIntegerType
1949{
1950    my $self = shift;
1951    my $next = $self->nextToken();
1952    if ($next->value() eq "unsigned") {
1953        $self->assertTokenValue($self->getToken(), "unsigned", __LINE__);
1954        return "unsigned " . $self->parseIntegerType();
1955    }
1956    if ($next->value() =~ /$nextUnsignedIntegerType_1/) {
1957        return $self->parseIntegerType();
1958    }
1959    $self->assertUnexpectedToken($next->value(), __LINE__);
1960}
1961
1962sub parseIntegerType
1963{
1964    my $self = shift;
1965    my $next = $self->nextToken();
1966    if ($next->value() eq "short") {
1967        $self->assertTokenValue($self->getToken(), "short", __LINE__);
1968        return "short";
1969    }
1970    if ($next->value() eq "int") {
1971        $self->assertTokenValue($self->getToken(), "int", __LINE__);
1972        return "int";
1973    }
1974    if ($next->value() eq "long") {
1975        $self->assertTokenValue($self->getToken(), "long", __LINE__);
1976        if ($self->parseOptionalLong()) {
1977            return "long long";
1978        }
1979        return "long";
1980    }
1981    $self->assertUnexpectedToken($next->value(), __LINE__);
1982}
1983
1984sub parseOptionalLong
1985{
1986    my $self = shift;
1987    my $next = $self->nextToken();
1988    if ($next->value() eq "long") {
1989        $self->assertTokenValue($self->getToken(), "long", __LINE__);
1990        return 1;
1991    }
1992    return 0;
1993}
1994
1995sub parseTypeSuffix
1996{
1997    my $self = shift;
1998    my $next = $self->nextToken();
1999    if ($next->value() eq "[") {
2000        $self->assertTokenValue($self->getToken(), "[", __LINE__);
2001        $self->assertTokenValue($self->getToken(), "]", __LINE__);
2002        return "[]" . $self->parseTypeSuffix();
2003    }
2004    if ($next->value() eq "?") {
2005        $self->assertTokenValue($self->getToken(), "?", __LINE__);
2006        return "?" . $self->parseTypeSuffixStartingWithArray();
2007    }
2008    return "";
2009}
2010
2011sub parseTypeSuffixStartingWithArray
2012{
2013    my $self = shift;
2014    my $next = $self->nextToken();
2015    if ($next->value() eq "[") {
2016        $self->assertTokenValue($self->getToken(), "[", __LINE__);
2017        $self->assertTokenValue($self->getToken(), "]", __LINE__);
2018        return "[]" . $self->parseTypeSuffix();
2019    }
2020    return "";
2021}
2022
2023sub parseNull
2024{
2025    my $self = shift;
2026    my $next = $self->nextToken();
2027    if ($next->value() eq "?") {
2028        $self->assertTokenValue($self->getToken(), "?", __LINE__);
2029        return "?";
2030    }
2031    return "";
2032}
2033
2034sub parseReturnType
2035{
2036    my $self = shift;
2037    my $next = $self->nextToken();
2038    if ($next->value() eq "void") {
2039        $self->assertTokenValue($self->getToken(), "void", __LINE__);
2040        return "void";
2041    }
2042    if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) {
2043        return $self->parseType();
2044    }
2045    $self->assertUnexpectedToken($next->value(), __LINE__);
2046}
2047
2048sub parseIn
2049{
2050    my $self = shift;
2051    my $next = $self->nextToken();
2052    if ($next->value() eq "in") {
2053        $self->assertTokenValue($self->getToken(), "in", __LINE__);
2054        return "in";
2055    }
2056    return "";
2057}
2058
2059sub parseOptionalSemicolon
2060{
2061    my $self = shift;
2062    my $next = $self->nextToken();
2063    if ($next->value() eq ";") {
2064        $self->assertTokenValue($self->getToken(), ";", __LINE__);
2065    }
2066}
2067
2068sub parseScopedName
2069{
2070    my $self = shift;
2071    my $next = $self->nextToken();
2072    if ($next->value() eq "::") {
2073        return $self->parseAbsoluteScopedName();
2074    }
2075    if ($next->type() == IdentifierToken) {
2076        return $self->parseRelativeScopedName();
2077    }
2078    $self->assertUnexpectedToken($next->value());
2079}
2080
2081sub parseAbsoluteScopedName
2082{
2083    my $self = shift;
2084    my $next = $self->nextToken();
2085    if ($next->value() eq "::") {
2086        $self->assertTokenValue($self->getToken(), "::");
2087        my $token = $self->getToken();
2088        $self->assertTokenType($token, IdentifierToken);
2089        return "::" . $token->value() . $self->parseScopedNameParts();
2090    }
2091    $self->assertUnexpectedToken($next->value());
2092}
2093
2094sub parseRelativeScopedName
2095{
2096    my $self = shift;
2097    my $next = $self->nextToken();
2098    if ($next->type() == IdentifierToken) {
2099        my $token = $self->getToken();
2100        return $token->value() . $self->parseScopedNameParts();
2101    }
2102    $self->assertUnexpectedToken($next->value());
2103}
2104
2105sub parseScopedNameParts
2106{
2107    my $self = shift;
2108    my @names = ();
2109
2110    while (1) {
2111        my $next = $self->nextToken();
2112        if ($next->value() eq "::") {
2113            $self->assertTokenValue($self->getToken(), "::");
2114            push(@names, "::");
2115            my $token = $self->getToken();
2116            $self->assertTokenType($token, IdentifierToken);
2117            push(@names, $token->value());
2118        } else {
2119            last;
2120        }
2121    }
2122    return join("", @names);
2123}
2124
2125sub parseScopedNameList
2126{
2127    my $self = shift;
2128    my $next = $self->nextToken();
2129    if ($next->type() == IdentifierToken || $next->value() eq "::") {
2130        my @names = ();
2131        push(@names, $self->parseScopedName());
2132        push(@names, @{$self->parseScopedNames()});
2133        return \@names;
2134    }
2135    $self->assertUnexpectedToken($next->value(), __LINE__);
2136}
2137
2138sub parseScopedNames
2139{
2140    my $self = shift;
2141    my @names = ();
2142
2143    while (1) {
2144        my $next = $self->nextToken();
2145        if ($next->value() eq ",") {
2146            $self->assertTokenValue($self->getToken(), ",");
2147            push(@names, $self->parseScopedName());
2148        } else {
2149            last;
2150        }
2151    }
2152    return \@names;
2153}
2154
2155sub applyMemberList
2156{
2157    my $interface = shift;
2158    my $members = shift;
2159
2160    for my $item (@{$members}) {
2161        if (ref($item) eq "domAttribute") {
2162            push(@{$interface->attributes}, $item);
2163            next;
2164        }
2165        if (ref($item) eq "domConstant") {
2166            push(@{$interface->constants}, $item);
2167            next;
2168        }
2169        if (ref($item) eq "domFunction") {
2170            if ($item->signature->name eq "") {
2171                push(@{$interface->anonymousFunctions}, $item);
2172            } else {
2173                push(@{$interface->functions}, $item);
2174            }
2175            next;
2176        }
2177    }
2178}
2179
2180sub applyExtendedAttributeList
2181{
2182    my $interface = shift;
2183    my $extendedAttributeList = shift;
2184
2185    if (defined $extendedAttributeList->{"Constructors"}) {
2186        my @constructorParams = @{$extendedAttributeList->{"Constructors"}};
2187        my $index = (@constructorParams == 1) ? 0 : 1;
2188        foreach my $param (@constructorParams) {
2189            my $constructor = domFunction->new();
2190            $constructor->signature(domSignature->new());
2191            $constructor->signature->name("Constructor");
2192            $constructor->signature->extendedAttributes($extendedAttributeList);
2193            $constructor->parameters($param);
2194            $constructor->{overloadedIndex} = $index++;
2195            push(@{$interface->constructors}, $constructor);
2196        }
2197        delete $extendedAttributeList->{"Constructors"};
2198        $extendedAttributeList->{"Constructor"} = "VALUE_IS_MISSING";
2199    } elsif (defined $extendedAttributeList->{"NamedConstructor"}) {
2200        my $newDataNode = domFunction->new();
2201        $newDataNode->signature(domSignature->new());
2202        $newDataNode->signature->name("NamedConstructor");
2203        $newDataNode->signature->extendedAttributes($extendedAttributeList);
2204        my %attributes = %{$extendedAttributeList->{"NamedConstructor"}};
2205        my @attributeKeys = keys (%attributes);
2206        my $constructorName = $attributeKeys[0];
2207        push(@{$newDataNode->parameters}, @{$attributes{$constructorName}});
2208        $extendedAttributeList->{"NamedConstructor"} = $constructorName;
2209        push(@{$interface->constructors}, $newDataNode);
2210    }
2211    if (defined $extendedAttributeList->{"CustomConstructors"}) {
2212        my @customConstructorParams = @{$extendedAttributeList->{"CustomConstructors"}};
2213        my $index = (@customConstructorParams == 1) ? 0 : 1;
2214        foreach my $param (@customConstructorParams) {
2215            my $customConstructor = domFunction->new();
2216            $customConstructor->signature(domSignature->new());
2217            $customConstructor->signature->name("CustomConstructor");
2218            $customConstructor->signature->extendedAttributes($extendedAttributeList);
2219            $customConstructor->parameters($param);
2220            $customConstructor->{overloadedIndex} = $index++;
2221            push(@{$interface->customConstructors}, $customConstructor);
2222        }
2223        delete $extendedAttributeList->{"CustomConstructors"};
2224        $extendedAttributeList->{"CustomConstructor"} = "VALUE_IS_MISSING";
2225    }
2226    $interface->extendedAttributes($extendedAttributeList);
2227}
2228
22291;
2230
2231