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