Skip to content

Commit 0068fca

Browse files
committed
parser - AST for const, var decl. better AST printing
AST is not printed to a syntax_tree.txt file in the same directory.
1 parent c171fa4 commit 0068fca

File tree

8 files changed

+155
-28
lines changed

8 files changed

+155
-28
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
env/
22
*__pycache__*
3+
ply/__pycache__*
34
tmp*
45
parser.out
56
.vim/
7+
syntax_tree.txt

go_parser.py

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,10 @@ def p_Signature(p):
205205
"""Signature : Parameters
206206
| Parameters Result
207207
"""
208+
if len(p) == 2:
209+
p[0] = syntree.Signature(p[1])
210+
else:
211+
p[0] = syntree.Signature(p[1], p[2])
208212

209213

210214
def p_Parameters(p):
@@ -298,20 +302,19 @@ def p_IncDecStmt(p):
298302

299303

300304
def p_Assignment(p):
301-
'''Assignment : ExpressionList assign_op ExpressionList
302-
'''
305+
"""Assignment : ExpressionList assign_op ExpressionList"""
303306
p[0] = syntree.Assignment(p[2], p[1], p[3])
304307

305308

306309
def p_assign_op(p):
307-
'''assign_op : '='
308-
| ADD_EQ
309-
| SUB_EQ
310-
| MUL_EQ
311-
| DIV_EQ
312-
| MOD_EQ
313-
'''
314-
# # TODO : Add |= ^= <<= >>= &= &^=
310+
"""assign_op : '='
311+
| ADD_EQ
312+
| SUB_EQ
313+
| MUL_EQ
314+
| DIV_EQ
315+
| MOD_EQ
316+
"""
317+
# # TODO : Add |= ^= <<= >>= &= &^=
315318
p[0] = p[1]
316319

317320

@@ -324,12 +327,17 @@ def p_Declaration(p):
324327
| ConstDecl
325328
| TypeDecl
326329
"""
330+
p[0] = p[1]
327331

328332

329333
def p_VarDecl(p):
330334
"""VarDecl : KW_VAR VarSpec
331335
| KW_VAR '(' VarSpecList ')'
332336
"""
337+
if len(p) == 3:
338+
p[0] = syntree.List([p[2]])
339+
elif len(p) == 5:
340+
p[0] = p[3]
333341

334342

335343
def p_VarSpecList(p):
@@ -349,12 +357,22 @@ def p_VarSpec(p):
349357
| IdentifierList Type '=' ExpressionList
350358
| IdentifierList '=' ExpressionList
351359
"""
360+
if len(p) == 3:
361+
p[0] = syntree.VariableDecl(p[1], p[2])
362+
elif len(p) == 4:
363+
p[0] = syntree.VariableDecl(p[1], expression_list=p[3])
364+
elif len(p) == 5:
365+
p[0] = syntree.VariableDecl(p[1], p[2], p[4])
352366

353367

354368
def p_ConstDecl(p):
355369
"""ConstDecl : KW_CONST ConstSpec
356370
| KW_CONST '(' ConstSpecList ')'
357371
"""
372+
if len(p) == 3:
373+
p[0] = syntree.List([p[2]])
374+
elif len(p) == 5:
375+
p[0] = p[3]
358376

359377

