#!/usr/bin/env python # Copyright 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. """Translate parse tree to Mojom IR""" import os import sys def MapKind(kind): map_to_kind = { 'bool': 'b', 'int8': 'i8', 'int16': 'i16', 'int32': 'i32', 'int64': 'i64', 'uint8': 'u8', 'uint16': 'u16', 'uint32': 'u32', 'uint64': 'u64', 'float': 'f', 'double': 'd', 'string': 's', 'handle': 'h', 'handle<message_pipe>': 'h:m' } if kind.endswith('[]'): return 'a:' + MapKind(kind[0:len(kind)-2]) if kind in map_to_kind: return map_to_kind[kind] return 'x:' + kind def MapOrdinal(ordinal): if ordinal == None: return None; return int(ordinal[1:]) # Strip leading '@' def GetAttribute(attributes, name): out = None for attribute in attributes: if attribute[0] == 'ATTRIBUTE' and attribute[1] == name: out = attribute[2] return out def MapFields(fields): out = [] for field in fields: if field[0] == 'FIELD': out.append({'name': field[2], 'kind': MapKind(field[1]), 'ordinal': MapOrdinal(field[3])}) return out def MapParameters(parameters): out = [] for parameter in parameters: if parameter[0] == 'PARAM': out.append({'name': parameter[2], 'kind': MapKind(parameter[1]), 'ordinal': MapOrdinal(parameter[3])}) return out def MapMethods(methods): out = [] for method in methods: if method[0] == 'METHOD': out.append({'name': method[1], 'parameters': MapParameters(method[2]), 'ordinal': MapOrdinal(method[3])}) return out def MapEnumFields(fields): out = [] for field in fields: if field[0] == 'ENUM_FIELD': out.append({'name': field[1], 'value': field[2]}) return out class MojomBuilder(): def __init__(self): self.mojom = {} def AddStruct(self, name, attributes, fields): struct = {} struct['name'] = name # TODO(darin): Add support for |attributes| #struct['attributes'] = MapAttributes(attributes) struct['fields'] = MapFields(fields) self.mojom['structs'].append(struct) def AddInterface(self, name, attributes, methods): interface = {} interface['name'] = name interface['peer'] = GetAttribute(attributes, 'Peer') interface['methods'] = MapMethods(methods) self.mojom['interfaces'].append(interface) def AddEnum(self, name, fields): # TODO(mpcomplete): add support for specifying enums as types. Right now # we just use int32. enum = {} enum['name'] = name enum['fields'] = MapEnumFields(fields) self.mojom['enums'].append(enum) def AddModule(self, name, namespace, contents): self.mojom['name'] = name self.mojom['namespace'] = namespace self.mojom['structs'] = [] self.mojom['interfaces'] = [] self.mojom['enums'] = [] for item in contents: if item[0] == 'STRUCT': self.AddStruct(name=item[1], attributes=item[2], fields=item[3]) elif item[0] == 'INTERFACE': self.AddInterface(name=item[1], attributes=item[2], methods=item[3]) elif item[0] == 'ENUM': self.AddEnum(name=item[1], fields=item[2]) def Build(self, tree, name): if tree[0] == 'MODULE': self.AddModule(name=name, namespace=tree[1], contents=tree[2]) return self.mojom def Translate(tree, name): return MojomBuilder().Build(tree, name) def Main(): if len(sys.argv) < 2: print("usage: %s filename" % (sys.argv[0])) sys.exit(1) tree = eval(open(sys.argv[1]).read()) name = os.path.splitext(os.path.basename(sys.argv[1]))[0] result = Translate(tree, name) print(result) if __name__ == '__main__': Main()