-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.py
More file actions
159 lines (128 loc) · 4.94 KB
/
parser.py
File metadata and controls
159 lines (128 loc) · 4.94 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
from lexer import Tokenizer, TokenType
from AST import *
class Parser:
def __init__(self, tokens):
self.tokens = tokens
self.pos = 0
def current_token(self):
if self.pos < len(self.tokens):
return self.tokens[self.pos]
return None
def peek_token(self, offset = 1):
peek_pos = self.pos + offset
if peek_pos < len(self.tokens):
return self.tokens[peek_pos]
return None
def advance(self):
if self.pos < len(self.tokens):
self.pos += 1
def expect(self, token_type):
token = self.current_token()
if token and token.type == token_type:
self.advance()
return token
raise SyntaxError(f"Expected {token_type}, got {token.type if token else 'EOF'}")
def parse_statement(self):
token = self.current_token()
if not token:
return None
if token.type == TokenType.IDENTIFIER and self.peek_token() and self.peek_token().type == TokenType.ASSIGN:
return self.parse_assignment()
elif token.type == TokenType.IF:
return self.parse_if()
elif token.type == TokenType.WHILE:
return self.parse_while()
else:
expr = self.parse_expression()
return expr
def parse_assignment(self):
name = self.expect(TokenType.IDENTIFIER).value
self.expect(TokenType.ASSIGN)
value = self.parse_expression()
return Assign(name, value)
def parse_if(self):
self.expect(TokenType.IF)
condition = self.parse_expression()
self.expect(TokenType.COLON)
then_branch = [self.parse_statement()]
else_branch = None
if self.current_token() and self.current_token().type == TokenType.ELSE:
self.advance()
self.expect(TokenType.COLON)
else_branch = [self.parse_statement()]
return If(condition, then_branch, else_branch)
def parse_while(self):
self.expect(TokenType.WHILE)
condition = self.parse_expression()
self.expect(TokenType.COLON)
body = [self.parse_statement()]
return While(condition, body)
def parse_expression(self):
return self.parse_comparison()
def parse_comparison(self):
expr = self.parse_addition()
while self.current_token() and self.current_token().type in [TokenType.GREATER, TokenType.LESS]:
op = self.current_token().value
self.advance()
right = self.parse_addition()
expr = BinOp(expr, op, right)
return expr
def parse_addition(self):
expr = self.parse_multiplication()
while self.current_token() and self.current_token().type in [TokenType.PLUS, TokenType.MINUS]:
op = self.current_token().value
self.advance()
right = self.parse_multiplication()
expr = BinOp(expr,op, right)
return expr
def parse_multiplication(self):
expr = self.parse_unary()
while self.current_token() and self.current_token().type in [TokenType.MULTIPLY, TokenType.DIVIDE]:
op = self.current_token().value
self.advance()
right = self.parse_unary()
expr = BinOp(expr, op, right)
return expr
def parse_unary(self):
if self.current_token() and self.current_token().type == TokenType.MINUS:
op = self.current_token().value
self.advance()
operand = self.parse_unary()
return UnaryOp(op, operand)
return self.parse_primary()
def parse_primary(self):
token = self.current_token()
if not token:
raise SyntaxError("Unexpected end of input")
if token.type == TokenType.NUMBER:
self.advance()
return Number(token.value)
elif token.type == TokenType.STRING:
self.advance()
return String(token.value)
elif token.type == TokenType.IDENTIFIER:
self.advance()
return Variable(token.value)
elif token.type == TokenType.LPAREN:
self.advance()
expr = self.parse_expression()
self.expect(TokenType.RPAREN)
return expr
else:
raise SyntaxError(f"Unexpected token: {token.type}")
def parse(self):
statements = []
while self.current_token() and self.current_token().type != TokenType.EOF:
if self.current_token().type == TokenType.NEWLINE:
self.advance()
continue
statement = self.parse_statement()
if statement:
statements.append(statement)
return Program(statements)
def parse(code):
"""Convenience function to parse code string"""
tokenizer = Tokenizer(code)
tokens = tokenizer.tokenize()
parser = Parser(tokens)
return parser.parse()