-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathtokenizer.py
More file actions
46 lines (39 loc) · 1.32 KB
/
Copy pathtokenizer.py
File metadata and controls
46 lines (39 loc) · 1.32 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
import re
import collections
Token = collections.namedtuple('Token', ['typ', 'value', 'line', 'column'])
TOKENS = [
('NUMBER', r'\d+(?:\.\d*)?'),
('ASSIGN', r':='),
('END', r';'),
('ID', r'[a-zA-Z]+'),
('OP', r'[+\-*/]'),
('NEWLINE', r'\n'),
('SKIP', r'[ \t]+'),
('MISMATCH', r'.+')
]
KEYWORDS = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
TOKEN_REGEX = re.compile('|'.join([r'(?P<%s>%s)' % pair for pair in TOKENS]), flags=re.MULTILINE)
def tokenize(code):
"""tokenize a code snippet given the above language elements"""
line_nr = 1; nr_chars_before = 0
for m in TOKEN_REGEX.finditer(code):
kind = m.lastgroup
value = m.group(kind)
column = m.start(kind) - nr_chars_before
if kind == 'NEWLINE':
line_nr += 1
nr_chars_before = m.end(kind)
continue
elif kind == 'ID' and value in KEYWORDS:
kind = value
elif kind == 'SKIP': continue
elif kind == 'MISMATCH':
raise RuntimeError('Unknown error on line %d, column %d' %(line_nr, m.start(kind) - nr_chars_before))
yield Token(typ=kind, value=value, line=line_nr, column=column)
statements = '''
IF quantity THEN
total := total + price * quantity;
tax := price * 0.05;
ENDIF;'''
for token in tokenize(statements):
print(token)