diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:52 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:52 -0800 |
commit | 8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (patch) | |
tree | 11425ea0b299d6fb89c6d3618a22d97d5bf68d0f /WebCore/bindings/scripts/IDLParser.pm | |
parent | 648161bb0edfc3d43db63caed5cc5213bc6cb78f (diff) | |
download | external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.zip external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.gz external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'WebCore/bindings/scripts/IDLParser.pm')
-rw-r--r-- | WebCore/bindings/scripts/IDLParser.pm | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/WebCore/bindings/scripts/IDLParser.pm b/WebCore/bindings/scripts/IDLParser.pm new file mode 100644 index 0000000..de7cf9c --- /dev/null +++ b/WebCore/bindings/scripts/IDLParser.pm @@ -0,0 +1,416 @@ +# +# KDOM IDL parser +# +# Copyright (C) 2005 Nikolas Zimmermann <wildfox@kde.org> +# +# This file is part of the KDE project +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public License +# aint with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# + +package IDLParser; + +use IPC::Open2; +use IDLStructure; + +use constant MODE_UNDEF => 0; # Default mode. + +use constant MODE_MODULE => 10; # 'module' section +use constant MODE_INTERFACE => 11; # 'interface' section +use constant MODE_EXCEPTION => 12; # 'exception' section +use constant MODE_ALIAS => 13; # 'alias' section + +# Helper variables +my @temporaryContent = ""; + +my $parseMode = MODE_UNDEF; +my $preservedParseMode = MODE_UNDEF; + +my $beQuiet; # Should not display anything on STDOUT? +my $document = 0; # Will hold the resulting 'idlDocument' + +# Default Constructor +sub new +{ + my $object = shift; + my $reference = { }; + + $document = 0; + $beQuiet = shift; + + bless($reference, $object); + return $reference; +} + +# Returns the parsed 'idlDocument' +sub Parse +{ + my $object = shift; + my $fileName = shift; + my $defines = shift; + my $preprocessor = shift; + + if (!$preprocessor) { + $preprocessor = "/usr/bin/gcc -E -P -x c++"; + } + + if (!$defines) { + $defines = ""; + } + + print " | *** Starting to parse $fileName...\n |\n" unless $beQuiet; + + open2(\*PP_OUT, \*PP_IN, split(' ', $preprocessor), (map { "-D$_" } split(' ', $defines)), $fileName); + close PP_IN; + my @documentContent = <PP_OUT>; + close PP_OUT; + + my $dataAvailable = 0; + + # Simple IDL Parser (tm) + foreach (@documentContent) { + my $newParseMode = $object->DetermineParseMode($_); + + if ($newParseMode ne MODE_UNDEF) { + if ($dataAvailable eq 0) { + $dataAvailable = 1; # Start node building... + } else { + $object->ProcessSection(); + } + } + + # Update detected data stream mode... + if ($newParseMode ne MODE_UNDEF) { + $parseMode = $newParseMode; + } + + push(@temporaryContent, $_); + } + + # Check if there is anything remaining to parse... + if (($parseMode ne MODE_UNDEF) and ($#temporaryContent > 0)) { + $object->ProcessSection(); + } + + print " | *** Finished parsing!\n" unless $beQuiet; + + $document->fileName($fileName); + + return $document; +} + +sub ParseModule +{ + my $object = shift; + my $dataNode = shift; + + print " |- Trying to parse module...\n" unless $beQuiet; + + my $data = join("", @temporaryContent); + $data =~ /$IDLStructure::moduleSelector/; + + my $moduleName = (defined($1) ? $1 : die("Parsing error!\nSource:\n$data\n)")); + $dataNode->module($moduleName); + + print " |----> Module; NAME \"$moduleName\"\n |-\n |\n" unless $beQuiet; +} + +sub dumpExtendedAttributes +{ + my $padStr = shift; + my $attrs = shift; + + if (!%{$attrs}) { + return ""; + } + + my @temp; + while (($name, $value) = each(%{$attrs})) { + push(@temp, "$name=$value"); + } + + return $padStr . "[" . join(", ", @temp) . "]"; +} + +sub parseExtendedAttributes +{ + my $str = shift; + $str =~ s/\[\s*(.*?)\s*\]/$1/g; + + my %attrs = (); + + foreach my $value (split(/\s*,\s*/, $str)) { + ($name,$value) = split(/\s*=\s*/, $value, 2); + + # Attributes with no value are set to be true + $value = 1 unless defined $value; + $attrs{$name} = $value; + } + + return \%attrs; +} + +sub ParseInterface +{ + my $object = shift; + my $dataNode = shift; + my $sectionName = shift; + + my $data = join("", @temporaryContent); + + # Look for end-of-interface mark + $data =~ /};/g; + $data = substr($data, index($data, $sectionName), pos($data) - length($data)); + + $data =~ s/[\n\r]/ /g; + + # Beginning of the regexp parsing magic + if ($sectionName eq "exception") { + print " |- Trying to parse exception...\n" unless $beQuiet; + + my $exceptionName = ""; + my $exceptionData = ""; + my $exceptionDataName = ""; + my $exceptionDataType = ""; + + # Match identifier of the exception, and enclosed data... + $data =~ /$IDLStructure::exceptionSelector/; + $exceptionName = (defined($1) ? $1 : die("Parsing error!\nSource:\n$data\n)")); + $exceptionData = (defined($2) ? $2 : die("Parsing error!\nSource:\n$data\n)")); + + ('' =~ /^/); # Reset variables needed for regexp matching + + # ... parse enclosed data (get. name & type) + $exceptionData =~ /$IDLStructure::exceptionSubSelector/; + $exceptionDataType = (defined($1) ? $1 : die("Parsing error!\nSource:\n$data\n)")); + $exceptionDataName = (defined($2) ? $2 : die("Parsing error!\nSource:\n$data\n)")); + + # Fill in domClass datastructure + $dataNode->name($exceptionName); + + my $newDataNode = new domAttribute(); + $newDataNode->type("readonly attribute"); + $newDataNode->signature(new domSignature()); + + $newDataNode->signature->name($exceptionDataName); + $newDataNode->signature->type($exceptionDataType); + + my $arrayRef = $dataNode->attributes; + push(@$arrayRef, $newDataNode); + + print " |----> Exception; NAME \"$exceptionName\" DATA TYPE \"$exceptionDataType\" DATA NAME \"$exceptionDataName\"\n |-\n |\n" unless $beQuiet; + } elsif ($sectionName eq "interface") { + print " |- Trying to parse interface...\n" unless $beQuiet; + + my $interfaceName = ""; + my $interfaceData = ""; + + # Match identifier of the interface, and enclosed data... + $data =~ /$IDLStructure::interfaceSelector/; + + $interfaceExtendedAttributes = (defined($1) ? $1 : " "); chop($interfaceExtendedAttributes); + $interfaceName = (defined($2) ? $2 : die("Parsing error!\nSource:\n$data\n)")); + $interfaceBase = (defined($3) ? $3 : ""); + $interfaceData = (defined($4) ? $4 : die("Parsing error!\nSource:\n$data\n)")); + + # Fill in known parts of the domClass datastructure now... + $dataNode->name($interfaceName); + $dataNode->extendedAttributes(parseExtendedAttributes($interfaceExtendedAttributes)); + + # Inheritance detection + my @interfaceParents = split(/,/, $interfaceBase); + foreach(@interfaceParents) { + my $line = $_; + $line =~ s/\s*//g; + + my $arrayRef = $dataNode->parents; + push(@$arrayRef, $line); + } + + $interfaceData =~ s/[\n\r]/ /g; + my @interfaceMethods = split(/;/, $interfaceData); + + foreach my $line (@interfaceMethods) { + if ($line =~ /attribute/) { + $line =~ /$IDLStructure::interfaceAttributeSelector/; + + my $attributeType = (defined($1) ? $1 : die("Parsing error!\nSource:\n$line\n)")); + my $attributeExtendedAttributes = (defined($2) ? $2 : " "); chop($attributeExtendedAttributes); + + my $attributeDataType = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)")); + my $attributeDataName = (defined($4) ? $4 : die("Parsing error!\nSource:\n$line\n)")); + + ('' =~ /^/); # Reset variables needed for regexp matching + + $line =~ /$IDLStructure::getterRaisesSelector/; + my $getterException = (defined($1) ? $1 : ""); + + $line =~ /$IDLStructure::setterRaisesSelector/; + my $setterException = (defined($1) ? $1 : ""); + + my $newDataNode = new domAttribute(); + $newDataNode->type($attributeType); + $newDataNode->signature(new domSignature()); + + $newDataNode->signature->name($attributeDataName); + $newDataNode->signature->type($attributeDataType); + $newDataNode->signature->extendedAttributes(parseExtendedAttributes($attributeExtendedAttributes)); + + my $arrayRef = $dataNode->attributes; + push(@$arrayRef, $newDataNode); + + print " | |> Attribute; TYPE \"$attributeType\" DATA NAME \"$attributeDataName\" DATA TYPE \"$attributeDataType\" GET EXCEPTION? \"$getterException\" SET EXCEPTION? \"$setterException\"" . + dumpExtendedAttributes("\n | ", $newDataNode->signature->extendedAttributes) . "\n" unless $beQuiet; + + $getterException =~ s/\s+//g; + $setterException =~ s/\s+//g; + @{$newDataNode->getterExceptions} = split(/,/, $getterException); + @{$newDataNode->setterExceptions} = split(/,/, $setterException); + } elsif (($line !~ s/^\s*$//g) and ($line !~ /^\s*const/)) { + $line =~ /$IDLStructure::interfaceMethodSelector/ or die "Parsing error!\nSource:\n$line\n)"; + + my $methodExtendedAttributes = (defined($1) ? $1 : " "); chop($methodExtendedAttributes); + my $methodType = (defined($2) ? $2 : die("Parsing error!\nSource:\n$line\n)")); + my $methodName = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)")); + my $methodSignature = (defined($4) ? $4 : die("Parsing error!\nSource:\n$line\n)")); + + ('' =~ /^/); # Reset variables needed for regexp matching + + $line =~ /$IDLStructure::raisesSelector/; + my $methodException = (defined($1) ? $1 : ""); + + my $newDataNode = new domFunction(); + + $newDataNode->signature(new domSignature()); + $newDataNode->signature->name($methodName); + $newDataNode->signature->type($methodType); + $newDataNode->signature->extendedAttributes(parseExtendedAttributes($methodExtendedAttributes)); + + print " | |- Method; TYPE \"$methodType\" NAME \"$methodName\" EXCEPTION? \"$methodException\"" . + dumpExtendedAttributes("\n | ", $newDataNode->signature->extendedAttributes) . "\n" unless $beQuiet; + + $methodException =~ s/\s+//g; + @{$newDataNode->raisesExceptions} = split(/,/, $methodException); + + my @params = split(/,/, $methodSignature); + foreach(@params) { + my $line = $_; + + $line =~ /$IDLStructure::interfaceParameterSelector/; + my $paramExtendedAttributes = (defined($1) ? $1 : " "); chop($paramExtendedAttributes); + my $paramType = (defined($2) ? $2 : die("Parsing error!\nSource:\n$line\n)")); + my $paramName = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)")); + + my $paramDataNode = new domSignature(); + $paramDataNode->name($paramName); + $paramDataNode->type($paramType); + $paramDataNode->extendedAttributes(parseExtendedAttributes($paramExtendedAttributes)); + + my $arrayRef = $newDataNode->parameters; + push(@$arrayRef, $paramDataNode); + + print " | |> Param; TYPE \"$paramType\" NAME \"$paramName\"" . + dumpExtendedAttributes("\n | ", $paramDataNode->extendedAttributes) . "\n" unless $beQuiet; + } + + my $arrayRef = $dataNode->functions; + push(@$arrayRef, $newDataNode); + } elsif ($line =~ /^\s*const/) { + $line =~ /$IDLStructure::constantSelector/; + my $constType = (defined($1) ? $1 : die("Parsing error!\nSource:\n$line\n)")); + my $constName = (defined($2) ? $2 : die("Parsing error!\nSource:\n$line\n)")); + my $constValue = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)")); + + my $newDataNode = new domConstant(); + $newDataNode->name($constName); + $newDataNode->type($constType); + $newDataNode->value($constValue); + + my $arrayRef = $dataNode->constants; + push(@$arrayRef, $newDataNode); + + print " | |> Constant; TYPE \"$constType\" NAME \"$constName\" VALUE \"$constValue\"\n" unless $beQuiet; + } + } + + print " |----> Interface; NAME \"$interfaceName\"" . + dumpExtendedAttributes("\n | ", $dataNode->extendedAttributes) . "\n |-\n |\n" unless $beQuiet; + } +} + +# Internal helper +sub DetermineParseMode +{ + my $object = shift; + my $line = shift; + + my $mode = MODE_UNDEF; + if ($_ =~ /module/) { + $mode = MODE_MODULE; + } elsif ($_ =~ /interface/) { + $mode = MODE_INTERFACE; + } elsif ($_ =~ /exception/) { + $mode = MODE_EXCEPTION; + } elsif ($_ =~ /alias/) { + $mode = MODE_ALIAS; + } + + return $mode; +} + +# Internal helper +sub ProcessSection +{ + my $object = shift; + + if ($parseMode eq MODE_MODULE) { + die ("Two modules in one file! Fatal error!\n") if ($document ne 0); + $document = new idlDocument(); + $object->ParseModule($document); + } elsif ($parseMode eq MODE_INTERFACE) { + my $node = new domClass(); + $object->ParseInterface($node, "interface"); + + die ("No module specified! Fatal Error!\n") if ($document eq 0); + my $arrayRef = $document->classes; + push(@$arrayRef, $node); + } elsif($parseMode eq MODE_EXCEPTION) { + my $node = new domClass(); + $object->ParseInterface($node, "exception"); + + die ("No module specified! Fatal Error!\n") if ($document eq 0); + my $arrayRef = $document->classes; + push(@$arrayRef, $node); + } elsif($parseMode eq MODE_ALIAS) { + print " |- Trying to parse alias...\n" unless $beQuiet; + + my $line = join("", @temporaryContent); + $line =~ /$IDLStructure::aliasSelector/; + + my $interfaceName = (defined($1) ? $1 : die("Parsing error!\nSource:\n$line\n)")); + my $wrapperName = (defined($2) ? $2 : die("Parsing error!\nSource:\n$line\n)")); + + print " |----> Alias; INTERFACE \"$interfaceName\" WRAPPER \"$wrapperName\"\n |-\n |\n" unless $beQuiet; + + # FIXME: Check if alias is already in aliases + my $aliases = $document->aliases; + $aliases->{$interfaceName} = $wrapperName; + } + + @temporaryContent = ""; +} + +1; |