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