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

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

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

Powered by Google App Engine
This is Rietveld 408576698