Index: tools/idl_parser/idl_ppapi_parser.py |
diff --git a/tools/idl_parser/idl_ppapi_parser.py b/tools/idl_parser/idl_ppapi_parser.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..9cfe953b8e68e85728a77baadc05c822c1be1c70 |
--- /dev/null |
+++ b/tools/idl_parser/idl_ppapi_parser.py |
@@ -0,0 +1,241 @@ |
+#!/usr/bin/env python |
+# Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+""" Parser for PPAPI IDL """ |
+ |
+# |
+# IDL Parser |
+# |
+# The parser is uses the PLY yacc library to build a set of parsing rules based |
+# on WebIDL. |
+# |
+# WebIDL, and WebIDL grammar can be found at: |
+# http://dev.w3.org/2006/webapi/WebIDL/ |
+# PLY can be found at: |
+# http://www.dabeaz.com/ply/ |
+# |
+# The parser generates a tree by recursively matching sets of items against |
+# defined patterns. When a match is made, that set of items is reduced |
+# to a new item. The new item can provide a match for parent patterns. |
+# In this way an AST is built (reduced) depth first. |
+# |
+ |
+# |
+# Disable check for line length and Member as Function due to how grammar rules |
+# are defined with PLY |
+# |
+# pylint: disable=R0201 |
+# pylint: disable=C0301 |
+ |
+import os.path |
+import sys |
+import time |
+ |
+from idl_ppapi_lexer import IDLPPAPILexer |
+from idl_parser import IDLParser, ListFromConcat, ParseFile |
+from idl_node import IDLAttribute, IDLNode |
+ |
+class IDLPPAPIParser(IDLParser): |
+# |
+# We force all input files to start with two comments. The first comment is a |
+# Copyright notice followed by a file comment and finally by file level |
+# productions. |
+# |
+ # [0] Insert a TOP definition for Copyright and Comments |
+ def p_Top(self, p): |
+ """Top : COMMENT COMMENT Definitions""" |
+ Copyright = self.BuildComment('Copyright', p, 1) |
+ Filedoc = self.BuildComment('Comment', p, 2) |
+ p[0] = ListFromConcat(Copyright, Filedoc, p[3]) |
+ |
+# |
+#The parser is based on the WebIDL standard. See: |
+# http://www.w3.org/TR/WebIDL/#idl-grammar |
+# |
+ # [1] |
+ 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]) |
+ |
+ # [2] Add INLINE definition |
+ def p_Definition(self, p): |
+ """Definition : CallbackOrInterface |
+ | Partial |
+ | Dictionary |
+ | Exception |
+ | Enum |
+ | Typedef |
+ | ImplementsStatement |
+ | Label |
+ | Inline""" |
+ p[0] = p[1] |
+ |
+ def p_Inline(self, p): |
+ """Inline : INLINE""" |
+ words = p[1].split() |
+ name = self.BuildAttribute('NAME', words[1]) |
+ lines = p[1].split('\n') |
+ value = self.BuildAttribute('VALUE', '\n'.join(lines[1:-1]) + '\n') |
+ children = ListFromConcat(name, value) |
+ p[0] = self.BuildProduction('Inline', p, 1, children) |
+ |
+# |
+# Label |
+# |
+# A label is a special kind of enumeration which allows us to go from a |
+# set of version numbrs to releases |
+# |
+ def p_Label(self, p): |
+ """Label : LABEL identifier '{' LabelList '}' ';'""" |
+ p[0] = self.BuildNamed('Label', p, 2, p[4]) |
+ |
+ def p_LabelList(self, p): |
+ """LabelList : identifier '=' float LabelCont""" |
+ val = self.BuildAttribute('VALUE', p[3]) |
+ label = self.BuildNamed('LabelItem', p, 1, val) |
+ p[0] = ListFromConcat(label, p[4]) |
+ |
+ def p_LabelCont(self, p): |
+ """LabelCont : ',' LabelList |
+ |""" |
+ if len(p) > 1: p[0] = p[2] |
+ |
+ def p_LabelContError(self, p): |
+ """LabelCont : error LabelCont""" |
+ p[0] = p[2] |
+ |
+ # [27] |
+ def p_ConstValue(self, p): |
+ """ConstValue : integer |
+ | integer LSHIFT integer |
+ | integer RSHIFT integer""" |
+ val = str(p[1]) |
+ if len(p) > 2: |
+ val = "%s %s %s" % (p[1], p[2], p[3]) |
+ |
+ p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'integer'), |
+ self.BuildAttribute('NAME', val)) |
+ |
+ def p_ConstValueStr(self, p): |
+ """ConstValue : string""" |
+ p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'string'), |
+ self.BuildAttribute('NAME', p[1])) |
+ |
+ def p_ConstValueLiteral(self, p): |
+ """ConstValue : FloatLiteral |
+ | BooleanLiteral """ |
+ p[0] = p[1] |
+ |
+ |
+ # [21] |
+ def p_EnumValueList(self, p): |
+ """EnumValueList : EnumValue EnumValues""" |
+ p[0] = ListFromConcat(p[1], p[2]) |
+ |
+ # [22] |
+ def p_EnumValues(self, p): |
+ """EnumValues : ',' EnumValue EnumValues |
+ |""" |
+ if len(p) > 1: |
+ p[0] = ListFromConcat(p[2], p[3]) |
+ |
+ def p_EnumValue(self, p): |
+ """EnumValue : ExtendedAttributeList identifier |
+ | ExtendedAttributeList identifier '=' ConstValue""" |
+ p[0] = self.BuildNamed('EnumItem', p, 2, p[1]) |
+ if len(p) > 3: |
+ p[0].AddChildren(self.BuildAttribute('VALUE', p[4])) |
+ |
+ def p_PrimitiveType(self, p): |
+ """PrimitiveType : IntegerType |
+ | UnsignedIntegerType |
+ | FloatType |
+ | HandleType |
+ | PointerType""" |
+ if type(p[1]) == str: |
+ p[0] = self.BuildNamed('PrimitiveType', p, 1) |
+ else: |
+ p[0] = p[1] |
+ |
+ def p_PointerType(self, p): |
+ """PointerType : STR_T |
+ | MEM_T |
+ | CSTR_T |
+ | INTERFACE_T |
+ | NULL""" |
+ p[0] = p[1] |
+ |
+ def p_HandleType(self, p): |
+ """HandleType : HANDLE_T |
+ | PP_FILEHANDLE""" |
+ p[0] = p[1] |
+ |
+ # [66] |
+ def p_FloatType(self, p): |
+ """FloatType : FLOAT_T |
+ | DOUBLE_T""" |
+ p[0] = p[1] |
+ |
+ # [67] |
+ def p_UnsignedIntegerType(self, p): |
+ """UnsignedIntegerType : UINT8_T |
+ | UINT16_T |
+ | UINT32_T |
+ | UINT64_T""" |
+ p[0] = p[1] |
+ |
+ |
+ # [68] |
+ def p_IntegerType(self, p): |
+ """IntegerType : CHAR |
+ | INT8_T |
+ | INT16_T |
+ | INT32_T |
+ | INT64_T""" |
+ p[0] = p[1] |
+ |
+ # These targets are no longer used |
+ def p_OptionalLong(self, p): |
+ """ """ |
+ pass |
+ |
+ def p_UnrestrictedFloatType(self, p): |
+ """ """ |
+ pass |
+ |
+ def p_null(self, p): |
+ """ """ |
+ pass |
+ |
+ def __init__(self, lexer, verbose=False, debug=False, mute_error=False): |
+ IDLParser.__init__(self, lexer, verbose, debug, mute_error) |
+ |
+ |
+def main(argv): |
+ nodes = [] |
+ parser = IDLPPAPIParser(IDLPPAPILexer()) |
+ errors = 0 |
+ |
+ for filename in argv: |
+ filenode = ParseFile(parser, filename) |
+ if filenode: |
+ errors += filenode.GetProperty('ERRORS') |
+ nodes.append(filenode) |
+ |
+ ast = IDLNode('AST', '__AST__', 0, 0, nodes) |
+ |
+ print '\n'.join(ast.Tree(accept_props=['PROD','VALUE'])) |
+ if errors: |
+ print '\nFound %d errors.\n' % errors |
+ |
+ |
+ return errors |
+ |
+ |
+if __name__ == '__main__': |
+ sys.exit(main(sys.argv[1:])) |