360378
def p_ConstSpecList(p):
@@ -374,6 +392,12 @@ def p_ConstSpec(p):
374392
| IdentifierList '=' ExpressionList
375393
| IdentifierList Type '=' ExpressionList
376394
"""
395+
if len(p) == 2:
396+
p[0] = syntree.VariableDecl(p[1], const=True)
397+
elif len(p) == 4:
398+
p[0] = syntree.VariableDecl(p[1], expression_list=p[3], const=True)
399+
elif len(p) == 5:
400+
p[0] = syntree.VariableDecl(p[1], p[2], p[4], const=True)
377401

378402

379403
def p_TypeDecl(p):
@@ -412,12 +436,22 @@ def p_IdentifierList(p):
412436
"""IdentifierList : IDENTIFIER
413437
| IDENTIFIER ',' IdentifierList %prec WALRUS
414438
"""
439+
if len(p) == 2:
440+
p[0] = syntree.List([syntree.Identifier(p[1])])
441+
elif len(p) == 4:
442+
p[3].append(syntree.Identifier(p[1]))
443+
p[0] = p[3]
415444

416445

417446
def p_ExpressionList(p):
418447
"""ExpressionList : Expression
419448
| Expression ',' ExpressionList
420449
"""
450+
if len(p) == 4:
451+
p[3].append(p[1])
452+
p[0] = p[3]
453+
elif len(p) == 2:
454+
p[0] = syntree.List([p[1]])
421455

422456

423457
def p_Expression(p):
@@ -450,8 +484,9 @@ def p_UnaryExpr(p):
450484
if len(p) == 3:
451485
p[0] = syntree.UnaryOp(p[1], p[2])
452486
else:
453-
# TODO : handle PrimaryExpr
454-
pass
487+
# TODO : handle more stuff in PrimaryExpr
488+
# also change the PrimaryExpr class in syntree when doing so
489+
p[0] = syntree.UnaryOp(None, p[1])
455490

456491

457492
def p_UnaryOp(p):
@@ -465,7 +500,7 @@ def p_UnaryOp(p):
465500
def p_PrimaryExpr(p):
466501
"""PrimaryExpr : Operand"""
467502
# TODO : This is too less! Many more to add
468-
p[0] = p[1]
503+
p[0] = syntree.PrimaryExpr(p[1])
469504

470505

471506
def p_Operand(p):
@@ -488,7 +523,7 @@ def p_OperandName(p):
488523

489524
def p_QualifiedIdent(p):
490525
"""QualifiedIdent : PackageName '.' IDENTIFIER"""
491-
# TODO : AST for this
526+
p[0] = syntree.QualifiedIdent(p[1], p[3])
492527

493528

494529
def p_Literal(p):
@@ -930,7 +965,10 @@ def p_error(p: lex.LexToken):
930965
go_lexer.lines = lines
931966
result = parser.parse(input_code, tracking=True)
932967
# print(result)
933-
print_tree(ast, nameattr=None)
968+
with open("syntax_tree.txt", "wt") as ast_file:
969+
sys.stdout = ast_file
970+
print_tree(ast, nameattr=None, horizontal=False)
971+
sys.stdout = sys.__stdout__
934972
print("Finished Parsing!")
935973
print("Symbol Table: ")
936974
print(symtab)
-191 Bytes
Binary file not shown.

ply/__pycache__/lex.cpython-39.pyc

-16.8 KB
Binary file not shown.

pptree_mod.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ def balanced_branches(current_node):
1717
size_branch = {child: nb_children(child) for child in children(current_node)}
1818

1919
""" Creation of balanced lists for "a" branch and "b" branch. """
20-
a = sorted(children(current_node), key=lambda node: nb_children(node))
20+
a = children(current_node)
2121
b = []
2222
while a and sum(size_branch[node] for node in b) < sum(size_branch[node] for node in a):
23-
b.append(a.pop())
23+
b.insert(0, a.pop())
2424

2525
return a, b
2626

syntree.py

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ def __init__(self, name, **kwargs):
77
self.data = kwargs.get("data", None)
88

99
def __repr__(self):
10-
return f"<Node: {self.name}; {self.data}; {self.children}>"
10+
return str(self)
1111

1212
def __str__(self):
13-
return f"<Node: {self.name}; {self.data}; {len(self.children)} child(s)>"
13+
if self.data is not None:
14+
return f"<{self.name}: {str(self.data)}>"
15+
else:
16+
return f"<{self.name}>"
1417

1518
def add_child(self, child):
1619
if child is not None:
@@ -41,6 +44,8 @@ class UnaryOp(Node):
4144
"""Node for unary operations"""
4245

4346
def __init__(self, operator, operand):
47+
if isinstance(operand, UnaryOp) and operand.operator is None:
48+
operand = operand.operand
4449
super().__init__(f"Unary {operator}", children=[operand], data=operator)
4550

4651
@property
@@ -52,6 +57,16 @@ def operand(self):
5257
return self.children[0]
5358

5459

60+
class PrimaryExpr(Node):
61+
"""Node for PrimaryExpr
62+
63+
Ref: https://golang.org/ref/spec#PrimaryExpr
64+
"""
65+
66+
def __init__(self, operand):
67+
super().__init__("PrimaryExpr", children=[], data=operand)
68+
69+
5570
class Literal(Node):
5671
"""Node to store literals"""
5772

@@ -75,13 +90,31 @@ def __init__(self, children):
7590
super().__init__("LIST", children=children)
7691
self.append = self.add_child
7792

93+
def __iter__(self):
94+
return iter(self.children)
95+
96+
97+
class Signature(Node):
98+
"""Node to store function signature"""
99+
100+
def __init__(self, parameters, result=None):
101+
super().__init__("signature", children=[parameters, result])
102+
103+
@property
104+
def parameters(self):
105+
return self.children[0]
106+
107+
@property
108+
def result(self):
109+
return self.children[1]
110+
78111

79112
class Function(Node):
80113
"""Node to store function declaration"""
81114

82115
def __init__(self, name, signature, body=None):
83116
super().__init__("FUNCTION", children=[signature, body], data=name)
84-
self.name = name
117+
self.fn_name = name
85118

86119
@property
87120
def signature(self):
@@ -96,7 +129,7 @@ def body(self):
96129

97130

98131
class Type(Node):
99-
"Parent class for all types"""
132+
"""Parent class for all types"""
100133

