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