summaryrefslogtreecommitdiff
path: root/Source/WebCore/bindings/scripts/IDLParser.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/bindings/scripts/IDLParser.pm')
-rw-r--r--Source/WebCore/bindings/scripts/IDLParser.pm1245
1 files changed, 736 insertions, 509 deletions
diff --git a/Source/WebCore/bindings/scripts/IDLParser.pm b/Source/WebCore/bindings/scripts/IDLParser.pm
index 319f62bae..2107b94a5 100644
--- a/Source/WebCore/bindings/scripts/IDLParser.pm
+++ b/Source/WebCore/bindings/scripts/IDLParser.pm
@@ -23,6 +23,9 @@ package IDLParser;
use strict;
+use Carp qw<longmess>;
+use Data::Dumper;
+
use preprocessor;
use Class::Struct;
@@ -34,68 +37,132 @@ use constant OtherToken => 4;
use constant EmptyToken => 5;
# Used to represent a parsed IDL document
-struct( idlDocument => {
- interfaces => '@', # All parsed interfaces
- enumerations => '@', # All parsed enumerations
- fileName => '$', # file name
+struct( IDLDocument => {
+ interfaces => '@', # List of 'IDLInterface'
+ enumerations => '@', # List of 'IDLEnum'
+ dictionaries => '@', # List of 'IDLDictionary'
+ callbackFunctions => '@', # List of 'IDLCallbackFunction'
+ fileName => '$',
+});
+
+# https://heycam.github.io/webidl/#idl-types
+struct( IDLType => {
+ name => '$', # Type identifier
+ isNullable => '$', # Is the type Nullable (T?)
+ isUnion => '$', # Is the type a union (T or U)
+ subtypes => '@', # Array of subtypes, only valid if isUnion or sequence
});
# Used to represent 'interface' blocks
-struct( domInterface => {
- name => '$', # Class identifier
- parent => '$', # Parent class identifier
- parents => '@', # Parent class identifiers (Kept for compatibility with ObjC bindings)
- constants => '@', # List of 'domConstant'
- functions => '@', # List of 'domFunction'
- anonymousFunctions => '@', # List of 'domFunction'
- attributes => '@', # List of 'domAttribute'
- extendedAttributes => '$', # Extended attributes
- constructors => '@', # Constructors, list of 'domFunction'
- customConstructors => '@', # Custom constructors, list of 'domFunction'
+struct( IDLInterface => {
+ type => 'IDLType',
+ parentType => 'IDLType',
+ constants => '@', # List of 'IDLConstant'
+ functions => '@', # List of 'IDLOperation'
+ anonymousFunctions => '@', # List of 'IDLOperation'
+ attributes => '@', # List of 'IDLAttribute'
+ constructors => '@', # Constructors, list of 'IDLOperation'
+ customConstructors => '@', # Custom constructors, list of 'IDLOperation'
isException => '$', # Used for exception interfaces
isCallback => '$', # Used for callback interfaces
isPartial => '$', # Used for partial interfaces
+ iterable => '$', # Used for iterable interfaces
+ serializable => '$', # Used for serializable interfaces
+ extendedAttributes => '$',
});
-# Used to represent domInterface contents (name of method, signature)
-struct( domFunction => {
+# Used to represent an argument to a IDLOperation.
+struct( IDLArgument => {
+ name => '$',
+ type => 'IDLType',
+ isVariadic => '$',
+ isOptional => '$',
+ default => '$',
+ extendedAttributes => '$',
+});
+
+# https://heycam.github.io/webidl/#idl-operations
+struct( IDLOperation => {
+ name => '$',
+ type => 'IDLType', # Return type
+ arguments => '@', # List of 'IDLArgument'
isStatic => '$',
- signature => '$', # Return type/Object name/extended attributes
- parameters => '@', # List of 'domSignature'
+ specials => '@',
+ extendedAttributes => '$',
});
-# Used to represent domInterface contents (name of attribute, signature)
-struct( domAttribute => {
- type => '$', # Attribute type (including namespace)
+
+# https://heycam.github.io/webidl/#idl-attributes
+struct( IDLAttribute => {
+ name => '$',
+ type => 'IDLType',
isStatic => '$',
+ isStringifier => '$',
isReadOnly => '$',
- signature => '$', # Attribute signature
+ extendedAttributes => '$',
+});
+
+# https://heycam.github.io/webidl/#idl-iterable
+struct( IDLIterable => {
+ isKeyValue => '$',
+ keyType => 'IDLType',
+ valueType => 'IDLType',
+ functions => '@', # Iterable functions (entries, keys, values, [Symbol.Iterator], forEach)
+ extendedAttributes => '$',
+});
+
+# https://heycam.github.io/webidl/#idl-serializers
+struct( IDLSerializable => {
+ attributes => '@', # List of attributes to serialize
+ hasAttribute => '$', # serializer = { attribute }
+ hasInherit => '$', # serializer = { inherit }
+ hasGetter => '$', # serializer = { getter }
+ functions => '@', # toJSON function
+});
+
+# https://heycam.github.io/webidl/#idl-constants
+struct( IDLConstant => {
+ name => '$',
+ type => 'IDLType',
+ value => '$',
+ extendedAttributes => '$',
+});
+
+# https://heycam.github.io/webidl/#idl-enums
+struct( IDLEnum => {
+ name => '$',
+ type => 'IDLType',
+ values => '@',
+ extendedAttributes => '$',
+});
+
+# https://heycam.github.io/webidl/#dfn-dictionary-member
+struct( IDLDictionaryMember => {
+ name => '$',
+ type => 'IDLType',
+ isRequired => '$',
+ default => '$',
+ extendedAttributes => '$',
});
-# Used to represent a map of 'variable name' <-> 'variable type'
-struct( domSignature => {
- direction => '$', # Variable direction (in or out)
- name => '$', # Variable name
- type => '$', # Variable type
- specials => '@', # Specials
- extendedAttributes => '$', # Extended attributes
- isNullable => '$', # Is variable type Nullable (T?)
- isVariadic => '$', # Is variable variadic (long... numbers)
- isOptional => '$', # Is variable optional (optional T)
+# https://heycam.github.io/webidl/#idl-dictionaries
+struct( IDLDictionary => {
+ type => 'IDLType',
+ parentType => 'IDLType',
+ members => '@', # List of 'IDLDictionaryMember'
+ extendedAttributes => '$',
});
-# Used to represent string constants
-struct( domConstant => {
- name => '$', # DOM Constant identifier
- type => '$', # Type of data
- value => '$', # Constant value
- extendedAttributes => '$', # Extended attributes
+# https://heycam.github.io/webidl/#idl-callback-functions
+struct( IDLCallbackFunction => {
+ type => '$',
+ operation => 'IDLOperation',
+ extendedAttributes => '$',
});
-# Used to represent 'enum' definitions
-struct( domEnum => {
- name => '$', # Enumeration identifier
- values => '@', # Enumeration values (list of unique strings)
+# https://heycam.github.io/webidl/#idl-typedefs
+struct( IDLTypedef => {
+ type => 'IDLType',
});
struct( Token => {
@@ -103,11 +170,6 @@ struct( Token => {
value => '$' # value of token
});
-struct( Typedef => {
- extendedAttributes => '$', # Extended attributes
- type => '$', # Type of data
-});
-
# Maps 'typedef name' -> Typedef
my %typedefs = ();
@@ -129,17 +191,28 @@ sub new {
return bless $self, $class;
}
+sub assert
+{
+ my $message = shift;
+
+ my $mess = longmess();
+ print Dumper($mess);
+
+ die $message;
+}
+
sub assertTokenValue
{
my $self = shift;
my $token = shift;
my $value = shift;
my $line = shift;
- my $msg = "Next token should be " . $value . ", but " . $token->value() . " at " . $self->{Line};
+ my $msg = "Next token should be " . $value . ", but " . $token->value() . " on line " . $self->{Line};
if (defined ($line)) {
$msg .= " IDLParser.pm:" . $line;
}
- die $msg unless $token->value() eq $value;
+
+ assert $msg unless $token->value() eq $value;
}
sub assertTokenType
@@ -147,7 +220,8 @@ sub assertTokenType
my $self = shift;
my $token = shift;
my $type = shift;
- die "Next token's type should be " . $type . ", but " . $token->type() . " at " . $self->{Line} unless $token->type() eq $type;
+
+ assert "Next token's type should be " . $type . ", but " . $token->type() . " on line " . $self->{Line} unless $token->type() eq $type;
}
sub assertUnexpectedToken
@@ -155,11 +229,12 @@ sub assertUnexpectedToken
my $self = shift;
my $token = shift;
my $line = shift;
- my $msg = "Unexpected token " . $token . " at " . $self->{Line};
+ my $msg = "Unexpected token " . $token . " on line " . $self->{Line};
if (defined ($line)) {
$msg .= " IDLParser.pm:" . $line;
}
- die $msg;
+
+ assert $msg;
}
sub assertNoExtendedAttributesInTypedef
@@ -168,11 +243,12 @@ sub assertNoExtendedAttributesInTypedef
my $name = shift;
my $line = shift;
my $typedef = $typedefs{$name};
- my $msg = "Unexpected extendedAttributeList in typedef \"$name\" at " . $self->{Line};
+ my $msg = "Unexpected extendedAttributeList in typedef \"$name\" on line " . $self->{Line};
if (defined ($line)) {
$msg .= " IDLParser.pm:" . $line;
}
- die $msg if %{$typedef->extendedAttributes};
+
+ assert $msg if %{$typedef->extendedAttributes};
}
sub Parse
@@ -196,15 +272,19 @@ sub Parse
my $next = $self->nextToken();
$self->assertTokenType($next, EmptyToken);
};
- die $@ . " in $fileName" if $@;
+ assert $@ . " in $fileName" if $@;
- my $document = idlDocument->new();
+ my $document = IDLDocument->new();
$document->fileName($fileName);
foreach my $definition (@definitions) {
- if (ref($definition) eq "domInterface") {
+ if (ref($definition) eq "IDLInterface") {
push(@{$document->interfaces}, $definition);
- } elsif (ref($definition) eq "domEnum") {
+ } elsif (ref($definition) eq "IDLEnum") {
push(@{$document->enumerations}, $definition);
+ } elsif (ref($definition) eq "IDLDictionary") {
+ push(@{$document->dictionaries}, $definition);
+ } elsif (ref($definition) eq "IDLCallbackFunction") {
+ push(@{$document->callbackFunctions}, $definition);
} else {
die "Unrecognized IDL definition kind: \"" . ref($definition) . "\"";
}
@@ -231,7 +311,7 @@ my $floatTokenPattern = '^(-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|
my $integerTokenPattern = '^(-?[1-9][0-9]*|-?0[Xx][0-9A-Fa-f]+|-?0[0-7]*)';
my $stringTokenPattern = '^(\"[^\"]*\")';
my $identifierTokenPattern = '^([A-Z_a-z][0-9A-Z_a-z]*)';
-my $otherTokenPattern = '^(::|\.\.\.|[^\t\n\r 0-9A-Z_a-z])';
+my $otherTokenPattern = '^(\.\.\.|[^\t\n\r 0-9A-Z_a-z])';
sub getTokenInternal
{
@@ -296,51 +376,75 @@ sub unquoteString
die "Failed to parse string (" . $quotedString . ") at " . $self->{Line};
}
-sub typeHasNullableSuffix
+sub identifierRemoveNullablePrefix
{
my $type = shift;
- return $type =~ /\?$/;
+ $type =~ s/^_//;
+ return $type;
}
-sub typeRemoveNullableSuffix
+sub typeDescription
{
my $type = shift;
- $type =~ s/\?//g;
+
+ if (scalar @{$type->subtypes}) {
+ return $type->name . '<' . join(', ', map { typeDescription($_) } @{$type->subtypes}) . '>' . ($type->isNullable ? "?" : "");
+ }
+
+ return $type->name . ($type->isNullable ? "?" : "");
+}
+
+sub makeSimpleType
+{
+ my $typeName = shift;
+
+ my $type = IDLType->new();
+ $type->name($typeName);
+
return $type;
}
-sub identifierRemoveNullablePrefix
+sub cloneType
{
+ my $self = shift;
my $type = shift;
- $type =~ s/^_//;
- return $type;
+
+ my $clonedType = IDLType->new();
+ $clonedType->name($type->name);
+ $clonedType->isNullable($type->isNullable);
+ $clonedType->isUnion($type->isUnion);
+ foreach my $subtype (@{$type->subtypes}) {
+ push(@{$clonedType->subtypes}, $self->cloneType($subtype));
+ }
+
+ return $clonedType;
}
my $nextAttribute_1 = '^(attribute|inherit|readonly)$';
my $nextPrimitiveType_1 = '^(int|long|short|unsigned)$';
my $nextPrimitiveType_2 = '^(double|float|unrestricted)$';
-my $nextArgumentList_1 = '^(\(|::|ByteString|DOMString|Date|\[|any|boolean|byte|double|float|in|int|long|object|octet|optional|sequence|short|unrestricted|unsigned)$';
-my $nextNonAnyType_1 = '^(boolean|byte|double|float|int|long|octet|short|unrestricted|unsigned)$';
-my $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)$';
-my $nextOptionalIteratorInterfaceOrObject_1 = '^(;|=)$';
-my $nextAttributeOrOperationOrIterator_1 = '^(static|stringifier)$';
-my $nextAttributeOrOperationOrIterator_2 = '^(\(|::|ByteString|DOMString|Date|any|boolean|byte|creator|deleter|double|float|getter|int|legacycaller|long|object|octet|sequence|setter|short|unrestricted|unsigned|void)$';
+my $nextArgumentList_1 = '^(\(|ByteString|DOMString|USVString|Date|\[|any|boolean|byte|double|float|in|long|object|octet|optional|sequence|short|unrestricted|unsigned)$';
+my $nextNonAnyType_1 = '^(boolean|byte|double|float|long|octet|short|unrestricted|unsigned)$';
+my $nextStringType_1 = '^(ByteString|DOMString|USVString)$';
+my $nextInterfaceMember_1 = '^(\(|ByteString|DOMString|USVString|Date|any|attribute|boolean|byte|creator|deleter|double|float|getter|inherit|legacycaller|long|object|octet|readonly|sequence|serializer|setter|short|static|stringifier|unrestricted|unsigned|void)$';
+my $nextAttributeOrOperation_1 = '^(static|stringifier)$';
+my $nextAttributeOrOperation_2 = '^(\(|ByteString|DOMString|USVString|Date|any|boolean|byte|creator|deleter|double|float|getter|legacycaller|long|object|octet|sequence|setter|short|unrestricted|unsigned|void)$';
my $nextUnrestrictedFloatType_1 = '^(double|float)$';
-my $nextExtendedAttributeRest3_1 = '^(\,|::|\])$';
-my $nextExceptionField_1 = '^(\(|::|ByteString|DOMString|Date|any|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned)$';
-my $nextType_1 = '^(::|ByteString|DOMString|Date|any|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned)$';
+my $nextExtendedAttributeRest3_1 = '^(\,|\])$';
+my $nextExceptionField_1 = '^(\(|ByteString|DOMString|USVString|Date|any|boolean|byte|double|float|long|object|octet|sequence|short|unrestricted|unsigned)$';
+my $nextType_1 = '^(ByteString|DOMString|USVString|Date|any|boolean|byte|double|float|long|object|octet|sequence|short|unrestricted|unsigned)$';
my $nextSpecials_1 = '^(creator|deleter|getter|legacycaller|setter)$';
-my $nextDefinitions_1 = '^(::|callback|dictionary|enum|exception|interface|partial|typedef)$';
-my $nextExceptionMembers_1 = '^(\(|::|ByteString|DOMString|Date|\[|any|boolean|byte|const|double|float|int|long|object|octet|optional|sequence|short|unrestricted|unsigned)$';
+my $nextDefinitions_1 = '^(callback|dictionary|enum|exception|interface|partial|typedef)$';
+my $nextExceptionMembers_1 = '^(\(|ByteString|DOMString|USVString|Date|\[|any|boolean|byte|const|double|float|long|object|octet|optional|sequence|short|unrestricted|unsigned)$';
my $nextAttributeRest_1 = '^(attribute|readonly)$';
-my $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)$';
-my $nextSingleType_1 = '^(::|ByteString|DOMString|Date|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned)$';
+my $nextInterfaceMembers_1 = '^(\(|ByteString|DOMString|USVString|Date|any|attribute|boolean|byte|const|creator|deleter|double|float|getter|inherit|legacycaller|long|object|octet|readonly|sequence|serializer|setter|short|static|stringifier|unrestricted|unsigned|void)$';
+my $nextSingleType_1 = '^(ByteString|DOMString|USVString|Date|boolean|byte|double|float|long|object|octet|sequence|short|unrestricted|unsigned)$';
my $nextArgumentName_1 = '^(attribute|callback|const|creator|deleter|dictionary|enum|exception|getter|implements|inherit|interface|legacycaller|partial|serializer|setter|static|stringifier|typedef|unrestricted)$';
my $nextConstValue_1 = '^(false|true)$';
my $nextConstValue_2 = '^(-|Infinity|NaN)$';
my $nextDefinition_1 = '^(callback|interface)$';
-my $nextAttributeOrOperationRest_1 = '^(\(|::|ByteString|DOMString|Date|any|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned|void)$';
-my $nextUnsignedIntegerType_1 = '^(int|long|short)$';
+my $nextAttributeOrOperationRest_1 = '^(\(|ByteString|DOMString|USVString|Date|any|boolean|byte|double|float|long|object|octet|sequence|short|unrestricted|unsigned|void)$';
+my $nextUnsignedIntegerType_1 = '^(long|short)$';
my $nextDefaultValue_1 = '^(-|Infinity|NaN|false|null|true)$';
@@ -374,59 +478,71 @@ sub applyTypedefs
if (!%typedefs) {
return;
}
+
+ # FIXME: Add support for applying typedefs to IDLIterable.
foreach my $definition (@$definitions) {
- if (ref($definition) eq "domInterface") {
+ if (ref($definition) eq "IDLInterface") {
foreach my $constant (@{$definition->constants}) {
- if (exists $typedefs{$constant->type}) {
- my $typedef = $typedefs{$constant->type};
- $self->assertNoExtendedAttributesInTypedef($constant->type, __LINE__);
- $constant->type($typedef->type);
- }
+ $constant->type($self->typeByApplyingTypedefs($constant->type));
}
foreach my $attribute (@{$definition->attributes}) {
- $self->applyTypedefsForSignature($attribute->signature);
+ $attribute->type($self->typeByApplyingTypedefs($attribute->type));
}
- foreach my $function (@{$definition->functions}, @{$definition->anonymousFunctions}, @{$definition->constructors}, @{$definition->customConstructors}) {
- $self->applyTypedefsForSignature($function->signature);
- foreach my $signature (@{$function->parameters}) {
- $self->applyTypedefsForSignature($signature);
- }
+ foreach my $operation (@{$definition->functions}, @{$definition->anonymousFunctions}, @{$definition->constructors}, @{$definition->customConstructors}) {
+ $self->applyTypedefsToOperation($operation);
}
+ } elsif (ref($definition) eq "IDLDictionary") {
+ foreach my $member (@{$definition->members}) {
+ $member->type($self->typeByApplyingTypedefs($member->type));
+ }
+ } elsif (ref($definition) eq "IDLCallbackFunction") {
+ $self->applyTypedefsToOperation($definition->operation);
}
}
}
-sub applyTypedefsForSignature
+sub applyTypedefsToOperation
{
my $self = shift;
- my $signature = shift;
+ my $operation = shift;
- if (!defined ($signature->type)) {
- return;
+ if ($operation->type) {
+ $operation->type($self->typeByApplyingTypedefs($operation->type));
}
- my $type = $signature->type;
- $type =~ s/[\?\[\]]+$//g;
- my $typeSuffix = $signature->type;
- $typeSuffix =~ s/^[^\?\[\]]+//g;
- if (exists $typedefs{$type}) {
- my $typedef = $typedefs{$type};
- $signature->type($typedef->type . $typeSuffix);
- copyExtendedAttributes($signature->extendedAttributes, $typedef->extendedAttributes);
+ foreach my $argument (@{$operation->arguments}) {
+ $argument->type($self->typeByApplyingTypedefs($argument->type));
}
+}
- # Handle union types, sequences and etc.
- foreach my $name (%typedefs) {
- if (!exists $typedefs{$name}) {
- next;
+sub typeByApplyingTypedefs
+{
+ my $self = shift;
+ my $type = shift;
+
+ assert("Missing type") if !$type;
+
+ my $numberOfSubtypes = scalar @{$type->subtypes};
+ if ($numberOfSubtypes) {
+ for my $i (0..$numberOfSubtypes - 1) {
+ my $subtype = @{$type->subtypes}[$i];
+ my $replacementSubtype = $self->typeByApplyingTypedefs($subtype);
+ @{$type->subtypes}[$i] = $replacementSubtype
}
- my $typedef = $typedefs{$name};
- my $regex = '\\b' . $name . '\\b';
- my $replacement = $typedef->type;
- my $type = $signature->type;
- $type =~ s/($regex)/$replacement/g;
- $signature->type($type);
+
+ return $type;
}
+
+ if (exists $typedefs{$type->name}) {
+ my $typedef = $typedefs{$type->name};
+
+ my $clonedType = $self->cloneType($typedef->type);
+ $clonedType->isNullable($clonedType->isNullable || $type->isNullable);
+
+ return $self->typeByApplyingTypedefs($clonedType);
+ }
+
+ return $type;
}
sub parseDefinition
@@ -453,7 +569,7 @@ sub parseDefinition
if ($next->value() eq "typedef") {
return $self->parseTypedef($extendedAttributeList);
}
- if ($next->type() == IdentifierToken || $next->value() eq "::") {
+ if ($next->type() == IdentifierToken) {
return $self->parseImplementsStatement($extendedAttributeList);
}
$self->assertUnexpectedToken($next->value(), __LINE__);
@@ -499,14 +615,20 @@ sub parseInterface
my $next = $self->nextToken();
if ($next->value() eq "interface") {
- my $interface = domInterface->new();
+ my $interface = IDLInterface->new();
$self->assertTokenValue($self->getToken(), "interface", __LINE__);
my $interfaceNameToken = $self->getToken();
$self->assertTokenType($interfaceNameToken, IdentifierToken);
- $interface->name(identifierRemoveNullablePrefix($interfaceNameToken->value()));
- my $parents = $self->parseInheritance();
- $interface->parents($parents);
- $interface->parent($parents->[0]);
+
+ my $name = identifierRemoveNullablePrefix($interfaceNameToken->value());
+ $interface->type(makeSimpleType($name));
+
+ $next = $self->nextToken();
+ if ($next->value() eq ":") {
+ my $parent = $self->parseInheritance();
+ $interface->parentType(makeSimpleType($parent));
+ }
+
$self->assertTokenValue($self->getToken(), "{", __LINE__);
my $interfaceMembers = $self->parseInterfaceMembers();
$self->assertTokenValue($self->getToken(), "}", __LINE__);
@@ -610,14 +732,27 @@ sub parseDictionary
my $next = $self->nextToken();
if ($next->value() eq "dictionary") {
+ my $dictionary = IDLDictionary->new();
+ $dictionary->extendedAttributes($extendedAttributeList);
$self->assertTokenValue($self->getToken(), "dictionary", __LINE__);
- $self->assertTokenType($self->getToken(), IdentifierToken);
- $self->parseInheritance();
+
+ my $nameToken = $self->getToken();
+ $self->assertTokenType($nameToken, IdentifierToken);
+
+ my $name = $nameToken->value();
+ $dictionary->type(makeSimpleType($name));
+
+ $next = $self->nextToken();
+ if ($next->value() eq ":") {
+ my $parent = $self->parseInheritance();
+ $dictionary->parentType(makeSimpleType($parent));
+ }
+
$self->assertTokenValue($self->getToken(), "{", __LINE__);
- $self->parseDictionaryMembers();
+ $dictionary->members($self->parseDictionaryMembers());
$self->assertTokenValue($self->getToken(), "}", __LINE__);
$self->assertTokenValue($self->getToken(), ";", __LINE__);
- return;
+ return $dictionary;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -626,15 +761,19 @@ sub parseDictionaryMembers
{
my $self = shift;
+ my @members = ();
+
while (1) {
my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty();
my $next = $self->nextToken();
if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) {
- $self->parseDictionaryMember($extendedAttributeList);
+ push(@members, $self->parseDictionaryMember($extendedAttributeList));
} else {
last;
}
}
+
+ return \@members;
}
sub parseDictionaryMember
@@ -644,11 +783,24 @@ sub parseDictionaryMember
my $next = $self->nextToken();
if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) {
- $self->parseType();
- $self->assertTokenType($self->getToken(), IdentifierToken);
- $self->parseDefault();
+ my $member = IDLDictionaryMember->new();
+ if ($next->value eq "required") {
+ $self->assertTokenValue($self->getToken(), "required", __LINE__);
+ $member->isRequired(1);
+ } else {
+ $member->isRequired(0);
+ }
+ $member->extendedAttributes($extendedAttributeList);
+
+ my $type = $self->parseType();
+ $member->type($type);
+
+ my $nameToken = $self->getToken();
+ $self->assertTokenType($nameToken, IdentifierToken);
+ $member->name($nameToken->value);
+ $member->default($self->parseDefault());
$self->assertTokenValue($self->getToken(), ";", __LINE__);
- return;
+ return $member;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -677,6 +829,7 @@ sub parseDefault
$self->assertTokenValue($self->getToken(), "=", __LINE__);
return $self->parseDefaultValue();
}
+ return undef;
}
sub parseDefaultValue
@@ -689,6 +842,11 @@ sub parseDefaultValue
if ($next->type() == StringToken) {
return $self->getToken()->value();
}
+ if ($next->value() eq "[") {
+ $self->assertTokenValue($self->getToken(), "[", __LINE__);
+ $self->assertTokenValue($self->getToken(), "]", __LINE__);
+ return "[]";
+ }
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -699,15 +857,21 @@ sub parseException
my $next = $self->nextToken();
if ($next->value() eq "exception") {
- my $interface = domInterface->new();
+ my $interface = IDLInterface->new();
$self->assertTokenValue($self->getToken(), "exception", __LINE__);
my $exceptionNameToken = $self->getToken();
$self->assertTokenType($exceptionNameToken, IdentifierToken);
- $interface->name(identifierRemoveNullablePrefix($exceptionNameToken->value()));
+
+ my $name = identifierRemoveNullablePrefix($exceptionNameToken->value());
+ $interface->type(makeSimpleType($name));
$interface->isException(1);
- my $parents = $self->parseInheritance();
- $interface->parents($parents);
- $interface->parent($parents->[0]);
+
+ $next = $self->nextToken();
+ if ($next->value() eq ":") {
+ my $parent = $self->parseInheritance();
+ $interface->parentType(makeSimpleType($parent));
+ }
+
$self->assertTokenValue($self->getToken(), "{", __LINE__);
my $exceptionMembers = $self->parseExceptionMembers();
$self->assertTokenValue($self->getToken(), "}", __LINE__);
@@ -743,35 +907,34 @@ sub parseExceptionMembers
sub parseInheritance
{
my $self = shift;
- my @parent = ();
my $next = $self->nextToken();
if ($next->value() eq ":") {
$self->assertTokenValue($self->getToken(), ":", __LINE__);
- my $scopedName = $self->parseScopedName();
- push(@parent, $scopedName);
- # Multiple inheritance (needed for ObjC bindings).
- push(@parent, @{$self->parseIdentifiers()});
+ return $self->parseName();
}
- return \@parent;
+ $self->assertUnexpectedToken($next->value(), __LINE__);
}
sub parseEnum
{
my $self = shift;
- my $extendedAttributeList = shift; # ignored: Extended attributes are not applicable to enumerations
+ my $extendedAttributeList = shift;
my $next = $self->nextToken();
if ($next->value() eq "enum") {
- my $enum = domEnum->new();
+ my $enum = IDLEnum->new();
$self->assertTokenValue($self->getToken(), "enum", __LINE__);
my $enumNameToken = $self->getToken();
$self->assertTokenType($enumNameToken, IdentifierToken);
- $enum->name(identifierRemoveNullablePrefix($enumNameToken->value()));
+ my $name = identifierRemoveNullablePrefix($enumNameToken->value());
+ $enum->name($name);
+ $enum->type(makeSimpleType($name));
$self->assertTokenValue($self->getToken(), "{", __LINE__);
push(@{$enum->values}, @{$self->parseEnumValueList()});
$self->assertTokenValue($self->getToken(), "}", __LINE__);
$self->assertTokenValue($self->getToken(), ";", __LINE__);
+ $enum->extendedAttributes($extendedAttributeList);
return $enum;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
@@ -818,14 +981,30 @@ sub parseCallbackRest
my $next = $self->nextToken();
if ($next->type() == IdentifierToken) {
- $self->assertTokenType($self->getToken(), IdentifierToken);
+ my $callback = IDLCallbackFunction->new();
+
+ my $nameToken = $self->getToken();
+ $self->assertTokenType($nameToken, IdentifierToken);
+
+ $callback->type(makeSimpleType($nameToken->value()));
+
$self->assertTokenValue($self->getToken(), "=", __LINE__);
- $self->parseReturnType();
+
+ my $operation = IDLOperation->new();
+ $operation->type($self->parseReturnType());
+ $operation->extendedAttributes($extendedAttributeList);
+
$self->assertTokenValue($self->getToken(), "(", __LINE__);
- $self->parseArgumentList();
+
+ push(@{$operation->arguments}, @{$self->parseArgumentList()});
+
$self->assertTokenValue($self->getToken(), ")", __LINE__);
$self->assertTokenValue($self->getToken(), ";", __LINE__);
- return;
+
+ $callback->operation($operation);
+ $callback->extendedAttributes($extendedAttributeList);
+
+ return $callback;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -839,14 +1018,16 @@ sub parseTypedef
my $next = $self->nextToken();
if ($next->value() eq "typedef") {
$self->assertTokenValue($self->getToken(), "typedef", __LINE__);
- my $typedef = Typedef->new();
- $typedef->extendedAttributes($self->parseExtendedAttributeListAllowEmpty());
- $typedef->type($self->parseType());
+ my $typedef = IDLTypedef->new();
+
+ my $type = $self->parseType();
+ $typedef->type($type);
+
my $nameToken = $self->getToken();
$self->assertTokenType($nameToken, IdentifierToken);
$self->assertTokenValue($self->getToken(), ";", __LINE__);
my $name = $nameToken->value();
- die "typedef redefinition for " . $name . " at " . $self->{Line} if (exists $typedefs{$name} && $typedef->type ne $typedefs{$name}->type);
+ die "typedef redefinition for " . $name . " at " . $self->{Line} if (exists $typedefs{$name} && $typedef->type->name ne $typedefs{$name}->type->name);
$typedefs{$name} = $typedef;
return;
}
@@ -860,9 +1041,9 @@ sub parseImplementsStatement
my $next = $self->nextToken();
if ($next->type() == IdentifierToken) {
- $self->parseScopedName();
+ $self->parseName();
$self->assertTokenValue($self->getToken(), "implements", __LINE__);
- $self->parseScopedName();
+ $self->parseName();
$self->assertTokenValue($self->getToken(), ";", __LINE__);
return;
}
@@ -876,9 +1057,10 @@ sub parseConst
my $next = $self->nextToken();
if ($next->value() eq "const") {
- my $newDataNode = domConstant->new();
+ my $newDataNode = IDLConstant->new();
$self->assertTokenValue($self->getToken(), "const", __LINE__);
- $newDataNode->type($self->parseConstType());
+ my $type = $self->parseConstType();
+ $newDataNode->type($type);
my $constNameToken = $self->getToken();
$self->assertTokenType($constNameToken, IdentifierToken);
$newDataNode->name(identifierRemoveNullablePrefix($constNameToken->value()));
@@ -905,10 +1087,6 @@ sub parseConstValue
if ($next->type() == FloatToken || $next->value() =~ /$nextConstValue_2/) {
return $self->parseFloatLiteral();
}
- # backward compatibility
- if ($next->type() == StringToken) {
- return $self->getToken()->value();
- }
if ($next->type() == IntegerToken) {
return $self->getToken()->value();
}
@@ -962,18 +1140,19 @@ sub parseAttributeOrOperationOrIterator
if ($next->value() eq "serializer") {
return $self->parseSerializer($extendedAttributeList);
}
- if ($next->value() =~ /$nextAttributeOrOperationOrIterator_1/) {
+ if ($next->value() =~ /$nextAttributeOrOperation_1/) {
my $qualifier = $self->parseQualifier();
my $newDataNode = $self->parseAttributeOrOperationRest($extendedAttributeList);
- if (defined($newDataNode) && $qualifier eq "static") {
- $newDataNode->isStatic(1);
+ if (defined($newDataNode)) {
+ $newDataNode->isStatic(1) if $qualifier eq "static";
+ $newDataNode->isStringifier(1) if $qualifier eq "stringifier";
}
return $newDataNode;
}
if ($next->value() =~ /$nextAttribute_1/) {
return $self->parseAttribute($extendedAttributeList);
}
- if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperationOrIterator_2/) {
+ if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperation_2/) {
return $self->parseOperationOrIterator($extendedAttributeList);
}
$self->assertUnexpectedToken($next->value(), __LINE__);
@@ -987,7 +1166,22 @@ sub parseSerializer
my $next = $self->nextToken();
if ($next->value() eq "serializer") {
$self->assertTokenValue($self->getToken(), "serializer", __LINE__);
- return $self->parseSerializerRest($extendedAttributeList);
+ my $next = $self->nextToken();
+ my $newDataNode;
+ if ($next->value() ne ";") {
+ $newDataNode = $self->parseSerializerRest($extendedAttributeList);
+ my $next = $self->nextToken();
+ } else {
+ $newDataNode = IDLSerializable->new();
+ }
+
+ my $toJSONFunction = IDLOperation->new();
+ $toJSONFunction->name("toJSON");
+ $toJSONFunction->extendedAttributes($extendedAttributeList);
+ push(@{$newDataNode->functions}, $toJSONFunction);
+
+ $self->assertTokenValue($self->getToken(), ";", __LINE__);
+ return $newDataNode;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -1000,7 +1194,9 @@ sub parseSerializerRest
my $next = $self->nextToken();
if ($next->value() eq "=") {
$self->assertTokenValue($self->getToken(), "=", __LINE__);
- return $self->parseSerializationPattern($extendedAttributeList);
+
+ return $self->parseSerializationPattern();
+
}
if ($next->type() == IdentifierToken || $next->value() eq "(") {
return $self->parseOperationRest($extendedAttributeList);
@@ -1010,59 +1206,74 @@ sub parseSerializerRest
sub parseSerializationPattern
{
my $self = shift;
- my $extendedAttributeList = shift;
my $next = $self->nextToken();
if ($next->value() eq "{") {
$self->assertTokenValue($self->getToken(), "{", __LINE__);
- $self->parseSerializationPatternMap();
+ my $newDataNode = IDLSerializable->new();
+ $self->parseSerializationAttributes($newDataNode);
$self->assertTokenValue($self->getToken(), "}", __LINE__);
- return;
+ return $newDataNode;
}
if ($next->value() eq "[") {
- $self->assertTokenValue($self->getToken(), "[", __LINE__);
- $self->parseSerializationPatternList();
- $self->assertTokenValue($self->getToken(), "]", __LINE__);
- return;
+ die "Serialization of lists pattern is not currently supported.";
}
if ($next->type() == IdentifierToken) {
- $self->assertTokenType($self->getToken(), IdentifierToken);
- return;
+ my @attributes = ();
+ my $token = $self->getToken();
+ $self->assertTokenType($token, IdentifierToken);
+ push(@attributes, $token->value());
+
+ my $newDataNode = IDLSerializable->new();
+ $newDataNode->attributes(\@attributes);
+
+ return $newDataNode;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
-sub parseSerializationPatternMap
+sub parseSerializationAttributes
{
my $self = shift;
- my $next = $self->nextToken();
- if ($next->value() eq "getter") {
- $self->assertTokenValue($self->getToken(), "getter", __LINE__);
- return;
- }
- if ($next->value() eq "inherit") {
- $self->assertTokenValue($self->getToken(), "inherit", __LINE__);
- $self->parseIdentifiers();
- return;
- }
- if ($next->type() == IdentifierToken) {
- $self->assertTokenType($self->getToken(), IdentifierToken);
- $self->parseIdentifiers();
+ my $serializable = shift;
+
+ my @attributes = ();
+ my @identifiers = $self->parseIdentifierList();
+
+ for my $identifier (@identifiers) {
+ if ($identifier eq "getter") {
+ $serializable->hasGetter(1);
+ die "Serializer getter keyword is not currently supported.";
+ }
+
+ if ($identifier eq "inherit") {
+ $serializable->hasInherit(1);
+ next;
+ }
+
+ if ($identifier eq "attribute") {
+ $serializable->hasAttribute(1);
+ # Attributes will be filled in via applyMemberList()
+ next;
+ }
+
+ push(@attributes, $identifier);
}
+
+ $serializable->attributes(\@attributes);
}
-sub parseSerializationPatternList
+sub parseIdentifierList
{
my $self = shift;
my $next = $self->nextToken();
- if ($next->value() eq "getter") {
- $self->assertTokenValue($self->getToken(), "getter", __LINE__);
- return;
- }
- if ($next->type() == IdentifierToken) {
- $self->assertTokenType($self->getToken(), IdentifierToken);
- $self->parseIdentifiers();
+
+ my @identifiers = ();
+ if ($next->type == IdentifierToken) {
+ push(@identifiers, $self->getToken()->value());
+ push(@identifiers, @{$self->parseIdentifiers()});
}
+ return @identifiers;
}
sub parseIdentifiers
@@ -1115,11 +1326,11 @@ sub parseAttributeOrOperationRest
}
if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperationRest_1/) {
my $returnType = $self->parseReturnType();
- my $interface = $self->parseOperationRest($extendedAttributeList);
- if (defined ($interface)) {
- $interface->signature->type($returnType);
+ my $operation = $self->parseOperationRest($extendedAttributeList);
+ if (defined ($operation)) {
+ $operation->type($returnType);
}
- return $interface;
+ return $operation;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -1144,33 +1355,25 @@ sub parseAttributeRest
my $next = $self->nextToken();
if ($next->value() =~ /$nextAttributeRest_1/) {
- my $newDataNode = domAttribute->new();
- if ($self->parseReadOnly()) {
- $newDataNode->type("attribute");
- $newDataNode->isReadOnly(1);
- } else {
- $newDataNode->type("attribute");
- }
+ my $newDataNode = IDLAttribute->new();
+ $newDataNode->isReadOnly($self->parseReadOnly());
+
$self->assertTokenValue($self->getToken(), "attribute", __LINE__);
- $newDataNode->signature(domSignature->new());
+
my $type = $self->parseType();
- if (typeHasNullableSuffix($type)) {
- $newDataNode->signature->isNullable(1);
- } else {
- $newDataNode->signature->isNullable(0);
- }
- # Remove all "?" in the type declaration, e.g. "double?" -> "double".
- $newDataNode->signature->type(typeRemoveNullableSuffix($type));
+ $newDataNode->type($type);
+
my $token = $self->getToken();
$self->assertTokenType($token, IdentifierToken);
- $newDataNode->signature->name(identifierRemoveNullablePrefix($token->value()));
+ $newDataNode->name(identifierRemoveNullablePrefix($token->value()));
$self->assertTokenValue($self->getToken(), ";", __LINE__);
+
# CustomConstructor may also be used on attributes.
if (defined $extendedAttributeList->{"CustomConstructors"}) {
delete $extendedAttributeList->{"CustomConstructors"};
$extendedAttributeList->{"CustomConstructor"} = "VALUE_IS_MISSING";
}
- $newDataNode->signature->extendedAttributes($extendedAttributeList);
+ $newDataNode->extendedAttributes($extendedAttributeList);
return $newDataNode;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
@@ -1207,13 +1410,17 @@ sub parseOperationOrIterator
if ($next->value() =~ /$nextSpecials_1/) {
return $self->parseSpecialOperation($extendedAttributeList);
}
+ if ($next->value() eq "iterable") {
+ return $self->parseIterableRest($extendedAttributeList);
+ }
if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperationRest_1/) {
my $returnType = $self->parseReturnType();
- my $interface = $self->parseOperationOrIteratorRest($extendedAttributeList);
- if (defined ($interface)) {
- $interface->signature->type($returnType);
+ my $next = $self->nextToken();
+ if ($next->type() == IdentifierToken || $next->value() eq "(") {
+ my $operation = $self->parseOperationRest($extendedAttributeList);
+ $operation->type($returnType);
+ return $operation;
}
- return $interface;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -1228,12 +1435,12 @@ sub parseSpecialOperation
my @specials = ();
push(@specials, @{$self->parseSpecials()});
my $returnType = $self->parseReturnType();
- my $interface = $self->parseOperationRest($extendedAttributeList);
- if (defined ($interface)) {
- $interface->signature->type($returnType);
- $interface->signature->specials(\@specials);
+ my $operation = $self->parseOperationRest($extendedAttributeList);
+ if (defined ($operation)) {
+ $operation->type($returnType);
+ $operation->specials(\@specials);
}
- return $interface;
+ return $operation;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -1281,62 +1488,75 @@ sub parseSpecial
$self->assertUnexpectedToken($next->value(), __LINE__);
}
-sub parseOperationOrIteratorRest
+sub parseIterableRest
{
my $self = shift;
my $extendedAttributeList = shift;
my $next = $self->nextToken();
- if ($next->value() eq "iterator") {
- return $self->parseIteratorRest($extendedAttributeList);
- }
- if ($next->type() == IdentifierToken || $next->value() eq "(") {
- return $self->parseOperationRest($extendedAttributeList);
- }
- $self->assertUnexpectedToken($next->value(), __LINE__);
-}
-
-sub parseIteratorRest
-{
- my $self = shift;
- my $extendedAttributeList = shift;
-
- my $next = $self->nextToken();
- if ($next->value() eq "iterator") {
- $self->assertTokenValue($self->getToken(), "iterator", __LINE__);
- $self->parseOptionalIteratorInterfaceOrObject($extendedAttributeList);
+ if ($next->value() eq "iterable") {
+ $self->assertTokenValue($self->getToken(), "iterable", __LINE__);
+ my $iterableNode = $self->parseOptionalIterableInterface($extendedAttributeList);
$self->assertTokenValue($self->getToken(), ";", __LINE__);
- return;
+ return $iterableNode;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
-sub parseOptionalIteratorInterfaceOrObject
+sub parseOptionalIterableInterface
{
my $self = shift;
my $extendedAttributeList = shift;
- my $next = $self->nextToken();
- if ($next->value() =~ /$nextOptionalIteratorInterfaceOrObject_1/) {
- return $self->parseOptionalIteratorInterface($extendedAttributeList);
- }
- if ($next->value() eq "object") {
- $self->assertTokenValue($self->getToken(), "object", __LINE__);
- return;
- }
- $self->assertUnexpectedToken($next->value(), __LINE__);
-}
-
-sub parseOptionalIteratorInterface
-{
- my $self = shift;
- my $extendedAttributeList = shift;
+ my $symbolIteratorFunction = IDLOperation->new();
+ $symbolIteratorFunction->name("[Symbol.Iterator]");
+ $symbolIteratorFunction->extendedAttributes($extendedAttributeList);
+
+ my $entriesFunction = IDLOperation->new();
+ $entriesFunction->name("entries");
+ $entriesFunction->extendedAttributes($extendedAttributeList);
+
+ my $keysFunction = IDLOperation->new();
+ $keysFunction->name("keys");
+ $keysFunction->extendedAttributes($extendedAttributeList);
+
+ my $valuesFunction = IDLOperation->new();
+ $valuesFunction->name("values");
+ $valuesFunction->extendedAttributes($extendedAttributeList);
+
+ my $forEachFunction = IDLOperation->new();
+ $forEachFunction->name("forEach");
+ $forEachFunction->extendedAttributes($extendedAttributeList);
+ my $forEachArgument = IDLArgument->new();
+ $forEachArgument->name("callback");
+ $forEachArgument->type(makeSimpleType("any"));
+ push(@{$forEachFunction->arguments}, ($forEachArgument));
+
+ my $newDataNode = IDLIterable->new();
+ $newDataNode->extendedAttributes($extendedAttributeList);
+ push(@{$newDataNode->functions}, $symbolIteratorFunction);
+ push(@{$newDataNode->functions}, $entriesFunction);
+ push(@{$newDataNode->functions}, $keysFunction);
+ push(@{$newDataNode->functions}, $valuesFunction);
+ push(@{$newDataNode->functions}, $forEachFunction);
+
+ $self->assertTokenValue($self->getToken(), "<", __LINE__);
+ my $type1 = $self->parseType();
+
+ if ($self->nextToken()->value() eq ",") {
+ $self->assertTokenValue($self->getToken(), ",", __LINE__);
- my $next = $self->nextToken();
- if ($next->value() eq "=") {
- $self->assertTokenValue($self->getToken(), "=", __LINE__);
- $self->assertTokenType($self->getToken(), IdentifierToken);
+ my $type2 = $self->parseType();
+ $newDataNode->isKeyValue(1);
+ $newDataNode->keyType($type1);
+ $newDataNode->valueType($type2);
+ } else {
+ $newDataNode->isKeyValue(0);
+ $newDataNode->valueType($type1);
}
+ $self->assertTokenValue($self->getToken(), ">", __LINE__);
+
+ return $newDataNode;
}
sub parseOperationRest
@@ -1346,15 +1566,19 @@ sub parseOperationRest
my $next = $self->nextToken();
if ($next->type() == IdentifierToken || $next->value() eq "(") {
- my $newDataNode = domFunction->new();
- $newDataNode->signature(domSignature->new());
+ my $newDataNode = IDLOperation->new();
+
my $name = $self->parseOptionalIdentifier();
- $newDataNode->signature->name(identifierRemoveNullablePrefix($name));
+ $newDataNode->name(identifierRemoveNullablePrefix($name));
+
$self->assertTokenValue($self->getToken(), "(", $name, __LINE__);
- push(@{$newDataNode->parameters}, @{$self->parseArgumentList()});
+
+ push(@{$newDataNode->arguments}, @{$self->parseArgumentList()});
+
$self->assertTokenValue($self->getToken(), ")", __LINE__);
$self->assertTokenValue($self->getToken(), ";", __LINE__);
- $newDataNode->signature->extendedAttributes($extendedAttributeList);
+
+ $newDataNode->extendedAttributes($extendedAttributeList);
return $newDataNode;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
@@ -1406,10 +1630,8 @@ sub parseArgument
my $self = shift;
my $next = $self->nextToken();
if ($next->type() == IdentifierToken || $next->value() =~ /$nextArgumentList_1/) {
- my $in = $self->parseIn();
my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty();
my $argument = $self->parseOptionalOrRequiredArgument($extendedAttributeList);
- $argument->direction($self->parseIn());
return $argument;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
@@ -1420,36 +1642,23 @@ sub parseOptionalOrRequiredArgument
my $self = shift;
my $extendedAttributeList = shift;
- my $paramDataNode = domSignature->new();
+ my $paramDataNode = IDLArgument->new();
$paramDataNode->extendedAttributes($extendedAttributeList);
my $next = $self->nextToken();
if ($next->value() eq "optional") {
$self->assertTokenValue($self->getToken(), "optional", __LINE__);
+
my $type = $self->parseType();
- # domDataNode can only consider last "?".
- if (typeHasNullableSuffix($type)) {
- $paramDataNode->isNullable(1);
- } else {
- $paramDataNode->isNullable(0);
- }
- # Remove all "?" if exists, e.g. "object?[]?" -> "object[]".
- $paramDataNode->type(identifierRemoveNullablePrefix(typeRemoveNullableSuffix($type)));
+ $paramDataNode->type($type);
$paramDataNode->isOptional(1);
$paramDataNode->name($self->parseArgumentName());
- $self->parseDefault();
+ $paramDataNode->default($self->parseDefault());
return $paramDataNode;
}
if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) {
my $type = $self->parseType();
- # domDataNode can only consider last "?".
- if (typeHasNullableSuffix($type)) {
- $paramDataNode->isNullable(1);
- } else {
- $paramDataNode->isNullable(0);
- }
- # Remove all "?" if exists, e.g. "object?[]?" -> "object[]".
- $paramDataNode->type(typeRemoveNullableSuffix($type));
+ $paramDataNode->type($type);
$paramDataNode->isOptional(0);
$paramDataNode->isVariadic($self->parseEllipsis());
$paramDataNode->name($self->parseArgumentName());
@@ -1504,16 +1713,17 @@ sub parseExceptionField
my $next = $self->nextToken();
if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) {
- my $newDataNode = domAttribute->new();
- $newDataNode->type("attribute");
+ my $newDataNode = IDLAttribute->new();
$newDataNode->isReadOnly(1);
- $newDataNode->signature(domSignature->new());
- $newDataNode->signature->type($self->parseType());
+
+ my $type = $self->parseType();
+ $newDataNode->type($type);
+
my $token = $self->getToken();
$self->assertTokenType($token, IdentifierToken);
- $newDataNode->signature->name(identifierRemoveNullablePrefix($token->value()));
+ $newDataNode->name(identifierRemoveNullablePrefix($token->value()));
$self->assertTokenValue($self->getToken(), ";", __LINE__);
- $newDataNode->signature->extendedAttributes($extendedAttributeList);
+ $newDataNode->extendedAttributes($extendedAttributeList);
return $newDataNode;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
@@ -1594,9 +1804,9 @@ sub parseExtendedAttribute
{
my $self = shift;
my $next = $self->nextToken();
- if ($next->type() == IdentifierToken || $next->value() eq "::") {
- my $scopedName = $self->parseScopedName();
- return $self->parseExtendedAttributeRest($scopedName);
+ if ($next->type() == IdentifierToken) {
+ my $name = $self->parseName();
+ return $self->parseExtendedAttributeRest($name);
}
# backward compatibility. Spec doesn' allow "[]". But WebKit requires.
if ($next->value() eq ']') {
@@ -1609,9 +1819,9 @@ sub parseExtendedAttribute2
{
my $self = shift;
my $next = $self->nextToken();
- if ($next->type() == IdentifierToken || $next->value() eq "::") {
- my $scopedName = $self->parseScopedName();
- return $self->parseExtendedAttributeRest($scopedName);
+ if ($next->type() == IdentifierToken) {
+ my $name = $self->parseName();
+ return $self->parseExtendedAttributeRest($name);
}
return {};
}
@@ -1647,9 +1857,15 @@ sub parseExtendedAttributeRest2
{
my $self = shift;
my $next = $self->nextToken();
- if ($next->type() == IdentifierToken || $next->value() eq "::") {
- my $scopedName = $self->parseScopedName();
- return $self->parseExtendedAttributeRest3($scopedName);
+ if ($next->value() eq "(") {
+ $self->assertTokenValue($self->getToken(), "(", __LINE__);
+ my @arguments = $self->parseIdentifierList();
+ $self->assertTokenValue($self->getToken(), ")", __LINE__);
+ return @arguments;
+ }
+ if ($next->type() == IdentifierToken) {
+ my $name = $self->parseName();
+ return $self->parseExtendedAttributeRest3($name);
}
if ($next->type() == IntegerToken) {
my $token = $self->getToken();
@@ -1666,12 +1882,12 @@ sub parseExtendedAttributeRest3
my $next = $self->nextToken();
if ($next->value() eq "&") {
$self->assertTokenValue($self->getToken(), "&", __LINE__);
- my $rightValue = $self->parseScopedName();
+ my $rightValue = $self->parseName();
return $name . "&" . $rightValue;
}
if ($next->value() eq "|") {
$self->assertTokenValue($self->getToken(), "|", __LINE__);
- my $rightValue = $self->parseScopedName();
+ my $rightValue = $self->parseName();
return $name . "|" . $rightValue;
}
if ($next->value() eq "(") {
@@ -1682,30 +1898,12 @@ sub parseExtendedAttributeRest3
return $attr;
}
if ($next->type() == IdentifierToken || $next->value() =~ /$nextExtendedAttributeRest3_1/) {
- my @names = ();
- push(@names, $name);
- push(@names, @{$self->parseScopedNameListNoComma()});
- return join(' ', @names);
+ $self->parseNameNoComma();
+ return $name;
}
$self->assertUnexpectedToken($next->value());
}
-sub parseScopedNameListNoComma
-{
- my $self = shift;
- my @names = ();
-
- while (1) {
- my $next = $self->nextToken();
- if ($next->type() == IdentifierToken || $next->value() eq "::") {
- push(@names, $self->parseScopedName());
- } else {
- last;
- }
- }
- return \@names;
-}
-
sub parseArgumentNameKeyword
{
my $self = shift;
@@ -1778,9 +1976,9 @@ sub parseType
my $self = shift;
my $next = $self->nextToken();
if ($next->value() eq "(") {
- $self->parseUnionType();
- $self->parseTypeSuffix();
- return;
+ my $unionType = $self->parseUnionType();
+ $unionType->isNullable($self->parseNull());
+ return $unionType;
}
if ($next->type() == IdentifierToken || $next->value() =~ /$nextType_1/) {
return $self->parseSingleType();
@@ -1794,10 +1992,15 @@ sub parseSingleType
my $next = $self->nextToken();
if ($next->value() eq "any") {
$self->assertTokenValue($self->getToken(), "any", __LINE__);
- return "any" . $self->parseTypeSuffixStartingWithArray();
+
+ my $anyType = IDLType->new();
+ $anyType->name("any");
+ return $anyType;
}
if ($next->type() == IdentifierToken || $next->value() =~ /$nextSingleType_1/) {
- return $self->parseNonAnyType();
+ my $nonAnyType = $self->parseNonAnyType();
+ $nonAnyType->isNullable($self->parseNull());
+ return $nonAnyType;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -1806,14 +2009,20 @@ sub parseUnionType
{
my $self = shift;
my $next = $self->nextToken();
+
+ my $unionType = IDLType->new();
+ $unionType->name("UNION");
+ $unionType->isUnion(1);
+
if ($next->value() eq "(") {
$self->assertTokenValue($self->getToken(), "(", __LINE__);
- $self->parseUnionMemberType();
- $self->assertTokenValue($self->getToken(), "or", __LINE__);
- $self->parseUnionMemberType();
- $self->parseUnionMemberTypes();
+
+ push(@{$unionType->subtypes}, $self->parseUnionMemberType());
+ push(@{$unionType->subtypes}, $self->parseUnionMemberTypes());
+
$self->assertTokenValue($self->getToken(), ")", __LINE__);
- return;
+
+ return $unionType;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -1823,20 +2032,14 @@ sub parseUnionMemberType
my $self = shift;
my $next = $self->nextToken();
if ($next->value() eq "(") {
- $self->parseUnionType();
- $self->parseTypeSuffix();
- return;
- }
- if ($next->value() eq "any") {
- $self->assertTokenValue($self->getToken(), "any", __LINE__);
- $self->assertTokenValue($self->getToken(), "[", __LINE__);
- $self->assertTokenValue($self->getToken(), "]", __LINE__);
- $self->parseTypeSuffix();
- return;
+ my $unionType = $self->parseUnionType();
+ $unionType->isNullable($self->parseNull());
+ return $unionType;
}
if ($next->type() == IdentifierToken || $next->value() =~ /$nextSingleType_1/) {
- $self->parseNonAnyType();
- return;
+ my $nonAnyType = $self->parseNonAnyType();
+ $nonAnyType->isNullable($self->parseNull());
+ return $nonAnyType;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -1845,46 +2048,126 @@ sub parseUnionMemberTypes
{
my $self = shift;
my $next = $self->nextToken();
+
+ my @subtypes = ();
+
if ($next->value() eq "or") {
$self->assertTokenValue($self->getToken(), "or", __LINE__);
- $self->parseUnionMemberType();
- $self->parseUnionMemberTypes();
+ push(@subtypes, $self->parseUnionMemberType());
+ push(@subtypes, $self->parseUnionMemberTypes());
}
+
+ return @subtypes;
}
sub parseNonAnyType
{
my $self = shift;
my $next = $self->nextToken();
+
+ my $type = IDLType->new();
+
if ($next->value() =~ /$nextNonAnyType_1/) {
- return $self->parsePrimitiveType() . $self->parseTypeSuffix();
+ $type->name($self->parsePrimitiveType());
+ return $type;
}
- if ($next->value() eq "ByteString") {
- $self->assertTokenValue($self->getToken(), "ByteString", __LINE__);
- return "ByteString" . $self->parseTypeSuffix();
+ if ($next->value() =~ /$nextStringType_1/) {
+ $type->name($self->parseStringType());
+ return $type;
}
- if ($next->value() eq "DOMString") {
- $self->assertTokenValue($self->getToken(), "DOMString", __LINE__);
- return "DOMString" . $self->parseTypeSuffix();
+ if ($next->value() eq "object") {
+ $self->assertTokenValue($self->getToken(), "object", __LINE__);
+
+ $type->name("object");
+ return $type;
+ }
+ if ($next->value() eq "RegExp") {
+ $self->assertTokenValue($self->getToken(), "RegExp", __LINE__);
+
+ $type->name("RegExp");
+ return $type;
+ }
+ if ($next->value() eq "Error") {
+ $self->assertTokenValue($self->getToken(), "Error", __LINE__);
+
+ $type->name("Error");
+ return $type;
+ }
+ if ($next->value() eq "DOMException") {
+ $self->assertTokenValue($self->getToken(), "DOMException", __LINE__);
+
+ $type->name("DOMException");
+ return $type;
+ }
+ if ($next->value() eq "Date") {
+ $self->assertTokenValue($self->getToken(), "Date", __LINE__);
+
+ $type->name("Date");
+ return $type;
}
if ($next->value() eq "sequence") {
$self->assertTokenValue($self->getToken(), "sequence", __LINE__);
$self->assertTokenValue($self->getToken(), "<", __LINE__);
- my $type = $self->parseType();
+
+ my $subtype = $self->parseType();
+
$self->assertTokenValue($self->getToken(), ">", __LINE__);
- return "sequence<" . $type . ">" . $self->parseNull();
+
+ $type->name("sequence");
+ push(@{$type->subtypes}, $subtype);
+
+ return $type;
}
- if ($next->value() eq "object") {
- $self->assertTokenValue($self->getToken(), "object", __LINE__);
- return "object" . $self->parseTypeSuffix();
+ if ($next->value() eq "FrozenArray") {
+ $self->assertTokenValue($self->getToken(), "FrozenArray", __LINE__);
+ $self->assertTokenValue($self->getToken(), "<", __LINE__);
+
+ my $subtype = $self->parseType();
+
+ $self->assertTokenValue($self->getToken(), ">", __LINE__);
+
+ $type->name("FrozenArray");
+ push(@{$type->subtypes}, $subtype);
+
+ return $type;
}
- if ($next->value() eq "Date") {
- $self->assertTokenValue($self->getToken(), "Date", __LINE__);
- return "Date" . $self->parseTypeSuffix();
+ if ($next->value() eq "Promise") {
+ $self->assertTokenValue($self->getToken(), "Promise", __LINE__);
+ $self->assertTokenValue($self->getToken(), "<", __LINE__);
+
+ my $subtype = $self->parseReturnType();
+
+ $self->assertTokenValue($self->getToken(), ">", __LINE__);
+
+ $type->name("Promise");
+ push(@{$type->subtypes}, $subtype);
+
+ return $type;
}
- if ($next->type() == IdentifierToken || $next->value() eq "::") {
- my $name = identifierRemoveNullablePrefix($self->parseScopedName());
- return $name . $self->parseTypeSuffix();
+ if ($next->value() eq "record") {
+ $self->assertTokenValue($self->getToken(), "record", __LINE__);
+ $self->assertTokenValue($self->getToken(), "<", __LINE__);
+
+ my $keyType = IDLType->new();
+ $keyType->name($self->parseStringType());
+
+ $self->assertTokenValue($self->getToken(), ",", __LINE__);
+
+ my $valueType = $self->parseType();
+
+ $self->assertTokenValue($self->getToken(), ">", __LINE__);
+
+ $type->name("record");
+ push(@{$type->subtypes}, $keyType);
+ push(@{$type->subtypes}, $valueType);
+
+ return $type;
+ }
+ if ($next->type() == IdentifierToken) {
+ my $identifier = $self->getToken();
+
+ $type->name(identifierRemoveNullablePrefix($identifier->value()));
+ return $type;
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -1893,12 +2176,40 @@ sub parseConstType
{
my $self = shift;
my $next = $self->nextToken();
+
+ my $type = IDLType->new();
+
if ($next->value() =~ /$nextNonAnyType_1/) {
- return $self->parsePrimitiveType() . $self->parseNull();
+ $type->name($self->parsePrimitiveType());
+ $type->isNullable($self->parseNull());
+ return $type;
}
if ($next->type() == IdentifierToken) {
- my $token = $self->getToken();
- return $token->value() . $self->parseNull();
+ my $identifier = $self->getToken();
+
+ $type->name($identifier->value());
+ $type->isNullable($self->parseNull());
+
+ return $type;
+ }
+ $self->assertUnexpectedToken($next->value(), __LINE__);
+}
+
+sub parseStringType
+{
+ my $self = shift;
+ my $next = $self->nextToken();
+ if ($next->value() eq "ByteString") {
+ $self->assertTokenValue($self->getToken(), "ByteString", __LINE__);
+ return "ByteString";
+ }
+ if ($next->value() eq "DOMString") {
+ $self->assertTokenValue($self->getToken(), "DOMString", __LINE__);
+ return "DOMString";
+ }
+ if ($next->value() eq "USVString") {
+ $self->assertTokenValue($self->getToken(), "USVString", __LINE__);
+ return "USVString";
}
$self->assertUnexpectedToken($next->value(), __LINE__);
}
@@ -2004,43 +2315,15 @@ sub parseOptionalLong
return 0;
}
-sub parseTypeSuffix
-{
- my $self = shift;
- my $next = $self->nextToken();
- if ($next->value() eq "[") {
- $self->assertTokenValue($self->getToken(), "[", __LINE__);
- $self->assertTokenValue($self->getToken(), "]", __LINE__);
- return "[]" . $self->parseTypeSuffix();
- }
- if ($next->value() eq "?") {
- $self->assertTokenValue($self->getToken(), "?", __LINE__);
- return "?" . $self->parseTypeSuffixStartingWithArray();
- }
- return "";
-}
-
-sub parseTypeSuffixStartingWithArray
-{
- my $self = shift;
- my $next = $self->nextToken();
- if ($next->value() eq "[") {
- $self->assertTokenValue($self->getToken(), "[", __LINE__);
- $self->assertTokenValue($self->getToken(), "]", __LINE__);
- return "[]" . $self->parseTypeSuffix();
- }
- return "";
-}
-
sub parseNull
{
my $self = shift;
my $next = $self->nextToken();
if ($next->value() eq "?") {
$self->assertTokenValue($self->getToken(), "?", __LINE__);
- return "?";
+ return 1;
}
- return "";
+ return 0;
}
sub parseReturnType
@@ -2049,7 +2332,10 @@ sub parseReturnType
my $next = $self->nextToken();
if ($next->value() eq "void") {
$self->assertTokenValue($self->getToken(), "void", __LINE__);
- return "void";
+
+ my $voidType = IDLType->new();
+ $voidType->name("void");
+ return $voidType;
}
if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) {
return $self->parseType();
@@ -2057,17 +2343,6 @@ sub parseReturnType
$self->assertUnexpectedToken($next->value(), __LINE__);
}
-sub parseIn
-{
- my $self = shift;
- my $next = $self->nextToken();
- if ($next->value() eq "in") {
- $self->assertTokenValue($self->getToken(), "in", __LINE__);
- return "in";
- }
- return "";
-}
-
sub parseOptionalSemicolon
{
my $self = shift;
@@ -2077,115 +2352,72 @@ sub parseOptionalSemicolon
}
}
-sub parseScopedName
+sub parseNameNoComma
{
my $self = shift;
my $next = $self->nextToken();
- if ($next->value() eq "::") {
- return $self->parseAbsoluteScopedName();
- }
if ($next->type() == IdentifierToken) {
- return $self->parseRelativeScopedName();
+ my $identifier = $self->getToken();
+ return ($identifier->value());
}
- $self->assertUnexpectedToken($next->value());
-}
-sub parseAbsoluteScopedName
-{
- my $self = shift;
- my $next = $self->nextToken();
- if ($next->value() eq "::") {
- $self->assertTokenValue($self->getToken(), "::");
- my $token = $self->getToken();
- $self->assertTokenType($token, IdentifierToken);
- return "::" . $token->value() . $self->parseScopedNameParts();
- }
- $self->assertUnexpectedToken($next->value());
+ return ();
}
-sub parseRelativeScopedName
+sub parseName
{
my $self = shift;
my $next = $self->nextToken();
if ($next->type() == IdentifierToken) {
- my $token = $self->getToken();
- return $token->value() . $self->parseScopedNameParts();
+ my $identifier = $self->getToken();
+ return $identifier->value();
}
$self->assertUnexpectedToken($next->value());
}
-sub parseScopedNameParts
-{
- my $self = shift;
- my @names = ();
-
- while (1) {
- my $next = $self->nextToken();
- if ($next->value() eq "::") {
- $self->assertTokenValue($self->getToken(), "::");
- push(@names, "::");
- my $token = $self->getToken();
- $self->assertTokenType($token, IdentifierToken);
- push(@names, $token->value());
- } else {
- last;
- }
- }
- return join("", @names);
-}
-
-sub parseScopedNameList
-{
- my $self = shift;
- my $next = $self->nextToken();
- if ($next->type() == IdentifierToken || $next->value() eq "::") {
- my @names = ();
- push(@names, $self->parseScopedName());
- push(@names, @{$self->parseScopedNames()});
- return \@names;
- }
- $self->assertUnexpectedToken($next->value(), __LINE__);
-}
-
-sub parseScopedNames
-{
- my $self = shift;
- my @names = ();
-
- while (1) {
- my $next = $self->nextToken();
- if ($next->value() eq ",") {
- $self->assertTokenValue($self->getToken(), ",");
- push(@names, $self->parseScopedName());
- } else {
- last;
- }
- }
- return \@names;
-}
-
sub applyMemberList
{
my $interface = shift;
my $members = shift;
for my $item (@{$members}) {
- if (ref($item) eq "domAttribute") {
+ if (ref($item) eq "IDLAttribute") {
push(@{$interface->attributes}, $item);
next;
}
- if (ref($item) eq "domConstant") {
+ if (ref($item) eq "IDLConstant") {
push(@{$interface->constants}, $item);
next;
}
- if (ref($item) eq "domFunction") {
- if ($item->signature->name eq "") {
+ if (ref($item) eq "IDLIterable") {
+ $interface->iterable($item);
+ next;
+ }
+ if (ref($item) eq "IDLOperation") {
+ if ($item->name eq "") {
push(@{$interface->anonymousFunctions}, $item);
} else {
push(@{$interface->functions}, $item);
}
next;
}
+ if (ref($item) eq "IDLSerializable") {
+ $interface->serializable($item);
+ next;
+ }
+ }
+
+ if ($interface->serializable) {
+ my $numSerializerAttributes = @{$interface->serializable->attributes};
+ if ($interface->serializable->hasAttribute) {
+ foreach my $attribute (@{$interface->attributes}) {
+ push(@{$interface->serializable->attributes}, $attribute->name);
+ }
+ } elsif ($numSerializerAttributes == 0) {
+ foreach my $attribute (@{$interface->attributes}) {
+ push(@{$interface->serializable->attributes}, $attribute->name);
+ }
+ }
}
}
@@ -2198,25 +2430,22 @@ sub applyExtendedAttributeList
my @constructorParams = @{$extendedAttributeList->{"Constructors"}};
my $index = (@constructorParams == 1) ? 0 : 1;
foreach my $param (@constructorParams) {
- my $constructor = domFunction->new();
- $constructor->signature(domSignature->new());
- $constructor->signature->name("Constructor");
- $constructor->signature->extendedAttributes($extendedAttributeList);
- $constructor->parameters($param);
- $constructor->{overloadedIndex} = $index++;
+ my $constructor = IDLOperation->new();
+ $constructor->name("Constructor");
+ $constructor->extendedAttributes($extendedAttributeList);
+ $constructor->arguments($param);
push(@{$interface->constructors}, $constructor);
}
delete $extendedAttributeList->{"Constructors"};
$extendedAttributeList->{"Constructor"} = "VALUE_IS_MISSING";
} elsif (defined $extendedAttributeList->{"NamedConstructor"}) {
- my $newDataNode = domFunction->new();
- $newDataNode->signature(domSignature->new());
- $newDataNode->signature->name("NamedConstructor");
- $newDataNode->signature->extendedAttributes($extendedAttributeList);
+ my $newDataNode = IDLOperation->new();
+ $newDataNode->name("NamedConstructor");
+ $newDataNode->extendedAttributes($extendedAttributeList);
my %attributes = %{$extendedAttributeList->{"NamedConstructor"}};
my @attributeKeys = keys (%attributes);
my $constructorName = $attributeKeys[0];
- push(@{$newDataNode->parameters}, @{$attributes{$constructorName}});
+ push(@{$newDataNode->arguments}, @{$attributes{$constructorName}});
$extendedAttributeList->{"NamedConstructor"} = $constructorName;
push(@{$interface->constructors}, $newDataNode);
}
@@ -2224,12 +2453,10 @@ sub applyExtendedAttributeList
my @customConstructorParams = @{$extendedAttributeList->{"CustomConstructors"}};
my $index = (@customConstructorParams == 1) ? 0 : 1;
foreach my $param (@customConstructorParams) {
- my $customConstructor = domFunction->new();
- $customConstructor->signature(domSignature->new());
- $customConstructor->signature->name("CustomConstructor");
- $customConstructor->signature->extendedAttributes($extendedAttributeList);
- $customConstructor->parameters($param);
- $customConstructor->{overloadedIndex} = $index++;
+ my $customConstructor = IDLOperation->new();
+ $customConstructor->name("CustomConstructor");
+ $customConstructor->extendedAttributes($extendedAttributeList);
+ $customConstructor->arguments($param);
push(@{$interface->customConstructors}, $customConstructor);
}
delete $extendedAttributeList->{"CustomConstructors"};