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() |