-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
114 lines (86 loc) · 2.69 KB
/
main.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
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
import sys
import math
import lex
import parse
import semantic
from error import ParseError, LexError, SemanticError
class PyCC():
lines = []
lexer = lex.Lexer()
parser = parse.Parser()
analyzer = semantic.SemanticAnalyzer()
def repl():
while True:
line = input('PyCC> ').strip()
op = PyCC.repl_cmds.get(line)
if op:
op()
else:
try:
ln, src = line.split(maxsplit=1)
ln = int(ln)
if ln > len(PyCC.lines):
PyCC.lines += ['' for x in range(ln + 2)]
PyCC.lines[ln + 1] = src
except (ValueError, TypeError) as e:
PyCC.compile_line(line)
def file(path=''):
with open(path) as fp:
PyCC.lines = [line.strip() for line in fp]
PyCC.compile()
def compile():
try:
tokens = PyCC.lexer.tokenize(PyCC.lines)
ast = PyCC.parser.parse(tokens)
sym = PyCC.analyzer.analyze(ast)
PyCC.print_results(tokens, ast, sym)
except (LexError, ParseError, SemanticError) as e:
print(e)
def compile_line(line):
try:
tokens = PyCC.lexer.tokenize([line])
ast = PyCC.parser.parse(tokens)
sym = PyCC.analyzer.analyze(ast)
PyCC.print_results(tokens, ast, sym)
except (LexError, ParseError, SemanticError) as e:
print(e)
def _print_ast_node(node, level = 0):
if isinstance(node, tuple):
for e in node:
PyCC._print_ast_node(e, level + 1)
else:
print(' ' * level, node)
def print_results(tokens, ast, symbols):
print('Tokens:')
for t in tokens:
print(t)
print('\n')
print('Syntax Tree:')
#print(ast)
PyCC._print_ast_node(ast)
print('\n')
print('Global Symbols:')
for sym in symbols:
print('{} : {}'.format(sym, symbols[sym]))
print('\n')
def main():
if len(sys.argv) > 1:
PyCC.file(sys.argv[1])
else:
PyCC.repl()
def print_lines():
k = int(math.log(len(PyCC.lines) + 1))
for i, ln in enumerate(PyCC.lines):
if ln:
print('{num:{width}}'.format(num=i, width=k), ln)
repl_cmds = {
'run': compile,
'source': print_lines,
'clear': lambda: PyCC.lines.clear(),
'exit': lambda: sys.exit(0),
}
if __name__ == '__main__':
try:
PyCC.main()
except (EOFError, KeyboardInterrupt) as e:
print('Farewell')