-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathparser.py
More file actions
173 lines (147 loc) · 6.85 KB
/
Copy pathparser.py
File metadata and controls
173 lines (147 loc) · 6.85 KB
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
from typing import List, Tuple
#from predi.config import debug_print
class ASTNode:
def __init__(self, value: str, children: List['ASTNode'] = None):
self.value = value
self.children = children if children is not None else []
def __repr__(self):
return f"ASTNode(value='{self.value}', children={self.children})"
class Parser:
def __init__(self, tokens: List[Tuple[str, str]]):
self.tokens = tokens
self.position = 0
def parse(self) -> ASTNode:
self.position = 0 # Reset the position for each new parse
return self.expression()
def consume(self, expected_tag: str) -> Tuple[str, str]:
if self.position >= len(self.tokens):
raise ValueError(f"Unexpected end of input, expected {expected_tag}")
token = self.tokens[self.position]
if token[1] != expected_tag:
raise ValueError(f"Expected token {expected_tag} but got {token[1]} at position {self.position}")
self.position += 1
return token
def expression(self) -> ASTNode:
node = self.logical_term()
#debug_print(f"Parsed term: {node}")
while self.position < len(self.tokens) and self.tokens[self.position][1] in ('AND', 'OR'):
operator = self.tokens[self.position]
#debug_print(f"Parsing operator in expression: {operator}")
self.position += 1
right = self.logical_term()
node = ASTNode(operator[0], [node, right])
#debug_print(f"Parsed expression with operator: {node}")
return node
def logical_term(self) -> ASTNode:
node = self.equality()
#debug_print(f"Parsed equality: {node}")
while self.position < len(self.tokens) and self.tokens[self.position][1] in ('EQUAL', 'NOT_EQUAL'):
operator = self.tokens[self.position]
#debug_print(f"Parsing operator in logical term: {operator}")
self.position += 1
right = self.equality()
node = ASTNode(operator[0], [node, right])
#debug_print(f"Parsed logical term with operator: {node}")
return node
def equality(self) -> ASTNode:
node = self.relational()
#debug_print(f"Parsed relational: {node}")
while self.position < len(self.tokens) and self.tokens[self.position][1] in ('GREATER', 'LESS', 'GREATER_EQUAL', 'LESS_EQUAL'):
operator = self.tokens[self.position]
#debug_print(f"Parsing operator in equality: {operator}")
self.position += 1
right = self.relational()
node = ASTNode(operator[0], [node, right])
#debug_print(f"Parsed equality with operator: {node}")
return node
def relational(self) -> ASTNode:
node = self.term()
#debug_print(f"Parsed term in relational: {node}")
while self.position < len(self.tokens) and self.tokens[self.position][1] in ('PLUS', 'MINUS'):
operator = self.tokens[self.position]
#debug_print(f"Parsing operator in relational: {operator}")
self.position += 1
right = self.term()
node = ASTNode(operator[0], [node, right])
#debug_print(f"Parsed relational with operator: {node}")
return node
def term(self) -> ASTNode:
node = self.factor()
#debug_print(f"Parsed factor in term: {node}")
while self.position < len(self.tokens) and self.tokens[self.position][1] in ('MULTIPLY', 'DIVIDE', 'MODULUS', 'BITWISE_AND'):
operator = self.tokens[self.position]
#debug_print(f"Parsing operator in term: {operator}")
self.position += 1
right = self.factor()
node = ASTNode(operator[0], [node, right])
#debug_print(f"Parsed term with operator: {node}")
return node
def factor(self) -> ASTNode:
if self.position >= len(self.tokens):
raise ValueError("Unexpected end of input")
token = self.tokens[self.position]
if token[1] in ('TRUE', 'FALSE'):
self.position += 1
return ASTNode(token[0])
if token[1] == 'ADDRESS_LITERAL':
self.position += 1
return ASTNode(token[0])
if token[1] == 'BYTES_LITERAL':
self.position += 1
return ASTNode(token[0])
if token[1] == 'LPAREN':
self.position += 1
node = self.expression()
self.consume('RPAREN')
return node
elif token[1] in ('IDENTIFIER', 'MSG_SENDER', 'MSG_ORIGIN', 'INTEGER', 'FLOAT', 'SCIENTIFIC'):
self.position += 1
node = ASTNode(token[0])
return self.postfix(node)
elif token[1] == 'NOT':
self.position += 1
node = self.factor()
node = ASTNode('!', [node])
return node
elif token[1] in ('PLUS', 'MINUS'):
self.position += 1
node = self.factor()
node = ASTNode(token[0], [node])
return node
raise ValueError(f"Unexpected token {token[1]} at position {self.position}")
def postfix(self, node: ASTNode) -> ASTNode:
while self.position < len(self.tokens) and self.tokens[self.position][1] in ('DOT', 'LBRACKET', 'LPAREN'):
token = self.tokens[self.position]
if token[1] == 'DOT':
self.position += 1
member_token = self.consume('IDENTIFIER')
# Important fix: preserve indexing clearly
node = ASTNode(f"{node.value}.{member_token[0]}", node.children)
elif token[1] == 'LBRACKET':
self.position += 1
index_node = self.expression()
self.consume('RBRACKET')
node = ASTNode(f"{node.value}[]", [index_node])
elif token[1] == 'LPAREN':
self.position += 1
args = []
while self.position < len(self.tokens) and self.tokens[self.position][1] != 'RPAREN':
args.append(self.expression())
if self.position < len(self.tokens) and self.tokens[self.position][1] == 'COMMA':
self.position += 1
self.consume('RPAREN')
node = ASTNode(f"{node.value}()", args)
return node
def function_call(self, token: Tuple[str, str]) -> ASTNode:
function_name = token[0]
self.position += 1 # Consume FUNCTION_CALL token
self.consume('LPAREN')
args = []
while self.position < len(self.tokens) and self.tokens[self.position][1] != 'RPAREN':
args.append(self.expression())
if self.position < len(self.tokens) and self.tokens[self.position][1] == 'COMMA':
self.position += 1
self.consume('RPAREN')
node = ASTNode(function_name, args)
#debug_print(f"Parsed function call: {node}")
return node