/
parser.py
78 lines (71 loc) · 2.51 KB
/
parser.py
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
from string import *
import re
from yappsrt import *
class AssemblyScanner(Scanner):
patterns = [
('","', re.compile(',')),
('#.*(?=$|\\n)', re.compile('#.*(?=$|\\n)')),
('[ \\t\\n\\r]+', re.compile('[ \\t\\n\\r]+')),
('NUM', re.compile('\\$(0x[a-fA-F0-9]+|[0-9]+)')),
('ADR', re.compile('0x[a-fA-F0-9]+|[0-9]+')),
('REG', re.compile('%(\\w+)')),
('OP', re.compile('[a-zA-Z]+')),
('TAG', re.compile('[a-zA-Z0-9_]+')),
('TAGDEF', re.compile('[a-zA-Z0-9_]+:')),
('END', re.compile('$')),
]
def __init__(self, str):
Scanner.__init__(self,None,['#.*(?=$|\\n)', '[ \\t\\n\\r]+'],str)
class Assembly(Parser):
def line(self):
_token_ = self._peek('TAGDEF', 'END', 'OP')
if _token_ == 'OP':
instruction = self.instruction()
END = self._scan('END')
return instruction
elif _token_ == 'TAGDEF':
instruction = None
TAGDEF = self._scan('TAGDEF')
if self._peek('END', 'OP') == 'OP':
instruction = self.instruction()
END = self._scan('END')
t = ('TAGDEF', TAGDEF[:len(TAGDEF)-1])
return list(t, instruction) if instruction else t
else:# == 'END'
END = self._scan('END')
return []
def instruction(self):
OP = self._scan('OP')
result = []
while self._peek('NUM', 'ADR', 'TAG', 'REG', 'END') != 'END':
operand = self.operand()
if self._peek('","', 'NUM', 'ADR', 'TAG', 'REG', 'END') == '","':
self._scan('","')
result.append(operand)
return ('OP', OP, result)
def operand(self):
_token_ = self._peek('NUM', 'ADR', 'TAG', 'REG')
if _token_ == 'NUM':
NUM = self._scan('NUM')
return ('NUM', eval(NUM[1:]))
elif _token_ == 'ADR':
ADR = self._scan('ADR')
return ('ADR', eval(ADR))
elif _token_ == 'TAG':
TAG = self._scan('TAG')
return ('TAG', TAG)
else:# == 'REG'
REG = self._scan('REG')
return ('REG', REG[1:])
def parse(rule, text):
P = Assembly(AssemblyScanner(text))
return wrap_error_reporter(P, rule)
if __name__ == '__main__':
from sys import argv, stdin
if len(argv) >= 2:
if len(argv) >= 3:
f = open(argv[2],'r')
else:
f = stdin
print parse(argv[1], f.read())
else: print 'Args: <rule> [<filename>]'