-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.py
More file actions
94 lines (80 loc) · 2.67 KB
/
parser.py
File metadata and controls
94 lines (80 loc) · 2.67 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
from tokens import Token
class Parser:
def __init__(self,tokens):
self.tokens=tokens
self.pos=0
def __repr__(self):
return f"Parser({repr(self.tokens)})"
def peek(self):
return self.tokens[self.pos] if self.pos < len(self.tokens) else Token('EOF','',self.pos)
def advance(self):
self.pos+=1
def skip_newlines(self):
while self.peek().typ=='NEWLINE':
self.advance()
def require(self, typ):
t=self.peek()
if t.typ==typ:
print(f"Advance: {typ}")
self.advance()
return t
raise SyntaxError(f"Expected {typ}, got {t.typ}")
def parse_program(self):
p=[]
while self.peek().typ!='EOF':
self.skip_newlines()
s=self.parse_statement()
if s:
p.append(s)
return p
def parse_statement(self):
""" single token """
t=self.peek()
if t.typ=='LINENUMBER':
self.advance() # skip labels
return self.parse_labled_statement()
else:
# FIXME: command to the basic interpreter e.g. RUN or LIST
raise SyntaxError(f"Unexpected token {t.typ} at position {t.pos}")
def parse_labled_statement(self):
""" statement prefixed with number """
t=self.peek()
if t.typ=='PRINT':
return self.parse_print_statement()
if t.typ=='LET' or t.typ=='IDENTIFIER': # fixme: it's requiring me anyway because of this if statement here.
# so require("LET") is not strictly necessary...
return self.parse_let_statement()
if t.typ=='FOR':
return self.parse_for_statement()
if t.typ=='END':
self.advance()
return {"type": "End"}
raise SyntaxError(f"Unsupported statement {t.typ}")
def parse_print_statement(self):
""" print statement """
self.require('PRINT')
expr=self.parse_expression()
return {'type': 'Print', 'expression': expr}
def parse_let_statement(self):
""" let statement """
# self.require('LET', False(???)) # LET (keyword) A (identifier) = (assign) 5 (number)
t=self.peek()
print(f"Current token: {t.typ}") # It's advancing when it shouldn't? Skip linenumber, then?
ident=self.require('IDENTIFIER').val# .val
t=self.peek()
print(f"Current token: {t.typ}")
self.require('ASSIGN')
expr=self.parse_expression()
return {'type': 'Let', 'identifier': ident, 'expression': expr}
def parse_for_statement(self):
pass
def parse_expression(self):
t=self.peek()
if t.typ=='STRING_LITERAL':
self.advance()
return {"type": "StringLiteral", "value": t.val}
elif t.typ=='NUMBER':
self.advance()
return {"type": "Number", "value": t.val}
else:
raise SyntaxError(f"Unexpected token {t.typ} at position {t.pos}")