使用recursive
,我可以生成简单的 AST,例如
from hypothesis import *
from hypothesis.strategies import *
def trees():
base = integers(min_value=1, max_value=10).map(lambda n: 'x' + str(n))
@composite
def extend(draw, children):
op = draw(sampled_from(['+', '-', '*', '/']))
return (op, draw(children), draw(children))
return recursive(base, draw)
现在我想改变它,这样我就可以生成除算术运算之外的布尔运算。我最初的想法是添加一个参数trees
:
def trees(tpe):
base = integers(min_value=1, max_value=10).map(lambda n: 'x' + str(n) + ': ' + tpe)
@composite
def extend(draw, children):
if tpe == 'bool':
op = draw(sampled_from(['&&', '||']))
return (op, draw(children), draw(children))
elif tpe == 'num':
op = draw(sampled_from(['+', '-', '*', '/']))
return (op, draw(children), draw(children))
return recursive(base, draw)
到目前为止还好。但是我该如何混合它们呢?也就是说,我还想要比较运算符和三元运算符,也就是说,这需要“children
使用不同的参数调用”。
树需要很好的类型:如果操作是'||'
or '&&'
,两个参数都需要是布尔值,参数'+'
或'<'
需要是数字等。如果我只有两种类型,我可以使用filter
(给定一个type_of
函数):
if op in ('&&', '||'):
bool_trees = children.filter(lambda x: type_of(x) == 'bool')
return (op, draw(bool_trees), draw(bool_trees))
但在实际情况下,这是不能接受的。
recursive
支持这个吗?还是有其他方法?显然,我可以直接trees
递归定义,但这会遇到标准问题。