-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy patherror.py
More file actions
117 lines (93 loc) · 3.4 KB
/
error.py
File metadata and controls
117 lines (93 loc) · 3.4 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
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
115
116
import flags
def get_location_text_lines(location):
if not location.empty:
with open(location.filename, 'r') as f:
lines = list(f.readlines())
return lines[location.line-1:location.end_line]
else:
return ''
def error_header(location):
if not location.empty:
return '{file}:{line1}.{column1}-{line2}.{column2}: ' \
.format(file=location.filename,
line1=location.line, column1=location.column,
line2=location.end_line, column2=location.end_column)
else:
return '' # Don't want to risk returning None ever leading to issues
def error_program_text(location):
if not location.empty:
lines = get_location_text_lines(location)
# last line decides where we draw the carrots (^)
error = lines[-1]
start_column = location.column - 1 if location.line == location.end_line else 0
num_space = start_column
num_carrot = location.end_column - start_column - 1
# replace tabs with an exact number of spaces
tab_width = 4
for i in range(len(error)):
if error[i] == '\t':
if i < start_column:
num_space += tab_width - 1
else:
num_carrot += tab_width - 1
# num_space += tab_width
# num_carrot -= 1
error = error.replace('\t', ' ' * tab_width)
lines = list(map(lambda s: s.replace('\t', ' ' * tab_width), lines))
if error[-1] != '\n': error += '\n'
error += (' ' * num_space) + ('^' * num_carrot)
return ''.join(lines[:-1]) + error
else:
return ''
def error(location, msg):
exc = Exception(error_header(location) + msg)
# exc = Exception(error_header(location) + '\n\n' + error_program_text(location) + '\n\n' + msg)
exc.depth = 0
raise exc
class IncompleteProof(Exception):
pass
def incomplete_error(location, msg):
exc = IncompleteProof(error_header(location) + msg)
exc.depth = 0
raise exc
def warning(location, msg):
print(error_header(location) + msg)
class StaticError(Exception):
pass
def static_error(location, msg):
raise StaticError(error_header(location) + msg)
# raise StaticError(error_header(location) + '\n\n' + error_program_text(location) + '\n\n' + msg)
class MatchFailed(Exception):
pass
def match_failed(location, msg):
raise MatchFailed(error_header(location) + msg)
# raise MatchFailed(error_header(location) + '\n\n' + error_program_text(location) + '\n\n' + msg)
MAX_ERR_DEPTH = 2
# Parse Errors need to carry around some extra data
class ParseError(Exception):
def __init__(self, loc, msg, depth=0, missing=False, last=False):
super().__init__(msg)
self.loc = loc
self.depth = depth
self.missing = missing
self.last = last
self.trace = []
def extend(self, loc, msg):
self.trace.append(ParseError(loc, msg))
return self
def base_message(self):
return super().__str__()
def error_base(self):
base = error_header(self.loc) + super().__str__()
if self.trace:
base = "\n" + base
return base
# return "\n".join([x.error_str() for x in reversed(self.trace[:MAX_ERR_DEPTH])]) + base
def __str__(self):
# base = error_header(self.loc) + super().__str__()
# if self.trace:
# base = "\n" + base
return "\n".join([x.error_base() for x in reversed(self.trace[:MAX_ERR_DEPTH])]) + \
'\n\n' + error_program_text(self.loc) + '\n' + \
self.error_base()
# return self.error_str() #+ '\n\n' + error_program_text(self.loc)