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