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