| 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://heycam.github.io/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 sys | |
| 33 | |
| 34 from idl_ppapi_lexer import IDLPPAPILexer | |
| 35 from idl_parser import IDLParser, ListFromConcat, ParseFile | |
| 36 from idl_node import IDLNode | |
| 37 | |
| 38 class IDLPPAPIParser(IDLParser): | |
| 39 # | |
| 40 # We force all input files to start with two comments. The first comment is a | |
| 41 # Copyright notice followed by a file comment and finally by file level | |
| 42 # productions. | |
| 43 # | |
| 44 # [0] Insert a TOP definition for Copyright and Comments | |
| 45 def p_Top(self, p): | |
| 46 """Top : COMMENT COMMENT Definitions""" | |
| 47 Copyright = self.BuildComment('Copyright', p, 1) | |
| 48 Filedoc = self.BuildComment('Comment', p, 2) | |
| 49 p[0] = ListFromConcat(Copyright, Filedoc, p[3]) | |
| 50 | |
| 51 # | |
| 52 #The parser is based on the WebIDL standard. See: | |
| 53 # http://heycam.github.io/webidl/#idl-grammar | |
| 54 # | |
| 55 # [1] | |
| 56 def p_Definitions(self, p): | |
| 57 """Definitions : ExtendedAttributeList Definition Definitions | |
| 58 | """ | |
| 59 if len(p) > 1: | |
| 60 p[2].AddChildren(p[1]) | |
| 61 p[0] = ListFromConcat(p[2], p[3]) | |
| 62 | |
| 63 # [2] Add INLINE definition | |
| 64 def p_Definition(self, p): | |
| 65 """Definition : CallbackOrInterface | |
| 66 | Struct | |
| 67 | Partial | |
| 68 | Dictionary | |
| 69 | Exception | |
| 70 | Enum | |
| 71 | Typedef | |
| 72 | ImplementsStatement | |
| 73 | Label | |
| 74 | Inline""" | |
| 75 p[0] = p[1] | |
| 76 | |
| 77 def p_Inline(self, p): | |
| 78 """Inline : INLINE""" | |
| 79 words = p[1].split() | |
| 80 name = self.BuildAttribute('NAME', words[1]) | |
| 81 lines = p[1].split('\n') | |
| 82 value = self.BuildAttribute('VALUE', '\n'.join(lines[1:-1]) + '\n') | |
| 83 children = ListFromConcat(name, value) | |
| 84 p[0] = self.BuildProduction('Inline', p, 1, children) | |
| 85 | |
| 86 # | |
| 87 # Label | |
| 88 # | |
| 89 # A label is a special kind of enumeration which allows us to go from a | |
| 90 # set of version numbrs to releases | |
| 91 # | |
| 92 def p_Label(self, p): | |
| 93 """Label : LABEL identifier '{' LabelList '}' ';'""" | |
| 94 p[0] = self.BuildNamed('Label', p, 2, p[4]) | |
| 95 | |
| 96 def p_LabelList(self, p): | |
| 97 """LabelList : identifier '=' float LabelCont""" | |
| 98 val = self.BuildAttribute('VALUE', p[3]) | |
| 99 label = self.BuildNamed('LabelItem', p, 1, val) | |
| 100 p[0] = ListFromConcat(label, p[4]) | |
| 101 | |
| 102 def p_LabelCont(self, p): | |
| 103 """LabelCont : ',' LabelList | |
| 104 |""" | |
| 105 if len(p) > 1: | |
| 106 p[0] = p[2] | |
| 107 | |
| 108 def p_LabelContError(self, p): | |
| 109 """LabelCont : error LabelCont""" | |
| 110 p[0] = p[2] | |
| 111 | |
| 112 # [5.1] Add "struct" style interface | |
| 113 def p_Struct(self, p): | |
| 114 """Struct : STRUCT identifier Inheritance '{' StructMembers '}' ';'""" | |
| 115 p[0] = self.BuildNamed('Struct', p, 2, ListFromConcat(p[3], p[5])) | |
| 116 | |
| 117 def p_StructMembers(self, p): | |
| 118 """StructMembers : StructMember StructMembers | |
| 119 |""" | |
| 120 if len(p) > 1: | |
| 121 p[0] = ListFromConcat(p[1], p[2]) | |
| 122 | |
| 123 def p_StructMember(self, p): | |
| 124 """StructMember : ExtendedAttributeList Type identifier ';'""" | |
| 125 p[0] = self.BuildNamed('Member', p, 3, ListFromConcat(p[1], p[2])) | |
| 126 | |
| 127 def p_Typedef(self, p): | |
| 128 """Typedef : TYPEDEF ExtendedAttributeListNoComments Type identifier ';'""" | |
| 129 p[0] = self.BuildNamed('Typedef', p, 4, ListFromConcat(p[2], p[3])) | |
| 130 | |
| 131 def p_TypedefFunc(self, p): | |
| 132 """Typedef : TYPEDEF ExtendedAttributeListNoComments ReturnType identifier '
(' ArgumentList ')' ';'""" | |
| 133 args = self.BuildProduction('Arguments', p, 5, p[6]) | |
| 134 p[0] = self.BuildNamed('Callback', p, 4, ListFromConcat(p[2], p[3], args)) | |
| 135 | |
| 136 def p_ConstValue(self, p): | |
| 137 """ConstValue : integer | |
| 138 | integer LSHIFT integer | |
| 139 | integer RSHIFT integer""" | |
| 140 val = str(p[1]) | |
| 141 if len(p) > 2: | |
| 142 val = "%s %s %s" % (p[1], p[2], p[3]) | |
| 143 p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'integer'), | |
| 144 self.BuildAttribute('VALUE', val)) | |
| 145 | |
| 146 def p_ConstValueStr(self, p): | |
| 147 """ConstValue : string""" | |
| 148 p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'string'), | |
| 149 self.BuildAttribute('VALUE', p[1])) | |
| 150 | |
| 151 # Boolean & Float Literals area already BuildAttributes | |
| 152 def p_ConstValueLiteral(self, p): | |
| 153 """ConstValue : FloatLiteral | |
| 154 | BooleanLiteral """ | |
| 155 p[0] = p[1] | |
| 156 | |
| 157 def p_EnumValueList(self, p): | |
| 158 """EnumValueList : EnumValue EnumValues""" | |
| 159 p[0] = ListFromConcat(p[1], p[2]) | |
| 160 | |
| 161 def p_EnumValues(self, p): | |
| 162 """EnumValues : ',' EnumValue EnumValues | |
| 163 |""" | |
| 164 if len(p) > 1: | |
| 165 p[0] = ListFromConcat(p[2], p[3]) | |
| 166 | |
| 167 def p_EnumValue(self, p): | |
| 168 """EnumValue : ExtendedAttributeList identifier | |
| 169 | ExtendedAttributeList identifier '=' ConstValue""" | |
| 170 p[0] = self.BuildNamed('EnumItem', p, 2, p[1]) | |
| 171 if len(p) > 3: | |
| 172 p[0].AddChildren(p[4]) | |
| 173 | |
| 174 # Omit PromiseType, as it is a JS type. | |
| 175 def p_NonAnyType(self, p): | |
| 176 """NonAnyType : PrimitiveType TypeSuffix | |
| 177 | identifier TypeSuffix | |
| 178 | SEQUENCE '<' Type '>' Null""" | |
| 179 IDLParser.p_NonAnyType(self, p) | |
| 180 | |
| 181 def p_PrimitiveType(self, p): | |
| 182 """PrimitiveType : IntegerType | |
| 183 | UnsignedIntegerType | |
| 184 | FloatType | |
| 185 | HandleType | |
| 186 | PointerType""" | |
| 187 if type(p[1]) == str: | |
| 188 p[0] = self.BuildNamed('PrimitiveType', p, 1) | |
| 189 else: | |
| 190 p[0] = p[1] | |
| 191 | |
| 192 def p_PointerType(self, p): | |
| 193 """PointerType : STR_T | |
| 194 | MEM_T | |
| 195 | CSTR_T | |
| 196 | INTERFACE_T | |
| 197 | NULL""" | |
| 198 p[0] = p[1] | |
| 199 | |
| 200 def p_HandleType(self, p): | |
| 201 """HandleType : HANDLE_T | |
| 202 | PP_FILEHANDLE""" | |
| 203 p[0] = p[1] | |
| 204 | |
| 205 def p_FloatType(self, p): | |
| 206 """FloatType : FLOAT_T | |
| 207 | DOUBLE_T""" | |
| 208 p[0] = p[1] | |
| 209 | |
| 210 def p_UnsignedIntegerType(self, p): | |
| 211 """UnsignedIntegerType : UINT8_T | |
| 212 | UINT16_T | |
| 213 | UINT32_T | |
| 214 | UINT64_T""" | |
| 215 p[0] = p[1] | |
| 216 | |
| 217 | |
| 218 def p_IntegerType(self, p): | |
| 219 """IntegerType : CHAR | |
| 220 | INT8_T | |
| 221 | INT16_T | |
| 222 | INT32_T | |
| 223 | INT64_T""" | |
| 224 p[0] = p[1] | |
| 225 | |
| 226 # These targets are no longer used | |
| 227 def p_OptionalLong(self, p): | |
| 228 """ """ | |
| 229 pass | |
| 230 | |
| 231 def p_UnrestrictedFloatType(self, p): | |
| 232 """ """ | |
| 233 pass | |
| 234 | |
| 235 def p_null(self, p): | |
| 236 """ """ | |
| 237 pass | |
| 238 | |
| 239 def p_PromiseType(self, p): | |
| 240 """ """ | |
| 241 pass | |
| 242 | |
| 243 def p_EnumValueListComma(self, p): | |
| 244 """ """ | |
| 245 pass | |
| 246 | |
| 247 def p_EnumValueListString(self, p): | |
| 248 """ """ | |
| 249 pass | |
| 250 | |
| 251 # We only support: | |
| 252 # [ identifier ] | |
| 253 # [ identifier ( ArgumentList )] | |
| 254 # [ identifier ( ValueList )] | |
| 255 # [ identifier = identifier ] | |
| 256 # [ identifier = ( IdentifierList )] | |
| 257 # [ identifier = ConstValue ] | |
| 258 # [ identifier = identifier ( ArgumentList )] | |
| 259 # [51] map directly to 74-77 | |
| 260 # [52-54, 56] are unsupported | |
| 261 def p_ExtendedAttribute(self, p): | |
| 262 """ExtendedAttribute : ExtendedAttributeNoArgs | |
| 263 | ExtendedAttributeArgList | |
| 264 | ExtendedAttributeValList | |
| 265 | ExtendedAttributeIdent | |
| 266 | ExtendedAttributeIdentList | |
| 267 | ExtendedAttributeIdentConst | |
| 268 | ExtendedAttributeNamedArgList""" | |
| 269 p[0] = p[1] | |
| 270 | |
| 271 def p_ExtendedAttributeValList(self, p): | |
| 272 """ExtendedAttributeValList : identifier '(' ValueList ')'""" | |
| 273 arguments = self.BuildProduction('Values', p, 2, p[3]) | |
| 274 p[0] = self.BuildNamed('ExtAttribute', p, 1, arguments) | |
| 275 | |
| 276 def p_ValueList(self, p): | |
| 277 """ValueList : ConstValue ValueListCont""" | |
| 278 p[0] = ListFromConcat(p[1], p[2]) | |
| 279 | |
| 280 def p_ValueListCont(self, p): | |
| 281 """ValueListCont : ValueList | |
| 282 |""" | |
| 283 if len(p) > 1: | |
| 284 p[0] = p[1] | |
| 285 | |
| 286 def p_ExtendedAttributeIdentConst(self, p): | |
| 287 """ExtendedAttributeIdentConst : identifier '=' ConstValue""" | |
| 288 p[0] = self.BuildNamed('ExtAttribute', p, 1, p[3]) | |
| 289 | |
| 290 | |
| 291 def __init__(self, lexer, verbose=False, debug=False, mute_error=False): | |
| 292 IDLParser.__init__(self, lexer, verbose, debug, mute_error) | |
| 293 | |
| 294 | |
| 295 def main(argv): | |
| 296 nodes = [] | |
| 297 parser = IDLPPAPIParser(IDLPPAPILexer()) | |
| 298 errors = 0 | |
| 299 | |
| 300 for filename in argv: | |
| 301 filenode = ParseFile(parser, filename) | |
| 302 if filenode: | |
| 303 errors += filenode.GetProperty('ERRORS') | |
| 304 nodes.append(filenode) | |
| 305 | |
| 306 ast = IDLNode('AST', '__AST__', 0, 0, nodes) | |
| 307 | |
| 308 print '\n'.join(ast.Tree(accept_props=['PROD', 'TYPE', 'VALUE'])) | |
| 309 if errors: | |
| 310 print '\nFound %d errors.\n' % errors | |
| 311 | |
| 312 | |
| 313 return errors | |
| 314 | |
| 315 | |
| 316 if __name__ == '__main__': | |
| 317 sys.exit(main(sys.argv[1:])) | |
| OLD | NEW |