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