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