This repository has been archived by the owner on Jun 20, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
interp.py
81 lines (74 loc) · 2.85 KB
/
interp.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
import sys
from time import sleep
verbose = False
NONTERMINAL = 1
TERMINAL = 2
class CompileError(BaseException):
def __init__(self, source_path: str, ln: int, line: str, msg=None):
self.source_path = source
self.ln = ln
self.line = line
self.message = msg
def __str__():
return f'Error: File {self.source_path}, line {self.ln}:' \
+ f" Invalid syntax: {self.message+': ' if self.message else ''}" \
+ f" {self.line}"
class ExecutionInterrupt(BaseException):
pass
def compile(source_code: str, source_path='<script>'):
source = []
ln = 0
for line in source_code.splitlines():
ln += 1
line = line.split('~')[0]
if not line: continue
if ' : ' in line:
(l_side, r_side), method = line.split(' : '), NONTERMINAL
elif ' ; ' in line:
(l_side, r_side), method = line.split(' ; '), TERMINAL
else:
CompileError(source_path, ln, line, 'No valid method provided')
l_side, r_side = l_side.strip(), r_side.strip()
if not l_side or not r_side:
CompileError(source_path, ln, line, f"No {'left' if not l_side else 'right'} side provided")
l_side, r_side = l_side.replace('#', ''), r_side.replace('#', '')
source.append((method, l_side, r_side))
return source
kill = False
delay = 0.0
def execute(code: list, entry: str):
global kill
kill = False
loop = True
while loop:
for method, l_side, r_side in code:
if kill: raise ExecutionInterrupt()
if l_side in entry:
sleep(delay)
if verbose: print('--D: ', f'{l_side:>10}', '>->' if method == TERMINAL else '-->', f'{r_side:<10}', '|', f'{entry:>15}', '>->' if method == TERMINAL else '-->', end=' ')
entry = entry.replace(l_side, r_side, 1)
if method == TERMINAL: loop = False
if verbose: print(entry)
break
return entry
def interrupt():
global kill
kill = True
if __name__ == '__main__':
if '-v' in sys.argv or '--verbose' in sys.argv:
verbose = True
sys.argv.remove('-v' if '-v' in sys.argv else '--verbose')
if '-d' in sys.argv or '--delay' in sys.argv:
pos = sys.argv.index('-d' if '-d' in sys.argv else '--delay')
delay = float(sys.argv[pos+1])
del sys.argv[pos:pos+2]
if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) < 2:
print('Usage: alt.py [-v] [--verbose] [-h] [--help] <source.alt> [input]')
exit()
source_path = sys.argv[1]
source_code = open(source_path, 'r').read()
entry = sys.argv[2] if len(sys.argv) > 2 else input('Enter input: ')
code = compile(source_code, source_path)
try:
print(('Output: ' if verbose else '') + execute(code, entry))
except KeyboardInterrupt: pass