| Index: Source/bindings/scripts/unstable/blink_idl_parser.py
|
| diff --git a/Source/bindings/scripts/unstable/blink_idl_parser.py b/Source/bindings/scripts/unstable/blink_idl_parser.py
|
| deleted file mode 100644
|
| index bf40c68e1b7379d5669807aa54321c2e0921f21c..0000000000000000000000000000000000000000
|
| --- a/Source/bindings/scripts/unstable/blink_idl_parser.py
|
| +++ /dev/null
|
| @@ -1,425 +0,0 @@
|
| -# Copyright (C) 2013 Google Inc. All rights reserved.
|
| -#
|
| -# Redistribution and use in source and binary forms, with or without
|
| -# modification, are permitted provided that the following conditions are
|
| -# met:
|
| -#
|
| -# * Redistributions of source code must retain the above copyright
|
| -# notice, this list of conditions and the following disclaimer.
|
| -# * Redistributions in binary form must reproduce the above
|
| -# copyright notice, this list of conditions and the following disclaimer
|
| -# in the documentation and/or other materials provided with the
|
| -# distribution.
|
| -# * Neither the name of Google Inc. nor the names of its
|
| -# contributors may be used to endorse or promote products derived from
|
| -# this software without specific prior written permission.
|
| -#
|
| -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| -
|
| -"""Parser for Blink IDL.
|
| -
|
| -The parser uses the PLY (Python Lex-Yacc) library to build a set of parsing
|
| -rules which understand the Blink dialect of Web IDL.
|
| -It derives from a standard Web IDL parser, overriding rules where Blink IDL
|
| -differs syntactically or semantically from the base parser, or where the base
|
| -parser diverges from the Web IDL standard.
|
| -
|
| -Web IDL:
|
| - http://www.w3.org/TR/WebIDL/
|
| -Web IDL Grammar:
|
| - http://www.w3.org/TR/WebIDL/#idl-grammar
|
| -PLY:
|
| - http://www.dabeaz.com/ply/
|
| -"""
|
| -
|
| -# Disable check for line length and Member as Function due to how grammar rules
|
| -# are defined with PLY
|
| -#
|
| -# pylint: disable=R0201
|
| -# pylint: disable=C0301
|
| -#
|
| -# Disable attribute validation, as lint can't import parent class to check
|
| -# pylint: disable=E1101
|
| -
|
| -import os.path
|
| -import sys
|
| -
|
| -# PLY is in Chromium src/third_party/ply
|
| -module_path, module_name = os.path.split(__file__)
|
| -third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir)
|
| -# Insert at front to override system libraries, and after path[0] == script dir
|
| -sys.path.insert(1, third_party)
|
| -from ply import yacc
|
| -
|
| -# Base parser is in Chromium src/tools/idl_parser
|
| -tools_dir = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir, 'tools')
|
| -sys.path.append(tools_dir)
|
| -from idl_parser.idl_parser import IDLParser, ListFromConcat
|
| -from idl_parser.idl_parser import ParseFile as parse_file
|
| -
|
| -from blink_idl_lexer import BlinkIDLLexer
|
| -
|
| -
|
| -# Explicitly set starting symbol to rule defined only in base parser.
|
| -# BEWARE that the starting symbol should NOT be defined in both the base parser
|
| -# and the derived one, as otherwise which is used depends on which line number
|
| -# is lower, which is fragile. Instead, either use one in base parser or
|
| -# create a new symbol, so that this is unambiguous.
|
| -# FIXME: unfortunately, this doesn't work in PLY 3.4, so need to duplicate the
|
| -# rule below.
|
| -STARTING_SYMBOL = 'Definitions'
|
| -
|
| -# We ignore comments (and hence don't need 'Top') but base parser preserves them
|
| -# FIXME: Upstream: comments should be removed in base parser
|
| -REMOVED_RULES = ['Top', # [0]
|
| - 'Comments', # [0.1]
|
| - 'CommentsRest', # [0.2]
|
| - ]
|
| -
|
| -
|
| -class BlinkIDLParser(IDLParser):
|
| - # [1]
|
| - # FIXME: Need to duplicate rule for starting symbol here, with line number
|
| - # *lower* than in the base parser (idl_parser.py).
|
| - # This is a bug in PLY: it determines starting symbol by lowest line number.
|
| - # This can be overridden by the 'start' parameter, but as of PLY 3.4 this
|
| - # doesn't work correctly.
|
| - def p_Definitions(self, p):
|
| - """Definitions : ExtendedAttributeList Definition Definitions
|
| - | """
|
| - if len(p) > 1:
|
| - p[2].AddChildren(p[1])
|
| - p[0] = ListFromConcat(p[2], p[3])
|
| -
|
| - # Below are grammar rules used by yacc, given by functions named p_<RULE>.
|
| - # * The docstring is the production rule in BNF (grammar).
|
| - # * The body is the yacc action (semantics).
|
| - #
|
| - # The PLY framework builds the actual low-level parser by introspecting this
|
| - # parser object, selecting all attributes named p_<RULE> as grammar rules.
|
| - # It extracts the docstrings and uses them as the production rules, building
|
| - # the table of a LALR parser, and uses the body of the functions as actions.
|
| - #
|
| - # Reference:
|
| - # http://www.dabeaz.com/ply/ply.html#ply_nn23
|
| - #
|
| - # Review of yacc:
|
| - # Yacc parses a token stream, internally producing a Concrete Syntax Tree
|
| - # (CST), where each node corresponds to a production rule in the grammar.
|
| - # At each node, it runs an action, which is usually "produce a node in the
|
| - # Abstract Syntax Tree (AST)" or "ignore this node" (for nodes in the CST
|
| - # that aren't included in the AST, since only needed for parsing).
|
| - #
|
| - # The rules use pseudo-variables; in PLY syntax:
|
| - # p[0] is the left side: assign return value to p[0] instead of returning,
|
| - # p[1] ... p[n] are the right side: the values can be accessed, and they
|
| - # can be modified.
|
| - # (In yacc these are $$ and $1 ... $n.)
|
| - #
|
| - # The rules can look cryptic at first, but there are a few standard
|
| - # transforms from the CST to AST. With these in mind, the actions should
|
| - # be reasonably legible.
|
| - #
|
| - # * Ignore production
|
| - # Discard this branch. Primarily used when one alternative is empty.
|
| - #
|
| - # Sample code:
|
| - # if len(p) > 1:
|
| - # p[0] = ...
|
| - # # Note no assignment if len(p) == 1
|
| - #
|
| - # * Eliminate singleton production
|
| - # Discard this node in the CST, pass the next level down up the tree.
|
| - # Used to ignore productions only necessary for parsing, but not needed
|
| - # in the AST.
|
| - #
|
| - # Sample code:
|
| - # p[0] = p[1]
|
| - #
|
| - # * Build node
|
| - # The key type of rule. In this parser, produces object of class IDLNode.
|
| - # There are several helper functions:
|
| - # * BuildProduction: actually builds an IDLNode, based on a production.
|
| - # * BuildAttribute: builds an IDLAttribute, which is a temporary
|
| - # object to hold a name-value pair, which is then
|
| - # set as a Property of the IDLNode when the IDLNode
|
| - # is built.
|
| - # * BuildNamed: Same as BuildProduction, and sets the 'NAME' property.
|
| - # * BuildTrue: BuildAttribute with value True, for flags.
|
| - # See base idl_parser.py for definitions and more examples of use.
|
| - #
|
| - # Sample code:
|
| - # # Build node of type NodeType, with value p[1], and children.
|
| - # p[0] = self.BuildProduction('NodeType', p, 1, children)
|
| - #
|
| - # # Build named node of type NodeType, with name and value p[1].
|
| - # # (children optional)
|
| - # p[0] = self.BuildNamed('NodeType', p, 1)
|
| - #
|
| - # # Make a list
|
| - # # Used if one node has several children.
|
| - # children = ListFromConcat(p[2], p[3])
|
| - # p[0] = self.BuildProduction('NodeType', p, 1, children)
|
| - #
|
| - # # Also used to collapse the right-associative tree
|
| - # # produced by parsing a list back into a single list.
|
| - # """Foos : Foo Foos
|
| - # |"""
|
| - # if len(p) > 1:
|
| - # p[0] = ListFromConcat(p[1], p[2])
|
| - #
|
| - # # Add children.
|
| - # # Primarily used to add attributes, produced via BuildTrue.
|
| - # # p_StaticAttribute
|
| - # """StaticAttribute : STATIC Attribute"""
|
| - # p[2].AddChildren(self.BuildTrue('STATIC'))
|
| - # p[0] = p[2]
|
| - #
|
| - # Numbering scheme for the rules is:
|
| - # [1] for Web IDL spec (or additions in base parser)
|
| - # These should all be upstreamed to the base parser.
|
| - # [b1] for Blink IDL changes (overrides Web IDL)
|
| - # [b1.1] for Blink IDL additions, auxiliary rules for [b1]
|
| - # Numbers are as per Candidate Recommendation 19 April 2012:
|
| - # http://www.w3.org/TR/2012/CR-WebIDL-20120419/
|
| -
|
| - # [3] Override action, since we distinguish callbacks
|
| - # FIXME: Upstream
|
| - def p_CallbackOrInterface(self, p):
|
| - """CallbackOrInterface : CALLBACK CallbackRestOrInterface
|
| - | Interface"""
|
| - if len(p) > 2:
|
| - p[2].AddChildren(self.BuildTrue('CALLBACK'))
|
| - p[0] = p[2]
|
| - else:
|
| - p[0] = p[1]
|
| -
|
| - # [b27] Add strings, more 'Literal' productions
|
| - # 'Literal's needed because integers and strings are both internally strings
|
| - def p_ConstValue(self, p):
|
| - """ConstValue : BooleanLiteral
|
| - | FloatLiteral
|
| - | IntegerLiteral
|
| - | StringLiteral
|
| - | null"""
|
| - # Standard is (no 'string', fewer 'Literal's):
|
| - # ConstValue : BooleanLiteral
|
| - # | FloatLiteral
|
| - # | integer
|
| - # | NULL
|
| - p[0] = p[1]
|
| -
|
| - # [b27.1]
|
| - def p_IntegerLiteral(self, p):
|
| - """IntegerLiteral : integer"""
|
| - p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'integer'),
|
| - self.BuildAttribute('NAME', p[1]))
|
| -
|
| - # [b27.2]
|
| - def p_StringLiteral(self, p):
|
| - """StringLiteral : string"""
|
| - p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'DOMString'),
|
| - self.BuildAttribute('NAME', p[1]))
|
| -
|
| - # [b30] Add StaticAttribute
|
| - def p_AttributeOrOperation(self, p):
|
| - """AttributeOrOperation : STRINGIFIER StringifierAttributeOrOperation
|
| - | Attribute
|
| - | StaticAttribute
|
| - | Operation"""
|
| - # Standard is (no StaticAttribute):
|
| - # AttributeOrOperation : STRINGIFIER StringifierAttributeOrOperation
|
| - # | Attribute
|
| - # | Operation
|
| - if len(p) > 2:
|
| - # FIXME: Clearer to add stringifier property here, as:
|
| - # p[2].AddChildren(self.BuildTrue('STRINGIFIER'))
|
| - # Fix when actually implementing stringifiers.
|
| - p[0] = p[2]
|
| - else:
|
| - p[0] = p[1]
|
| -
|
| - # [b30.1]
|
| - def p_StaticAttribute(self, p):
|
| - """StaticAttribute : STATIC Attribute"""
|
| - p[2].AddChildren(self.BuildTrue('STATIC'))
|
| - p[0] = p[2]
|
| -
|
| - # [b47]
|
| - def p_ExceptionMember(self, p):
|
| - """ExceptionMember : Const
|
| - | ExceptionField
|
| - | Attribute
|
| - | ExceptionOperation"""
|
| - # Standard is (no Attribute, no ExceptionOperation):
|
| - # ExceptionMember : Const
|
| - # | ExceptionField
|
| - # FIXME: In DOMException.idl, Attributes should be changed to
|
| - # ExceptionFields, and Attribute removed from this rule.
|
| - p[0] = p[1]
|
| -
|
| - # [b47.1]
|
| - def p_ExceptionOperation(self, p):
|
| - """ExceptionOperation : Type identifier '(' ')' ';'"""
|
| - # Needed to handle one case in DOMException.idl:
|
| - # // Override in a Mozilla compatible format
|
| - # [NotEnumerable] DOMString toString();
|
| - # Limited form of Operation to prevent others from being added.
|
| - # FIXME: Should be a stringifier instead.
|
| - p[0] = self.BuildNamed('ExceptionOperation', p, 2, p[1])
|
| -
|
| - # Extended attributes
|
| - # [b49] Override base parser: remove comment field, since comments stripped
|
| - # FIXME: Upstream
|
| - def p_ExtendedAttributeList(self, p):
|
| - """ExtendedAttributeList : '[' ExtendedAttribute ExtendedAttributes ']'
|
| - | '[' ']'
|
| - | """
|
| - if len(p) > 3:
|
| - items = ListFromConcat(p[2], p[3])
|
| - p[0] = self.BuildProduction('ExtAttributes', p, 1, items)
|
| -
|
| - # [b50] Allow optional trailing comma
|
| - # Blink-only, marked as WONTFIX in Web IDL spec:
|
| - # https://www.w3.org/Bugs/Public/show_bug.cgi?id=22156
|
| - def p_ExtendedAttributes(self, p):
|
| - """ExtendedAttributes : ',' ExtendedAttribute ExtendedAttributes
|
| - | ','
|
| - |"""
|
| - if len(p) > 3:
|
| - p[0] = ListFromConcat(p[2], p[3])
|
| -
|
| - # [b51] Add ExtendedAttributeIdentAndOrIdent
|
| - def p_ExtendedAttribute(self, p):
|
| - """ExtendedAttribute : ExtendedAttributeNoArgs
|
| - | ExtendedAttributeArgList
|
| - | ExtendedAttributeIdent
|
| - | ExtendedAttributeIdentList
|
| - | ExtendedAttributeStringLiteralList
|
| - | ExtendedAttributeNamedArgList"""
|
| - p[0] = p[1]
|
| -
|
| - # [59]
|
| - # FIXME: Upstream UnionType
|
| - def p_UnionType(self, p):
|
| - """UnionType : '(' UnionMemberType OR UnionMemberType UnionMemberTypes ')'"""
|
| - members = ListFromConcat(p[2], p[4], p[5])
|
| - p[0] = self.BuildProduction('UnionType', p, 1, members)
|
| -
|
| - # [60]
|
| - def p_UnionMemberType(self, p):
|
| - """UnionMemberType : NonAnyType
|
| - | UnionType TypeSuffix
|
| - | ANY '[' ']' TypeSuffix"""
|
| - if len(p) == 2:
|
| - p[0] = self.BuildProduction('Type', p, 1, p[1])
|
| - elif len(p) == 3:
|
| - p[0] = self.BuildProduction('Type', p, 1, ListFromConcat(p[1], p[2]))
|
| - else:
|
| - any_node = ListFromConcat(self.BuildProduction('Any', p, 1), p[4])
|
| - p[0] = self.BuildProduction('Type', p, 1, any_node)
|
| -
|
| - # [61]
|
| - def p_UnionMemberTypes(self, p):
|
| - """UnionMemberTypes : OR UnionMemberType UnionMemberTypes
|
| - |"""
|
| - if len(p) > 2:
|
| - p[0] = ListFromConcat(p[2], p[3])
|
| -
|
| - # [70] Override base parser to remove non-standard sized array
|
| - # FIXME: Upstream
|
| - def p_TypeSuffix(self, p):
|
| - """TypeSuffix : '[' ']' TypeSuffix
|
| - | '?' TypeSuffixStartingWithArray
|
| - |"""
|
| - if len(p) == 4:
|
| - p[0] = self.BuildProduction('Array', p, 1, p[3])
|
| - elif len(p) == 3:
|
| - p[0] = ListFromConcat(self.BuildTrue('NULLABLE'), p[2])
|
| -
|
| - # [b76.1] Add support for compound Extended Attribute values (A&B and A|B)
|
| - def p_ExtendedAttributeIdentList(self, p):
|
| - """ExtendedAttributeIdentList : identifier '=' identifier '&' IdentAndList
|
| - | identifier '=' identifier '|' IdentOrList"""
|
| - value = self.BuildAttribute('VALUE', p[3] + p[4] + p[5])
|
| - p[0] = self.BuildNamed('ExtAttribute', p, 1, value)
|
| -
|
| - # [b76.2] A&B&C
|
| - def p_IdentAndList(self, p):
|
| - """IdentAndList : identifier '&' IdentAndList
|
| - | identifier"""
|
| - if len(p) > 3:
|
| - p[0] = p[1] + p[2] + p[3]
|
| - else:
|
| - p[0] = p[1]
|
| -
|
| - # [b76.3] A|B|C
|
| - def p_IdentOrList(self, p):
|
| - """IdentOrList : identifier '|' IdentOrList
|
| - | identifier"""
|
| - if len(p) > 3:
|
| - p[0] = p[1] + p[2] + p[3]
|
| - else:
|
| - p[0] = p[1]
|
| -
|
| - # Blink extension: Add support for compound Extended Attribute values over string literals ("A"|"B")
|
| - def p_ExtendedAttributeStringLiteralList(self, p):
|
| - """ExtendedAttributeStringLiteralList : identifier '=' StringLiteralOrList"""
|
| - value = self.BuildAttribute('VALUE', p[3])
|
| - p[0] = self.BuildNamed('ExtAttribute', p, 1, value)
|
| -
|
| - # Blink extension: one or more string literals. The values aren't propagated as literals,
|
| - # but their by their value only.
|
| - def p_StringLiteralOrList(self, p):
|
| - """StringLiteralOrList : StringLiteral '|' StringLiteralOrList
|
| - | StringLiteral"""
|
| - def unwrap_string(ls):
|
| - """Reach in and grab the string literal's "NAME"."""
|
| - return ls[1].value
|
| -
|
| - if len(p) > 3:
|
| - p[0] = unwrap_string(p[1]) + p[2] + p[3]
|
| - else:
|
| - p[0] = unwrap_string(p[1])
|
| -
|
| - def __dir__(self):
|
| - # Remove REMOVED_RULES from listing so yacc doesn't parse them
|
| - # FIXME: Upstream
|
| - keys = set(self.__dict__.keys() + dir(self.__class__))
|
| - for rule in REMOVED_RULES:
|
| - production_name = 'p_' + rule
|
| - if production_name in keys:
|
| - keys.remove(production_name)
|
| - return list(keys)
|
| -
|
| - def __init__(self, lexer=None, verbose=False, debug=False, mute_error=False, outputdir=''):
|
| - lexer = lexer or BlinkIDLLexer()
|
| - self.lexer = lexer
|
| - self.tokens = lexer.KnownTokens()
|
| - # Using SLR (instead of LALR) generates the table faster,
|
| - # but produces the same output. This is ok b/c Web IDL (and Blink IDL)
|
| - # is an SLR grammar (as is often the case for simple LL(1) grammars).
|
| - self.yaccobj = yacc.yacc(module=self, start=STARTING_SYMBOL, method='SLR', debug=debug, outputdir=outputdir)
|
| - self.parse_debug = debug
|
| - self.verbose = verbose
|
| - self.mute_error = mute_error
|
| - self._parse_errors = 0
|
| - self._parse_warnings = 0
|
| - self._last_error_msg = None
|
| - self._last_error_lineno = 0
|
| - self._last_error_pos = 0
|
| -
|
| -
|
| -# If run by itself, attempt to build the parser
|
| -if __name__ == '__main__':
|
| - parser = BlinkIDLParser()
|
|
|