101134

102135
class Array(Type):
@@ -110,6 +143,48 @@ def __init__(self, eltype, length):
110143
def length(self):
111144
return self.children[0]
112145

146+
147+
class Identifier(Node):
148+
"""Node for identifiers"""
149+
150+
def __init__(self, ident_tuple):
151+
super().__init__("IDENTIFIER", children=[], data=ident_tuple[1])
152+
153+
154+
class QualifiedIdent(Node):
155+
"""Node for qualified identifiers"""
156+
157+
def __init__(self, package_name, identifier):
158+
super().__init__("IDENTIFIER", children=[], data=(package_name, identifier))
159+
160+
161+
class VariableDecl(Node):
162+
"""Node to store variable and constant declarations"""
163+
164+
def __init__(self, identifier_list, type_=None, expression_list=None, const=False):
165+
super().__init__(
166+
"DECL",
167+
children=[identifier_list, expression_list],
168+
data=(type_, const),
169+
)
170+
171+
@property
172+
def expression_list(self):
173+
return self.children[1]
174+
175+
@property
176+
def identifier_list(self):
177+
return self.children[0]
178+
179+
@property
180+
def type_(self):
181+
return self.data[0]
182+
183+
@property
184+
def is_const(self):
185+
return self.data[1]
186+
187+
113188
# class OldNode:
114189
# """Class to store a node of the AST"""
115190

@@ -166,5 +241,3 @@ def length(self):
166241
# self.children.append(Node(type(child), node=child))
167242
# else:
168243
# self.children.append(child)
169-
170-

tests/const_declarations.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,9 @@ const (
66
size int = 1024
77
eof = -1 // untyped integer constant
88
)
9-
const a, b, c = 3, 4, "foo
10-
askdhas
11-
alksdhsal
12-
asdasdsa" // a = 3, b = 4, c = "foo", untyped integer and string constants
9+
const a, b, c = 3, 4, "foo" // a = 3, b = 4, c = "foo", untyped integer and string constants
1310
const u, v float64 = 0, 3 // u = 0.0, v = 3.0
1411
const zero = 0
15-
asldas */
1612
const some = 5 * 3
1713
const somemore = 5.0 - 5
1814
const added = Pi + size

tests/const_declarations_errors.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package main
2+
3+
const Pi float64 = 3.14159265358979323846
4+
const zero = 0.0
5+
const (
6+
size int = 1024
7+
eof = -1 // untyped integer constant
8+
)
9+
const a, b, c = 3, 4, "foo
10+
askdhas
11+
alksdhsal
12+
asdasdsa" // a = 3, b = 4, c = "foo", untyped integer and string constants
13+
const u, v float64 = 0, 3 // u = 0.0, v = 3.0
14+
const zero = 0
15+
asldas */
16+
const some = 5 * 3
17+
const somemore = 5.0 - 5
18+
const added = Pi + size

0 commit comments

Comments
 (0)