Home | History | Annotate | Download | only in parse
      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