1 # Copyright 2014 The Chromium Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 """Translates parse tree to Mojom IR.""" 6 7 8 import ast 9 10 11 def _MapTree(func, tree, name): 12 if not tree: 13 return [] 14 return [func(subtree) for subtree in tree if subtree[0] == name] 15 16 def _MapKind(kind): 17 map_to_kind = { 'bool': 'b', 18 'int8': 'i8', 19 'int16': 'i16', 20 'int32': 'i32', 21 'int64': 'i64', 22 'uint8': 'u8', 23 'uint16': 'u16', 24 'uint32': 'u32', 25 'uint64': 'u64', 26 'float': 'f', 27 'double': 'd', 28 'string': 's', 29 'handle': 'h', 30 'handle<data_pipe_consumer>': 'h:d:c', 31 'handle<data_pipe_producer>': 'h:d:p', 32 'handle<message_pipe>': 'h:m', 33 'handle<shared_buffer>': 'h:s'} 34 if kind.endswith('[]'): 35 return 'a:' + _MapKind(kind[0:len(kind)-2]) 36 if kind.endswith('&'): 37 return 'r:' + _MapKind(kind[0:len(kind)-1]) 38 if kind in map_to_kind: 39 return map_to_kind[kind] 40 return 'x:' + kind 41 42 def _MapAttributes(attributes): 43 if not attributes: 44 return {} 45 return dict([(attribute[1], attribute[2]) 46 for attribute in attributes if attribute[0] == 'ATTRIBUTE']) 47 48 def _GetAttribute(attributes, name): 49 out = None 50 if attributes: 51 for attribute in attributes: 52 if attribute[0] == 'ATTRIBUTE' and attribute[1] == name: 53 out = attribute[2] 54 return out 55 56 def _MapField(tree): 57 assert type(tree[3]) is ast.Ordinal 58 return {'name': tree[2], 59 'kind': _MapKind(tree[1]), 60 'ordinal': tree[3].value, 61 'default': tree[4]} 62 63 def _MapParameter(tree): 64 assert type(tree[3]) is ast.Ordinal 65 return {'name': tree[2], 66 'kind': _MapKind(tree[1]), 67 'ordinal': tree[3].value} 68 69 def _MapMethod(tree): 70 assert type(tree[3]) is ast.Ordinal 71 method = {'name': tree[1], 72 'parameters': _MapTree(_MapParameter, tree[2], 'PARAM'), 73 'ordinal': tree[3].value} 74 if tree[4] != None: 75 method['response_parameters'] = _MapTree(_MapParameter, tree[4], 'PARAM') 76 return method 77 78 def _MapEnumField(tree): 79 return {'name': tree[1], 80 'value': tree[2]} 81 82 def _MapStruct(tree): 83 struct = {} 84 struct['name'] = tree[1] 85 struct['attributes'] = _MapAttributes(tree[2]) 86 struct['fields'] = _MapTree(_MapField, tree[3], 'FIELD') 87 struct['enums'] = _MapTree(_MapEnum, tree[3], 'ENUM') 88 struct['constants'] = _MapTree(_MapConstant, tree[3], 'CONST') 89 return struct 90 91 def _MapInterface(tree): 92 interface = {} 93 interface['name'] = tree[1] 94 interface['client'] = _GetAttribute(tree[2], 'Client') 95 interface['methods'] = _MapTree(_MapMethod, tree[3], 'METHOD') 96 interface['enums'] = _MapTree(_MapEnum, tree[3], 'ENUM') 97 interface['constants'] = _MapTree(_MapConstant, tree[3], 'CONST') 98 return interface 99 100 def _MapEnum(tree): 101 enum = {} 102 enum['name'] = tree[1] 103 enum['fields'] = _MapTree(_MapEnumField, tree[2], 'ENUM_FIELD') 104 return enum 105 106 def _MapConstant(tree): 107 constant = {} 108 constant['name'] = tree[2] 109 constant['kind'] = _MapKind(tree[1]) 110 constant['value'] = tree[3] 111 return constant 112 113 def _MapModule(tree, name): 114 mojom = {} 115 mojom['name'] = name 116 mojom['namespace'] = tree[1] 117 mojom['attributes'] = _MapAttributes(tree[2]) 118 mojom['structs'] = _MapTree(_MapStruct, tree[3], 'STRUCT') 119 mojom['interfaces'] = _MapTree(_MapInterface, tree[3], 'INTERFACE') 120 mojom['enums'] = _MapTree(_MapEnum, tree[3], 'ENUM') 121 mojom['constants'] = _MapTree(_MapConstant, tree[3], 'CONST') 122 return mojom 123 124 def _MapImport(tree): 125 import_item = {} 126 import_item['filename'] = tree[1] 127 return import_item 128 129 130 class _MojomBuilder(object): 131 def __init__(self): 132 self.mojom = {} 133 134 def Build(self, tree, name): 135 modules = [_MapModule(item, name) for item in tree if item[0] == 'MODULE'] 136 if len(modules) != 1: 137 raise Exception('A mojom file must contain exactly 1 module.') 138 self.mojom = modules[0] 139 self.mojom['imports'] = _MapTree(_MapImport, tree, 'IMPORT') 140 return self.mojom 141 142 143 def Translate(tree, name): 144 return _MojomBuilder().Build(tree, name) 145