-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlexer.py
More file actions
77 lines (71 loc) · 1.88 KB
/
Copy pathlexer.py
File metadata and controls
77 lines (71 loc) · 1.88 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
import re
import sys
from tokens import Token
spec = [
('LET', r'\bLET\b'),
('PRINT', r'\bPRINT\b'),
('IF', r'\bIF\b'),
('THEN', r'\bTHEN\b'),
('ELSE', r'\bELSE\b'),
('FOR', r'\bFOR\b'),
('NEXT', r'\bNEXT\b'),
('GOTO', r'\bGOTO\b'),
('REM', r'\bREM\b'),
('END', r'\bEND\b'),
('ASSIGN', r'='),
('PLUS', r'\+'),
('MINUS', r'-'),
('TIMES', r'\*'),
('DIVIDE', r'/'),
('EQ', r'=='),
('NEQ', r'<>'),
('LT', r'<'),
('GT', r'>'),
('LINENUMBER', r'^\d{1,5}\s+'),
('NUMBER', r'\d+(\.\d+)?'),
('IDENTIFIER', r'[A-Za-z][A-Za-z0-9_]*'),
('SEMI', r';'),
('COMMA', r','),
('STRING_LITERAL', r'"([^"\\]*(\\.[^"\\]*)*)"'),
('SKIP', r'[ \t]+'),
('NEWLINE', r'\n'),
('COMMENT', r'REM.*'),
('MISMATCH', r'.'),
]
DEBUG=False
class Lexer:
def __init__(self,w):
self.w=w
self.t=self._build_regex()
self.pos=0
self.after_newline=True
def _build_regex(self):
r='|'.join(f'(?P<{t}>{p})' for t,p in spec)
return re.compile(r)
def next_token(self):
if self.pos>=len(self.w):
return Token('EOF','',self.pos)
m=self.t.match(self.w,self.pos)
if not m:
if DEBUG:
print(f"Lexer error at position {self.pos}: {self.w[self.pos]}")
return Token('MISMATCH',self.w[self.pos],self.pos)
for k,_ in spec:
v=m.group(k)
if v:
if DEBUG:
# FIXME: this prints out before the LINENUMBER fixed
print(f"Matched {k}: {repr(v)} at position {self.pos}")
self.pos=m.end()
if k=='SKIP':
return self.next_token()
if k=='NEWLINE':
self.after_newline=True
return Token(k,v,self.pos)
if k=='NUMBER' and self.after_newline:
self.after_newline=False
print("Linenumber:", v)
return Token('LINENUMBER',v,self.pos)
self.after_newline=False
return Token(k,v,self.pos)
return Token('EOF','',self.pos)