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