• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
8import ast
9
10
11def _MapTree(func, tree, name):
12  if not tree:
13    return []
14  return [func(subtree) for subtree in tree if subtree[0] == name]
15
16def _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
42def _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
48def _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
56def _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
63def _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
69def _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
78def _MapEnumField(tree):
79  return {'name': tree[1],
80          'value': tree[2]}
81
82def _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
91def _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
100def _MapEnum(tree):
101  enum = {}
102  enum['name'] = tree[1]
103  enum['fields'] = _MapTree(_MapEnumField, tree[2], 'ENUM_FIELD')
104  return enum
105
106def _MapConstant(tree):
107  constant = {}
108  constant['name'] = tree[2]
109  constant['kind'] = _MapKind(tree[1])
110  constant['value'] = tree[3]
111  return constant
112
113def _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
124def _MapImport(tree):
125  import_item = {}
126  import_item['filename'] = tree[1]
127  return import_item
128
129
130class _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
143def Translate(tree, name):
144  return _MojomBuilder().Build(tree, name)
145