Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: Source/bindings/scripts/IDLParser.pm

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

Powered by Google App Engine
This is Rietveld 408576698