Skip to content

Commit

Permalink
Mojo: Mojom: Add AST types for struct and struct body.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
viettrungluu@chromium.org committed Jul 16, 2014
1 parent cb08257 commit e9931bb
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 138 deletions.
69 changes: 50 additions & 19 deletions mojo/public/tools/bindings/pylib/mojom/parse/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,49 +24,57 @@ def __eq__(self, other):
# TODO(vtl): Some of this is complicated enough that it should be tested.
class NodeListBase(NodeBase):
"""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
the members of the list; _list_item_type should also be a NodeBase.)"""
to be subclassed, with subclasses defining _list_item_type to be the class (or
classes, in a tuple) of the members of the list.)"""

def __init__(self, item_or_items=None, **kwargs):
assert issubclass(self._list_item_type, NodeBase)
super(NodeListBase, self).__init__(**kwargs)
self.items = []
if item_or_items is None:
self.elements = []
pass
self.items = []
elif isinstance(item_or_items, list):
# TODO(vtl): Possibly we should assert that each element of the list is a
# |_list_item_type|.
self.elements = list(item_or_items)
for item in item_or_items:
assert isinstance(item, self._list_item_type)
self.Append(item)
else:
assert isinstance(item_or_items, self._list_item_type)
self.elements = [item_or_items]
self._UpdateFilenameAndLineno()
self.Append(item_or_items)

# 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
# |bool(NodeListBase())| is true.)
def __iter__(self):
return self.elements.__iter__()
return self.items.__iter__()

def __eq__(self, other):
return super(NodeListBase, self).__eq__(other) and \
len(self.elements) == len(other.elements) and \
all(self.elements[i] == other.elements[i] \
for i in xrange(len(self.elements)))
len(self.items) == len(other.items) and \
all(self.items[i] == other.items[i] for i in xrange(len(self.items)))

# Implement this so that on failure, we get slightly more sensible output.
def __repr__(self):
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):
"""Appends item to the end of the list."""

assert isinstance(item, self._list_item_type)
self.elements.append(item)
self.items.append(item)
self._UpdateFilenameAndLineno()

def _UpdateFilenameAndLineno(self):
if self.elements:
self.filename = self.elements[0].filename
self.lineno = self.elements[0].lineno
if self.items:
self.filename = self.items[0].filename
self.lineno = self.items[0].lineno


class Definition(NodeBase):
Expand Down Expand Up @@ -255,6 +263,22 @@ class ParameterList(NodeListBase):
_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):
"""Represents a struct field definition."""

Expand All @@ -275,3 +299,10 @@ def __eq__(self, other):
self.ordinal == other.ordinal and \
self.typename == other.typename and \
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)
23 changes: 13 additions & 10 deletions mojo/public/tools/bindings/pylib/mojom/parse/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,18 +169,21 @@ def p_evaled_literal(self, p):

def p_struct(self, p):
"""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):
"""struct_body : field struct_body
| enum struct_body
| const struct_body
| """
if len(p) > 1:
p[0] = _ListFromConcat(p[1], p[2])
def p_struct_body_1(self, p):
"""struct_body : """
p[0] = ast.StructBody()

def p_struct_body_2(self, p):
"""struct_body : struct_body const
| struct_body enum
| struct_body struct_field"""
p[0] = p[1]
p[0].Append(p[2])

def p_field(self, p):
"""field : typename NAME ordinal default SEMI"""
def p_struct_field(self, p):
"""struct_field : typename NAME ordinal default SEMI"""
p[0] = ast.StructField(p[2], p[3], p[1], p[4])

def p_default_1(self, p):
Expand Down
38 changes: 19 additions & 19 deletions mojo/public/tools/bindings/pylib/mojom/parse/translate.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,24 +85,6 @@ def ParameterToDict(param):
method['response_parameters'] = map(ParameterToDict, tree[4])
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):
interface = {}
interface['name'] = tree[1]
Expand Down Expand Up @@ -135,6 +117,24 @@ def __init__(self):
self.mojom = {}

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)
self.mojom['name'] = name
self.mojom['namespace'] = tree.module.name[1] if tree.module else ''
Expand All @@ -143,7 +143,7 @@ def Build(self, tree, name):
self.mojom['attributes'] = \
_AttributeListToDict(tree.module.attribute_list) if tree.module else {}
self.mojom['structs'] = \
_MapTreeForName(_MapStruct, tree.definition_list, 'STRUCT')
_MapTreeForType(StructToDict, tree.definition_list, ast.Struct)
self.mojom['interfaces'] = \
_MapTreeForName(_MapInterface, tree.definition_list, 'INTERFACE')
self.mojom['enums'] = \
Expand Down
Loading

0 comments on commit e9931bb

Please sign in to comment.