Mojo: Mojom: Add AST type for struct fields.

Also rearrange parameter order of Parameter.__init__ to match other
definitions (name comes first; I figure the ordinal should be second
also).

R=davemoore@chromium.org

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283424 0039d316-1c4b-4281-b951-d872f2087c98
parent 679d8845
...@@ -142,7 +142,7 @@ class EnumValue(Definition): ...@@ -142,7 +142,7 @@ class EnumValue(Definition):
def __init__(self, name, value, **kwargs): def __init__(self, name, value, **kwargs):
# The optional value is either an int (which is current a string) or a # The optional value is either an int (which is current a string) or a
# "wrapped identifier". # "wrapped identifier".
assert value is None or isinstance(value, str) or isinstance(value, tuple) assert value is None or isinstance(value, (str, tuple))
super(EnumValue, self).__init__(name, **kwargs) super(EnumValue, self).__init__(name, **kwargs)
self.value = value self.value = value
...@@ -233,21 +233,45 @@ class Ordinal(NodeBase): ...@@ -233,21 +233,45 @@ class Ordinal(NodeBase):
class Parameter(NodeBase): class Parameter(NodeBase):
"""Represents a method request or response parameter.""" """Represents a method request or response parameter."""
def __init__(self, typename, name, ordinal, **kwargs): def __init__(self, name, ordinal, typename, **kwargs):
assert isinstance(name, str)
assert ordinal is None or isinstance(ordinal, Ordinal) assert ordinal is None or isinstance(ordinal, Ordinal)
assert isinstance(typename, str)
super(Parameter, self).__init__(**kwargs) super(Parameter, self).__init__(**kwargs)
self.typename = typename
self.name = name self.name = name
self.ordinal = ordinal self.ordinal = ordinal
self.typename = typename
def __eq__(self, other): def __eq__(self, other):
return super(Parameter, self).__eq__(other) and \ return super(Parameter, self).__eq__(other) and \
self.typename == other.typename and \
self.name == other.name and \ self.name == other.name and \
self.ordinal == other.ordinal self.ordinal == other.ordinal and \
self.typename == other.typename
class ParameterList(NodeListBase): class ParameterList(NodeListBase):
"""Represents a list of (method request or response) parameters.""" """Represents a list of (method request or response) parameters."""
_list_item_type = Parameter _list_item_type = Parameter
class StructField(Definition):
"""Represents a struct field definition."""
def __init__(self, name, ordinal, typename, default_value, **kwargs):
assert isinstance(name, str)
assert ordinal is None or isinstance(ordinal, Ordinal)
assert isinstance(typename, str)
# The optional default value is currently either a value as a string or a
# "wrapped identifier".
assert default_value is None or isinstance(default_value, (str, tuple))
super(StructField, self).__init__(name, **kwargs)
self.ordinal = ordinal
self.typename = typename
self.default_value = default_value
def __eq__(self, other):
return super(StructField, self).__eq__(other) and \
self.ordinal == other.ordinal and \
self.typename == other.typename and \
self.default_value == other.default_value
...@@ -181,13 +181,15 @@ class Parser(object): ...@@ -181,13 +181,15 @@ class Parser(object):
def p_field(self, p): def p_field(self, p):
"""field : typename NAME ordinal default SEMI""" """field : typename NAME ordinal default SEMI"""
p[0] = ('FIELD', p[1], p[2], p[3], p[4]) p[0] = ast.StructField(p[2], p[3], p[1], p[4])
def p_default(self, p): def p_default_1(self, p):
"""default : EQUALS constant """default : """
| """ p[0] = None
if len(p) > 2:
p[0] = p[2] def p_default_2(self, p):
"""default : EQUALS constant"""
p[0] = p[2]
def p_interface(self, p): def p_interface(self, p):
"""interface : attribute_section INTERFACE NAME LBRACE interface_body \ """interface : attribute_section INTERFACE NAME LBRACE interface_body \
...@@ -231,7 +233,7 @@ class Parser(object): ...@@ -231,7 +233,7 @@ class Parser(object):
def p_parameter(self, p): def p_parameter(self, p):
"""parameter : typename NAME ordinal""" """parameter : typename NAME ordinal"""
p[0] = ast.Parameter(p[1], p[2], p[3], p[0] = ast.Parameter(p[2], p[3], p[1],
filename=self.filename, lineno=p.lineno(2)) filename=self.filename, lineno=p.lineno(2))
def p_typename(self, p): def p_typename(self, p):
......
...@@ -67,13 +67,6 @@ def _AttributeListToDict(attribute_list): ...@@ -67,13 +67,6 @@ def _AttributeListToDict(attribute_list):
return dict([(attribute.key, attribute.value) return dict([(attribute.key, attribute.value)
for attribute in attribute_list]) for attribute in attribute_list])
def _MapField(tree):
assert tree[3] is None or isinstance(tree[3], ast.Ordinal)
return {'name': tree[2],
'kind': _MapKind(tree[1]),
'ordinal': tree[3].value if tree[3] else None,
'default': tree[4]}
def _MapMethod(tree): def _MapMethod(tree):
assert isinstance(tree[2], ast.ParameterList) assert isinstance(tree[2], ast.ParameterList)
assert tree[3] is None or isinstance(tree[3], ast.Ordinal) assert tree[3] is None or isinstance(tree[3], ast.Ordinal)
...@@ -93,10 +86,19 @@ def _MapMethod(tree): ...@@ -93,10 +86,19 @@ def _MapMethod(tree):
return method return method
def _MapStruct(tree): 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 = {}
struct['name'] = tree[1] struct['name'] = tree[1]
struct['attributes'] = _AttributeListToDict(tree[2]) struct['attributes'] = _AttributeListToDict(tree[2])
struct['fields'] = _MapTreeForName(_MapField, tree[3], 'FIELD') struct['fields'] = _MapTreeForType(StructFieldToDict, tree[3],
ast.StructField)
struct['enums'] = _MapTreeForType(_MapEnum, tree[3], ast.Enum) struct['enums'] = _MapTreeForType(_MapEnum, tree[3], ast.Enum)
struct['constants'] = _MapTreeForType(_MapConstant, tree[3], ast.Const) struct['constants'] = _MapTreeForType(_MapConstant, tree[3], ast.Const)
return struct return struct
......
...@@ -151,8 +151,8 @@ class ParserTest(unittest.TestCase): ...@@ -151,8 +151,8 @@ class ParserTest(unittest.TestCase):
[('STRUCT', [('STRUCT',
'MyStruct', 'MyStruct',
None, None,
[('FIELD', 'int32', 'a', None, None), [ast.StructField('a', None, 'int32', None),
('FIELD', 'double', 'b', None, None)])]) ast.StructField('b', None, 'double', None)])])
self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
def testSimpleStructWithoutModule(self): def testSimpleStructWithoutModule(self):
...@@ -170,8 +170,8 @@ class ParserTest(unittest.TestCase): ...@@ -170,8 +170,8 @@ class ParserTest(unittest.TestCase):
[('STRUCT', [('STRUCT',
'MyStruct', 'MyStruct',
None, None,
[('FIELD', 'int32', 'a', None, None), [ast.StructField('a', None, 'int32', None),
('FIELD', 'double', 'b', None, None)])]) ast.StructField('b', None, 'double', None)])])
self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
def testMissingModuleName(self): def testMissingModuleName(self):
...@@ -289,8 +289,8 @@ class ParserTest(unittest.TestCase): ...@@ -289,8 +289,8 @@ class ParserTest(unittest.TestCase):
[('STRUCT', [('STRUCT',
'MyStruct', None, 'MyStruct', None,
[ast.Const('kNumber', 'int8', '-1'), [ast.Const('kNumber', 'int8', '-1'),
('FIELD', 'int8', 'number', ast.StructField('number', ast.Ordinal(0), 'int8',
ast.Ordinal(0), ('IDENTIFIER', 'kNumber'))])]) ('IDENTIFIER', 'kNumber'))])])
self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
def testNoConditionals(self): def testNoConditionals(self):
...@@ -337,14 +337,15 @@ class ParserTest(unittest.TestCase): ...@@ -337,14 +337,15 @@ class ParserTest(unittest.TestCase):
[('STRUCT', [('STRUCT',
'MyStruct', 'MyStruct',
None, None,
[('FIELD', 'int32', 'a0', ast.Ordinal(0), None), [ast.StructField('a0', ast.Ordinal(0), 'int32', None),
('FIELD', 'int32', 'a1', ast.Ordinal(1), None), ast.StructField('a1', ast.Ordinal(1), 'int32', None),
('FIELD', 'int32', 'a2', ast.Ordinal(2), None), ast.StructField('a2', ast.Ordinal(2), 'int32', None),
('FIELD', 'int32', 'a9', ast.Ordinal(9), None), ast.StructField('a9', ast.Ordinal(9), 'int32', None),
('FIELD', 'int32', 'a10', ast.Ordinal(10), None), ast.StructField('a10', ast.Ordinal(10), 'int32', None),
('FIELD', 'int32', 'a11', ast.Ordinal(11), None), ast.StructField('a11', ast.Ordinal(11), 'int32', None),
('FIELD', 'int32', 'a29', ast.Ordinal(29), None), ast.StructField('a29', ast.Ordinal(29), 'int32', None),
('FIELD', 'int32', 'a1234567890', ast.Ordinal(1234567890), None)])]) ast.StructField('a1234567890', ast.Ordinal(1234567890), 'int32',
None)])])
self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
def testInvalidOrdinals(self): def testInvalidOrdinals(self):
...@@ -432,7 +433,7 @@ class ParserTest(unittest.TestCase): ...@@ -432,7 +433,7 @@ class ParserTest(unittest.TestCase):
[('STRUCT', [('STRUCT',
'MyStruct', 'MyStruct',
None, None,
[('FIELD', 'int32', 'a', None, None)])]) [ast.StructField('a', None, 'int32', None)])])
self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
def testValidHandleTypes(self): def testValidHandleTypes(self):
...@@ -455,11 +456,11 @@ class ParserTest(unittest.TestCase): ...@@ -455,11 +456,11 @@ class ParserTest(unittest.TestCase):
[('STRUCT', [('STRUCT',
'MyStruct', 'MyStruct',
None, None,
[('FIELD', 'handle', 'a', None, None), [ast.StructField('a', None, 'handle', None),
('FIELD', 'handle<data_pipe_consumer>', 'b', None, None), ast.StructField('b', None, 'handle<data_pipe_consumer>', None),
('FIELD', 'handle<data_pipe_producer>', 'c', None, None), ast.StructField('c', None, 'handle<data_pipe_producer>', None),
('FIELD', 'handle<message_pipe>', 'd', None, None), ast.StructField('d', None, 'handle<message_pipe>', None),
('FIELD', 'handle<shared_buffer>', 'e', None, None)])]) ast.StructField('e', None, 'handle<shared_buffer>', None)])])
self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
def testInvalidHandleType(self): def testInvalidHandleType(self):
...@@ -513,29 +514,29 @@ class ParserTest(unittest.TestCase): ...@@ -513,29 +514,29 @@ class ParserTest(unittest.TestCase):
[('STRUCT', [('STRUCT',
'MyStruct', 'MyStruct',
None, None,
[('FIELD', 'int16', 'a0', None, '0'), [ast.StructField('a0', None, 'int16', '0'),
('FIELD', 'uint16', 'a1', None, '0x0'), ast.StructField('a1', None, 'uint16', '0x0'),
('FIELD', 'uint16', 'a2', None, '0x00'), ast.StructField('a2', None, 'uint16', '0x00'),
('FIELD', 'uint16', 'a3', None, '0x01'), ast.StructField('a3', None, 'uint16', '0x01'),
('FIELD', 'uint16', 'a4', None, '0xcd'), ast.StructField('a4', None, 'uint16', '0xcd'),
('FIELD', 'int32', 'a5' , None, '12345'), ast.StructField('a5' , None, 'int32', '12345'),
('FIELD', 'int64', 'a6', None, '-12345'), ast.StructField('a6', None, 'int64', '-12345'),
('FIELD', 'int64', 'a7', None, '+12345'), ast.StructField('a7', None, 'int64', '+12345'),
('FIELD', 'uint32', 'a8', None, '0x12cd3'), ast.StructField('a8', None, 'uint32', '0x12cd3'),
('FIELD', 'uint32', 'a9', None, '-0x12cD3'), ast.StructField('a9', None, 'uint32', '-0x12cD3'),
('FIELD', 'uint32', 'a10', None, '+0x12CD3'), ast.StructField('a10', None, 'uint32', '+0x12CD3'),
('FIELD', 'bool', 'a11', None, 'true'), ast.StructField('a11', None, 'bool', 'true'),
('FIELD', 'bool', 'a12', None, 'false'), ast.StructField('a12', None, 'bool', 'false'),
('FIELD', 'float', 'a13', None, '1.2345'), ast.StructField('a13', None, 'float', '1.2345'),
('FIELD', 'float', 'a14', None, '-1.2345'), ast.StructField('a14', None, 'float', '-1.2345'),
('FIELD', 'float', 'a15', None, '+1.2345'), ast.StructField('a15', None, 'float', '+1.2345'),
('FIELD', 'float', 'a16', None, '123.'), ast.StructField('a16', None, 'float', '123.'),
('FIELD', 'float', 'a17', None, '.123'), ast.StructField('a17', None, 'float', '.123'),
('FIELD', 'double', 'a18', None, '1.23E10'), ast.StructField('a18', None, 'double', '1.23E10'),
('FIELD', 'double', 'a19', None, '1.E-10'), ast.StructField('a19', None, 'double', '1.E-10'),
('FIELD', 'double', 'a20', None, '.5E+10'), ast.StructField('a20', None, 'double', '.5E+10'),
('FIELD', 'double', 'a21', None, '-1.23E10'), ast.StructField('a21', None, 'double', '-1.23E10'),
('FIELD', 'double', 'a22', None, '+.123E10')])]) ast.StructField('a22', None, 'double', '+.123E10')])])
self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
def testValidFixedSizeArray(self): def testValidFixedSizeArray(self):
...@@ -554,10 +555,11 @@ class ParserTest(unittest.TestCase): ...@@ -554,10 +555,11 @@ class ParserTest(unittest.TestCase):
[('STRUCT', [('STRUCT',
'MyStruct', 'MyStruct',
None, None,
[('FIELD', 'int32[]', 'normal_array', None, None), [ast.StructField('normal_array', None, 'int32[]', None),
('FIELD', 'int32[1]', 'fixed_size_array_one_entry', None, None), ast.StructField('fixed_size_array_one_entry', None, 'int32[1]',
('FIELD', 'int32[10]', 'fixed_size_array_ten_entries', None, None),
None)])]) ast.StructField('fixed_size_array_ten_entries', None, 'int32[10]',
None)])])
self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
def testValidNestedArray(self): def testValidNestedArray(self):
...@@ -570,7 +572,7 @@ class ParserTest(unittest.TestCase): ...@@ -570,7 +572,7 @@ class ParserTest(unittest.TestCase):
[('STRUCT', [('STRUCT',
'MyStruct', 'MyStruct',
None, None,
[('FIELD', 'int32[][]', 'nested_array', None, None)])]) [ast.StructField('nested_array', None, 'int32[][]', None)])])
self.assertEquals(parser.Parse(source, "my_file.mojom"), expected) self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
def testInvalidFixedArraySize(self): def testInvalidFixedArraySize(self):
...@@ -621,7 +623,7 @@ class ParserTest(unittest.TestCase): ...@@ -621,7 +623,7 @@ class ParserTest(unittest.TestCase):
None, None,
[('METHOD', [('METHOD',
'MyMethod', 'MyMethod',
ast.ParameterList(ast.Parameter('int32', 'a', None)), ast.ParameterList(ast.Parameter('a', None, 'int32')),
None, None,
None)])]) None)])])
self.assertEquals(parser.Parse(source1, "my_file.mojom"), expected1) self.assertEquals(parser.Parse(source1, "my_file.mojom"), expected1)
...@@ -640,8 +642,8 @@ class ParserTest(unittest.TestCase): ...@@ -640,8 +642,8 @@ class ParserTest(unittest.TestCase):
None, None,
[('METHOD', [('METHOD',
'MyMethod1', 'MyMethod1',
ast.ParameterList([ast.Parameter('int32', 'a', ast.Ordinal(0)), ast.ParameterList([ast.Parameter('a', ast.Ordinal(0), 'int32'),
ast.Parameter('int64', 'b', ast.Ordinal(1))]), ast.Parameter('b', ast.Ordinal(1), 'int64')]),
ast.Ordinal(0), ast.Ordinal(0),
None), None),
('METHOD', ('METHOD',
...@@ -664,10 +666,10 @@ class ParserTest(unittest.TestCase): ...@@ -664,10 +666,10 @@ class ParserTest(unittest.TestCase):
None, None,
[('METHOD', [('METHOD',
'MyMethod', 'MyMethod',
ast.ParameterList(ast.Parameter('string', 'a', None)), ast.ParameterList(ast.Parameter('a', None, 'string')),
None, None,
ast.ParameterList([ast.Parameter('int32', 'a', None), ast.ParameterList([ast.Parameter('a', None, 'int32'),
ast.Parameter('bool', 'b', None)]))])]) ast.Parameter('b', None, 'bool')]))])])
self.assertEquals(parser.Parse(source3, "my_file.mojom"), expected3) self.assertEquals(parser.Parse(source3, "my_file.mojom"), expected3)
def testInvalidMethods(self): def testInvalidMethods(self):
......
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