Skip to content

Commit b7d3d89

Browse files
author
hartsantler
committed
test shows that Brython's tokenizer can be used to parse python code and transform it back into a PythonJS compatible AST.
1 parent 0353cfb commit b7d3d89

1 file changed

Lines changed: 97 additions & 30 deletions

File tree

tests/brython_AST.html

Lines changed: 97 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,31 @@
1616

1717
<script type="text/python">
1818

19-
class Name:
19+
def tokenize(src):
20+
module = 'test'
21+
return JS('$tokenize(src, module)') ## Brython tokenizer
22+
23+
24+
class Assign:
25+
def __init__(self, ctx):
26+
self.targets = []
27+
self.targets.append( to_ast_node(ctx.tree[0]) ) ## should be: expr.name==id
28+
self.value = to_ast_node( ctx.tree[1] ) ## should be an: expr.name==operand
29+
30+
class Num:
2031
def __init__(self, ctx):
21-
print 'Name:', ctx.name
22-
self.id = ctx.name
32+
self.n = ctx.value
33+
34+
class Name:
35+
def __init__(self, ctx=None, name=None):
36+
if name:
37+
self.id = name
38+
elif ctx.type == 'id':
39+
self.id = ctx.value
40+
else:
41+
raise TypeError
42+
43+
print 'Name:', self.id
2344

2445
class _arguments:
2546
def __init__(self, ctx):
@@ -32,59 +53,105 @@
3253
if ctx.type != 'func_args':
3354
raise TypeError
3455
for c in ctx.tree:
35-
if c.type != 'func_arg_id':
56+
if c.type == 'func_arg_id':
57+
self.args.append( Name(name=c.name) )
58+
elif c.type == 'func_star_arg' and c.op=='*':
59+
self.vararg = c.name
60+
elif c.type == 'func_star_arg' and c.op=='**':
61+
self.kwarg = c.name
62+
else:
3663
raise TypeError
37-
self.args.append( Name(c) )
3864

3965

4066

41-
class FunctionDef:
67+
class BinOp:
4268
def __init__(self, ctx):
69+
self.left = to_ast_node( ctx.tree[0] )
70+
self.right = to_ast_node( ctx.tree[1] )
71+
self.op = ctx.op ## should be: +,-,*, etc...
72+
73+
class Return:
74+
def __init__(self, ctx):
75+
self.value = to_ast_node( ctx.tree[0] )
76+
77+
class FunctionDef:
78+
def __init__(self, ctx, node):
4379
self.name = ctx.name
4480
self.args = _arguments( ctx.tree[0] )
4581
self.body = []
4682
self.decorator_list = []
4783
self.returns = None ## python3 returns annotation
84+
for child in node.children:
85+
anode = to_ast_node( child.get_ctx() )
86+
self.body.append( anode )
87+
88+
89+
class Call:
90+
def __init__(self, ctx, node):
91+
self.func = None
92+
self.args = []
93+
self.keywords = []
94+
self.starargs = None
95+
self.kwargs = None
96+
97+
for c in ctx.tree:
98+
if c.type == 'call_arg':
99+
self.args.append( to_ast_node(c.tree[0]) )
48100

49-
def tokenize(src):
50-
module = 'test'
51-
return JS('$tokenize(src, module)')
52101

53-
def walk_tree( ctx ):
54-
anode = None
55-
print 'ctx.type:', ctx.type
102+
def to_ast_node( ctx, node=None ):
103+
print 'to-ast-node', ctx
56104
if ctx.type == 'def':
57-
print ' def ', ctx.name
58-
anode = FunctionDef( ctx )
105+
return FunctionDef( ctx, node )
106+
elif ctx.type == 'assign':
107+
return Assign(ctx)
108+
elif ctx.type == 'return':
109+
return Return(ctx)
110+
elif ctx.type == 'node':
111+
return to_ast_node( ctx.tree[0], node=node )
112+
elif ctx.type == 'expr' and ctx.name == 'id':
113+
if ctx.tree[0].type == 'call':
114+
return Call( ctx.tree[0], node)
115+
else:
116+
return Name( ctx.tree[0] )
117+
elif ctx.type == 'expr' and ctx.name == 'operand':
118+
return BinOp( ctx.tree[0] )
119+
120+
elif ctx.type == 'expr' and ctx.name == 'int':
121+
return Num( ctx.tree[0] )
59122

60-
if anode:
61-
return anode
62123
else:
63-
for c in ctx.tree:
64-
walk_tree( c )
124+
print ctx
125+
raise TypeError
126+
65127

66-
def convert_to_ast( node ):
128+
def walk_nodes( node, module ):
67129
print 'node.type:', node.type
68-
ctx = node.get_ctx()
69-
if ctx:
70-
walk_tree( ctx )
71130

72-
for child in node.children:
73-
convert_to_ast( child )
131+
if node.type == 'expression':
132+
anode = to_ast_node( node.get_ctx(), node=node )
133+
module.append( anode )
74134

75-
source = """
76-
def xxx(a,b):
77-
return a+b
135+
else:
136+
for child in node.children:
137+
walk_nodes( child, module )
78138

79-
print( xxx(1, 2) )
80139

140+
source = """
141+
def func(a,b):
142+
c = a+b
143+
return c
144+
145+
func(100, 200)
81146
"""
82147

83148
def test():
84-
global a
149+
global a, module
85150
a = tokenize( source )
86151
print a
87-
convert_to_ast( a )
152+
module = list()
153+
walk_nodes( a, module )
154+
88155

89156
</script>
90157

0 commit comments

Comments
 (0)