Skip to content

Commit

Permalink
[ASDL] Parse parameterized types.
Browse files Browse the repository at this point in the history
Add unit tests for ASDL schema parsing.
  • Loading branch information
Andy Chu committed May 12, 2020
1 parent c75ff26 commit 3000338
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 16 deletions.
4 changes: 3 additions & 1 deletion asdl/asdl_.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,9 @@ def Print(self, f, indent):
f.write('TypeExpr %s' % (self.name)) # printed after field
if self.children:
f.write(' [ ')
for child in self.children:
for i, child in enumerate(self.children):
if i != 0:
f.write(', ')
child.Print(f, indent+1)
f.write(' ]')

Expand Down
44 changes: 33 additions & 11 deletions asdl/front_end.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,36 @@ def _parse_type_decl(self):

def _parse_type_expr(self):
"""
Name ( '?' | '*' )
We just need these expressions, not arbitrary ones:
one_param: ('array' | 'maybe') '[' type_expr ']'
two_params: 'map' '[' type_expr ',' type_expr ']'
type_expr:
Name ( '?' | '*' )
| one_param
| two_params
"""
type_name = self._advance()
type_name = self._match(TokenKind.Name)
typ = TypeExpr(type_name)

if type_name in ('array', 'maybe'):
self._match(TokenKind.LBracket)
child = self._parse_type_expr()
typ = TypeExpr(type_name, [child])
self._match(TokenKind.RBracket)
return typ

if type_name == 'map':
self._match(TokenKind.LBracket)
k = self._parse_type_expr()
self._match(TokenKind.Comma)
v = self._parse_type_expr()
typ = TypeExpr(type_name, [k, v])
self._match(TokenKind.RBracket)
return typ

if self.cur_token.kind == TokenKind.Asterisk:
# string* is equivalent to array[string]
typ = TypeExpr('array', [typ])
Expand All @@ -208,22 +233,19 @@ def _parse_type_expr(self):

def _parse_fields(self):
"""
'('
Name Quantifier? Name
( ',' Name Quantifier? Name )*
')'
fields:
'('
type_expr Name
( ',' type_expr Name )*
')'
Name Quantifier? should be changed to typename.
"""
fields = []
self._match(TokenKind.LParen)
while self.cur_token.kind == TokenKind.Name:
typ = self._parse_type_expr()

if self.cur_token.kind == TokenKind.Name:
field_name = self._advance()
else:
field_name = None
field_name = self._match(TokenKind.Name)

fields.append(Field(typ, field_name))

Expand Down
39 changes: 35 additions & 4 deletions asdl/front_end_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,48 @@ def testSharedVariantCode(self):
b = expr.Binary(d, d)
b.PrettyPrint()

def _assertParse(self, code_str):
f = cStringIO.StringIO(code_str)
p = front_end.ASDLParser()
schema_ast = p.parse(f)
print(schema_ast)
# For now just test its type
self.assert_(isinstance(schema_ast, asdl_.Module))

def testParse(self):
f = cStringIO.StringIO("""
self._assertParse("""
module foo {
point = (int? x, int* y)
action = Foo | Bar(point z)
-- foo = (map[string, int] options)
foo = (array[int] span_ids)
bar = (map[string, int] options)
}
""")

def _assertParseError(self, code_str):
f = cStringIO.StringIO(code_str)
p = front_end.ASDLParser()
schema_ast = p.parse(f)
print(schema_ast)
try:
schema_ast = p.parse(f)
except front_end.ASDLSyntaxError as e:
print(e)
else:
self.fail("Expected parse failure: %r" % code_str)

def testParseErrors(self):
# Need field name
self._assertParseError('module foo { t = (int) }')

# Need []
self._assertParseError('module foo { t = (array foo) }')

# Shouldn't have []
self._assertParseError('module foo { t = (string[string] a) }')

# Not enough params
self._assertParseError('module foo { t = (map[] a) }')
self._assertParseError('module foo { t = (map[string] a) }')
self._assertParseError('module foo { t = (map[string, ] a) }')

def testAstNodes(self):
# maybe[string]
Expand Down

0 comments on commit 3000338

Please sign in to comment.