OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 """ Parser for PPAPI IDL """ |
| 7 |
| 8 # |
| 9 # IDL Parser |
| 10 # |
| 11 # The parser is uses the PLY yacc library to build a set of parsing rules based |
| 12 # on WebIDL. |
| 13 # |
| 14 # WebIDL, and WebIDL grammar can be found at: |
| 15 # http://dev.w3.org/2006/webapi/WebIDL/ |
| 16 # PLY can be found at: |
| 17 # http://www.dabeaz.com/ply/ |
| 18 # |
| 19 # The parser generates a tree by recursively matching sets of items against |
| 20 # defined patterns. When a match is made, that set of items is reduced |
| 21 # to a new item. The new item can provide a match for parent patterns. |
| 22 # In this way an AST is built (reduced) depth first. |
| 23 # |
| 24 |
| 25 # |
| 26 # Disable check for line length and Member as Function due to how grammar rules |
| 27 # are defined with PLY |
| 28 # |
| 29 # pylint: disable=R0201 |
| 30 # pylint: disable=C0301 |
| 31 |
| 32 import os.path |
| 33 import sys |
| 34 import time |
| 35 |
| 36 from idl_ppapi_lexer import IDLPPAPILexer |
| 37 from idl_parser import IDLParser, ListFromConcat, ParseFile |
| 38 from idl_node import IDLAttribute, IDLNode |
| 39 |
| 40 class IDLPPAPIParser(IDLParser): |
| 41 # |
| 42 # We force all input files to start with two comments. The first comment is a |
| 43 # Copyright notice followed by a file comment and finally by file level |
| 44 # productions. |
| 45 # |
| 46 # [0] Insert a TOP definition for Copyright and Comments |
| 47 def p_Top(self, p): |
| 48 """Top : COMMENT COMMENT Definitions""" |
| 49 Copyright = self.BuildComment('Copyright', p, 1) |
| 50 Filedoc = self.BuildComment('Comment', p, 2) |
| 51 p[0] = ListFromConcat(Copyright, Filedoc, p[3]) |
| 52 |
| 53 # |
| 54 #The parser is based on the WebIDL standard. See: |
| 55 # http://www.w3.org/TR/WebIDL/#idl-grammar |
| 56 # |
| 57 # [1] |
| 58 def p_Definitions(self, p): |
| 59 """Definitions : ExtendedAttributeList Definition Definitions |
| 60 | """ |
| 61 if len(p) > 1: |
| 62 p[2].AddChildren(p[1]) |
| 63 p[0] = ListFromConcat(p[2], p[3]) |
| 64 |
| 65 # [2] Add INLINE definition |
| 66 def p_Definition(self, p): |
| 67 """Definition : CallbackOrInterface |
| 68 | Partial |
| 69 | Dictionary |
| 70 | Exception |
| 71 | Enum |
| 72 | Typedef |
| 73 | ImplementsStatement |
| 74 | Label |
| 75 | Inline""" |
| 76 p[0] = p[1] |
| 77 |
| 78 def p_Inline(self, p): |
| 79 """Inline : INLINE""" |
| 80 words = p[1].split() |
| 81 name = self.BuildAttribute('NAME', words[1]) |
| 82 lines = p[1].split('\n') |
| 83 value = self.BuildAttribute('VALUE', '\n'.join(lines[1:-1]) + '\n') |
| 84 children = ListFromConcat(name, value) |
| 85 p[0] = self.BuildProduction('Inline', p, 1, children) |
| 86 |
| 87 # |
| 88 # Label |
| 89 # |
| 90 # A label is a special kind of enumeration which allows us to go from a |
| 91 # set of version numbrs to releases |
| 92 # |
| 93 def p_Label(self, p): |
| 94 """Label : LABEL identifier '{' LabelList '}' ';'""" |
| 95 p[0] = self.BuildNamed('Label', p, 2, p[4]) |
| 96 |
| 97 def p_LabelList(self, p): |
| 98 """LabelList : identifier '=' float LabelCont""" |
| 99 val = self.BuildAttribute('VALUE', p[3]) |
| 100 label = self.BuildNamed('LabelItem', p, 1, val) |
| 101 p[0] = ListFromConcat(label, p[4]) |
| 102 |
| 103 def p_LabelCont(self, p): |
| 104 """LabelCont : ',' LabelList |
| 105 |""" |
| 106 if len(p) > 1: p[0] = p[2] |
| 107 |
| 108 def p_LabelContError(self, p): |
| 109 """LabelCont : error LabelCont""" |
| 110 p[0] = p[2] |
| 111 |
| 112 # [27] |
| 113 def p_ConstValue(self, p): |
| 114 """ConstValue : integer |
| 115 | integer LSHIFT integer |
| 116 | integer RSHIFT integer""" |
| 117 val = str(p[1]) |
| 118 if len(p) > 2: |
| 119 val = "%s %s %s" % (p[1], p[2], p[3]) |
| 120 |
| 121 p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'integer'), |
| 122 self.BuildAttribute('NAME', val)) |
| 123 |
| 124 def p_ConstValueStr(self, p): |
| 125 """ConstValue : string""" |
| 126 p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'string'), |
| 127 self.BuildAttribute('NAME', p[1])) |
| 128 |
| 129 def p_ConstValueLiteral(self, p): |
| 130 """ConstValue : FloatLiteral |
| 131 | BooleanLiteral """ |
| 132 p[0] = p[1] |
| 133 |
| 134 |
| 135 # [21] |
| 136 def p_EnumValueList(self, p): |
| 137 """EnumValueList : EnumValue EnumValues""" |
| 138 p[0] = ListFromConcat(p[1], p[2]) |
| 139 |
| 140 # [22] |
| 141 def p_EnumValues(self, p): |
| 142 """EnumValues : ',' EnumValue EnumValues |
| 143 |""" |
| 144 if len(p) > 1: |
| 145 p[0] = ListFromConcat(p[2], p[3]) |
| 146 |
| 147 def p_EnumValue(self, p): |
| 148 """EnumValue : ExtendedAttributeList identifier |
| 149 | ExtendedAttributeList identifier '=' ConstValue""" |
| 150 p[0] = self.BuildNamed('EnumItem', p, 2, p[1]) |
| 151 if len(p) > 3: |
| 152 p[0].AddChildren(self.BuildAttribute('VALUE', p[4])) |
| 153 |
| 154 def p_PrimitiveType(self, p): |
| 155 """PrimitiveType : IntegerType |
| 156 | UnsignedIntegerType |
| 157 | FloatType |
| 158 | HandleType |
| 159 | PointerType""" |
| 160 if type(p[1]) == str: |
| 161 p[0] = self.BuildNamed('PrimitiveType', p, 1) |
| 162 else: |
| 163 p[0] = p[1] |
| 164 |
| 165 def p_PointerType(self, p): |
| 166 """PointerType : STR_T |
| 167 | MEM_T |
| 168 | CSTR_T |
| 169 | INTERFACE_T |
| 170 | NULL""" |
| 171 p[0] = p[1] |
| 172 |
| 173 def p_HandleType(self, p): |
| 174 """HandleType : HANDLE_T |
| 175 | PP_FILEHANDLE""" |
| 176 p[0] = p[1] |
| 177 |
| 178 # [66] |
| 179 def p_FloatType(self, p): |
| 180 """FloatType : FLOAT_T |
| 181 | DOUBLE_T""" |
| 182 p[0] = p[1] |
| 183 |
| 184 # [67] |
| 185 def p_UnsignedIntegerType(self, p): |
| 186 """UnsignedIntegerType : UINT8_T |
| 187 | UINT16_T |
| 188 | UINT32_T |
| 189 | UINT64_T""" |
| 190 p[0] = p[1] |
| 191 |
| 192 |
| 193 # [68] |
| 194 def p_IntegerType(self, p): |
| 195 """IntegerType : CHAR |
| 196 | INT8_T |
| 197 | INT16_T |
| 198 | INT32_T |
| 199 | INT64_T""" |
| 200 p[0] = p[1] |
| 201 |
| 202 # These targets are no longer used |
| 203 def p_OptionalLong(self, p): |
| 204 """ """ |
| 205 pass |
| 206 |
| 207 def p_UnrestrictedFloatType(self, p): |
| 208 """ """ |
| 209 pass |
| 210 |
| 211 def p_null(self, p): |
| 212 """ """ |
| 213 pass |
| 214 |
| 215 def __init__(self, lexer, verbose=False, debug=False, mute_error=False): |
| 216 IDLParser.__init__(self, lexer, verbose, debug, mute_error) |
| 217 |
| 218 |
| 219 def main(argv): |
| 220 nodes = [] |
| 221 parser = IDLPPAPIParser(IDLPPAPILexer()) |
| 222 errors = 0 |
| 223 |
| 224 for filename in argv: |
| 225 filenode = ParseFile(parser, filename) |
| 226 if filenode: |
| 227 errors += filenode.GetProperty('ERRORS') |
| 228 nodes.append(filenode) |
| 229 |
| 230 ast = IDLNode('AST', '__AST__', 0, 0, nodes) |
| 231 |
| 232 print '\n'.join(ast.Tree(accept_props=['PROD','VALUE'])) |
| 233 if errors: |
| 234 print '\nFound %d errors.\n' % errors |
| 235 |
| 236 |
| 237 return errors |
| 238 |
| 239 |
| 240 if __name__ == '__main__': |
| 241 sys.exit(main(sys.argv[1:])) |
OLD | NEW |