Mojo: Mojom: Add AST types for struct and struct body.

R=davemoore@chromium.org

Review URL: https://codereview.chromium.org/398553002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283436 0039d316-1c4b-4281-b951-d872f2087c98
parent cb082570
...@@ -24,49 +24,57 @@ class NodeBase(object): ...@@ -24,49 +24,57 @@ class NodeBase(object):
# TODO(vtl): Some of this is complicated enough that it should be tested. # TODO(vtl): Some of this is complicated enough that it should be tested.
class NodeListBase(NodeBase): class NodeListBase(NodeBase):
"""Represents a list of other nodes, all having the same type. (This is meant """Represents a list of other nodes, all having the same type. (This is meant
to be subclassed, with subclasses defining _list_item_type to be the class of to be subclassed, with subclasses defining _list_item_type to be the class (or
the members of the list; _list_item_type should also be a NodeBase.)""" classes, in a tuple) of the members of the list.)"""
def __init__(self, item_or_items=None, **kwargs): def __init__(self, item_or_items=None, **kwargs):
assert issubclass(self._list_item_type, NodeBase)
super(NodeListBase, self).__init__(**kwargs) super(NodeListBase, self).__init__(**kwargs)
self.items = []
if item_or_items is None: if item_or_items is None:
self.elements = [] pass
self.items = []
elif isinstance(item_or_items, list): elif isinstance(item_or_items, list):
# TODO(vtl): Possibly we should assert that each element of the list is a for item in item_or_items:
# |_list_item_type|. assert isinstance(item, self._list_item_type)
self.elements = list(item_or_items) self.Append(item)
else: else:
assert isinstance(item_or_items, self._list_item_type) assert isinstance(item_or_items, self._list_item_type)
self.elements = [item_or_items] self.Append(item_or_items)
self._UpdateFilenameAndLineno()
# Support iteration. For everything else, users should just access |elements| # Support iteration. For everything else, users should just access |items|
# directly. (We intentionally do NOT supply |__len__()| or |__nonzero__()|, so # directly. (We intentionally do NOT supply |__len__()| or |__nonzero__()|, so
# |bool(NodeListBase())| is true.) # |bool(NodeListBase())| is true.)
def __iter__(self): def __iter__(self):
return self.elements.__iter__() return self.items.__iter__()
def __eq__(self, other): def __eq__(self, other):
return super(NodeListBase, self).__eq__(other) and \ return super(NodeListBase, self).__eq__(other) and \
len(self.elements) == len(other.elements) and \ len(self.items) == len(other.items) and \
all(self.elements[i] == other.elements[i] \ all(self.items[i] == other.items[i] for i in xrange(len(self.items)))
for i in xrange(len(self.elements)))
# Implement this so that on failure, we get slightly more sensible output. # Implement this so that on failure, we get slightly more sensible output.
def __repr__(self): def __repr__(self):
return self.__class__.__name__ + "([" + \ return self.__class__.__name__ + "([" + \
", ".join([repr(elem) for elem in self.elements]) + "])" ", ".join([repr(elem) for elem in self.items]) + "])"
def Insert(self, item):
"""Inserts item at the front of the list."""
assert isinstance(item, self._list_item_type)
self.items.insert(0, item)
self._UpdateFilenameAndLineno()
def Append(self, item): def Append(self, item):
"""Appends item to the end of the list."""
assert isinstance(item, self._list_item_type) assert isinstance(item, self._list_item_type)
self.elements.append(item) self.items.append(item)
self._UpdateFilenameAndLineno() self._UpdateFilenameAndLineno()
def _UpdateFilenameAndLineno(self): def _UpdateFilenameAndLineno(self):
if self.elements: if self.items:
self.filename = self.elements[0].filename self.filename = self.items[0].filename
self.lineno = self.elements[0].lineno self.lineno = self.items[0].lineno
class Definition(NodeBase): class Definition(NodeBase):
...@@ -255,6 +263,22 @@ class ParameterList(NodeListBase): ...@@ -255,6 +263,22 @@ class ParameterList(NodeListBase):
_list_item_type = Parameter _list_item_type = Parameter
class Struct(Definition):
"""Represents a struct definition."""
def __init__(self, name, attribute_list, body, **kwargs):
assert attribute_list is None or isinstance(attribute_list, AttributeList)
assert isinstance(body, StructBody)
super(Struct, self).__init__(name, **kwargs)
self.attribute_list = attribute_list
self.body = body
def __eq__(self, other):
return super(Struct, self).__eq__(other) and \
self.attribute_list == other.attribute_list and \
self.body == other.body
class StructField(Definition): class StructField(Definition):
"""Represents a struct field definition.""" """Represents a struct field definition."""
...@@ -275,3 +299,10 @@ class StructField(Definition): ...@@ -275,3 +299,10 @@ class StructField(Definition):
self.ordinal == other.ordinal and \ self.ordinal == other.ordinal and \
self.typename == other.typename and \ self.typename == other.typename and \
self.default_value == other.default_value self.default_value == other.default_value
# This needs to be declared after |StructField|.
class StructBody(NodeListBase):
"""Represents the body of (i.e., list of definitions inside) a struct."""
_list_item_type = (Const, Enum, StructField)
...@@ -169,18 +169,21 @@ class Parser(object): ...@@ -169,18 +169,21 @@ class Parser(object):
def p_struct(self, p): def p_struct(self, p):
"""struct : attribute_section STRUCT NAME LBRACE struct_body RBRACE SEMI""" """struct : attribute_section STRUCT NAME LBRACE struct_body RBRACE SEMI"""
p[0] = ('STRUCT', p[3], p[1], p[5]) p[0] = ast.Struct(p[3], p[1], p[5])
def p_struct_body(self, p): def p_struct_body_1(self, p):
"""struct_body : field struct_body """struct_body : """
| enum struct_body p[0] = ast.StructBody()
| const struct_body
| """ def p_struct_body_2(self, p):
if len(p) > 1: """struct_body : struct_body const
p[0] = _ListFromConcat(p[1], p[2]) | struct_body enum
| struct_body struct_field"""
p[0] = p[1]
p[0].Append(p[2])
def p_field(self, p): def p_struct_field(self, p):
"""field : typename NAME ordinal default SEMI""" """struct_field : typename NAME ordinal default SEMI"""
p[0] = ast.StructField(p[2], p[3], p[1], p[4]) p[0] = ast.StructField(p[2], p[3], p[1], p[4])
def p_default_1(self, p): def p_default_1(self, p):
......
...@@ -85,24 +85,6 @@ def _MapMethod(tree): ...@@ -85,24 +85,6 @@ def _MapMethod(tree):
method['response_parameters'] = map(ParameterToDict, tree[4]) method['response_parameters'] = map(ParameterToDict, tree[4])
return method return method
def _MapStruct(tree):
def StructFieldToDict(struct_field):
assert isinstance(struct_field, ast.StructField)
return {'name': struct_field.name,
'kind': _MapKind(struct_field.typename),
'ordinal': struct_field.ordinal.value \
if struct_field.ordinal else None,
'default': struct_field.default_value}
struct = {}
struct['name'] = tree[1]
struct['attributes'] = _AttributeListToDict(tree[2])
struct['fields'] = _MapTreeForType(StructFieldToDict, tree[3],
ast.StructField)
struct['enums'] = _MapTreeForType(_MapEnum, tree[3], ast.Enum)
struct['constants'] = _MapTreeForType(_MapConstant, tree[3], ast.Const)
return struct
def _MapInterface(tree): def _MapInterface(tree):
interface = {} interface = {}
interface['name'] = tree[1] interface['name'] = tree[1]
...@@ -135,6 +117,24 @@ class _MojomBuilder(object): ...@@ -135,6 +117,24 @@ class _MojomBuilder(object):
self.mojom = {} self.mojom = {}
def Build(self, tree, name): def Build(self, tree, name):
def StructToDict(struct):
def StructFieldToDict(struct_field):
assert isinstance(struct_field, ast.StructField)
return {'name': struct_field.name,
'kind': _MapKind(struct_field.typename),
'ordinal': struct_field.ordinal.value \
if struct_field.ordinal else None,
'default': struct_field.default_value}
assert isinstance(struct, ast.Struct)
return {'name': struct.name,
'attributes': _AttributeListToDict(struct.attribute_list),
'fields': _MapTreeForType(StructFieldToDict, struct.body,
ast.StructField),
'enums': _MapTreeForType(_MapEnum, struct.body, ast.Enum),
'constants': _MapTreeForType(_MapConstant, struct.body,
ast.Const)}
assert isinstance(tree, ast.Mojom) assert isinstance(tree, ast.Mojom)
self.mojom['name'] = name self.mojom['name'] = name
self.mojom['namespace'] = tree.module.name[1] if tree.module else '' self.mojom['namespace'] = tree.module.name[1] if tree.module else ''
...@@ -143,7 +143,7 @@ class _MojomBuilder(object): ...@@ -143,7 +143,7 @@ class _MojomBuilder(object):
self.mojom['attributes'] = \ self.mojom['attributes'] = \
_AttributeListToDict(tree.module.attribute_list) if tree.module else {} _AttributeListToDict(tree.module.attribute_list) if tree.module else {}
self.mojom['structs'] = \ self.mojom['structs'] = \
_MapTreeForName(_MapStruct, tree.definition_list, 'STRUCT') _MapTreeForType(StructToDict, tree.definition_list, ast.Struct)
self.mojom['interfaces'] = \ self.mojom['interfaces'] = \
_MapTreeForName(_MapInterface, tree.definition_list, 'INTERFACE') _MapTreeForName(_MapInterface, tree.definition_list, 'INTERFACE')
self.mojom['enums'] = \ self.mojom['enums'] = \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment