-
Notifications
You must be signed in to change notification settings - Fork 0
/
ppp_parser.py
127 lines (102 loc) · 3.4 KB
/
ppp_parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import pflfp_token as tk
class AstNode:
def __init__(self):
pass
class Basic(AstNode):
def __init__(self):
super().__init__()
def type(self):
return self.type
# --- Base types ---
class Int(Basic):
def __init__(self, value):
self.value = value
super().__init__()
def type(self):
return tk.T.INT
class Float(Basic):
def __init__(self, value):
self.value = value
super().__init__()
def type(self):
return tk.T.FLOAT
class Bool(Basic):
def __init__(self, value):
self.value = value
super().__init__()
def type(self):
return tk.T.BOOL
# --- Expressions/Statments ---
class Assignment(AstNode):
def __init__(self, identifier: str, value: AstNode):
self.identifier = identifier
self.value = value
super().__init__()
class BinOp(AstNode):
# might need to hold left hand and right hand values eventually
def __init__(self, op: str):
self.op = op
super().__init__()
def __str__(self) -> str:
return f'{self.op}'
class Macro(AstNode):
def __init__(self, identifier: str, body: list):
self.identifier = identifier
self.body = body
super().__init__()
def __str__(self) -> str:
print(f'{self.identifier} -> {self.body}')
return super().__str__()
class If(AstNode):
def __init__(self, condition: Bool, consequence: AstNode):
self.condition = condition
self.consequence = consequence
super().__init__()
class Identifier(AstNode):
def __init__(self, name):
self.name = name
super().__init__()
# ---------------------------
def is_type(node: Basic, type: tk.T):
return node.type() == type
def parse(tokens: list[tk.Token], debug: bool = False):
nodes: list[AstNode] = []
idx: int = 0
while True:
t = tokens[idx]
match t.type:
case tk.T.PLUS | tk.T.STAR | tk.T.MINUS | tk.T.SLASH:
# rh = nodes[idx - 2]
# lh = nodes[idx - 1]
# nodes.pop()
# nodes.pop()
nodes.append(BinOp(t.literal))
case tk.T.EOF:
return nodes
case tk.T.BLOCK:
idx += 1 # advance one
initial_pos = idx
while tokens[idx].type != tk.T.BLOCK:
idx += 1
if len(tokens) <= idx:
print("error, macro was not properly defined")
exit(-1)
aux_tok_list = tokens[initial_pos:idx]
aux_tok_list.append(tk.Token(tk.T.EOF, 'eof', len(aux_tok_list)))
sub_tok_list = parse(aux_tok_list)
# advance to get identifier
idx += 1
if not is_type(tokens[idx], tk.T.IDENTASSIGN):
# TODO: Error
print("error parsing macro, should have an identifier after the block, got " + tokens[idx].literal)
exit(-1)
nodes.append(Macro(tokens[idx].literal, sub_tok_list))
case tk.T.INT:
nodes.append(Int(t.literal))
case tk.T.FLOAT:
nodes.append(Float(t.literal))
case tk.T.BOOL:
nodes.append(Bool(t.literal))
idx += 1
if debug:
print(nodes[len(nodes) - 1])