comparison python/ppci/common.py @ 312:2c9768114877

Added cool logging formatter
author Windel Bouwman
date Mon, 16 Dec 2013 17:58:15 +0100
parents 6aa721e7b10b
children 6f4753202b9a
comparison
equal deleted inserted replaced
311:ff665880a6b0 312:2c9768114877
1 from collections import namedtuple 1 from collections import namedtuple
2 import logging
2 3
4 """
5 Error handling routines
6 Diagnostic utils
7 Source location structures
8 """
3 9
4 # Token is used in the lexical analyzer: 10 # Token is used in the lexical analyzer:
5 class Token: 11 class Token:
6 def __init__(self, typ, val, loc=None): 12 def __init__(self, typ, val, loc=None):
7 self.typ = typ 13 self.typ = typ
25 def __repr__(self): 31 def __repr__(self):
26 return '{}, {}, {}'.format(self.filename, self.row, self.col) 32 return '{}, {}, {}'.format(self.filename, self.row, self.col)
27 33
28 34
29 SourceRange = namedtuple('SourceRange', ['p1', 'p2']) 35 SourceRange = namedtuple('SourceRange', ['p1', 'p2'])
36
37
38 class CompilerError(Exception):
39 def __init__(self, msg, loc=None):
40 self.msg = msg
41 self.loc = loc
42 if loc:
43 assert type(loc) is SourceLocation, \
44 '{0} must be SourceLocation'.format(type(loc))
45 self.row = loc.row
46 self.col = loc.col
47 else:
48 self.row = self.col = 0
49
50 def __repr__(self):
51 return '"{}"'.format(self.msg)
52
53
54 class DiagnosticsManager:
55 def __init__(self):
56 self.diags = []
57 self.sources = {}
58 self.logger = logging.getLogger('diagnostics')
59
60 def addSource(self, name, src):
61 self.logger.info('Adding source {}'.format(name))
62 self.sources[name] = src
63
64 def addDiag(self, d):
65 #self.logger.warning(str(d.msg))
66 self.diags.append(d)
67
68 def error(self, msg, loc):
69 self.addDiag(CompilerError(msg, loc))
70
71 def clear(self):
72 del self.diags[:]
73 self.sources.clear()
74
75 def printErrors(self):
76 if len(self.diags) > 0:
77 print('{0} Errors'.format(len(self.diags)))
78 for d in self.diags:
79 self.printError(d)
80
81 def printError(self, e):
82 def printLine(row, txt):
83 print(str(row)+':'+txt)
84 print('==============')
85 if not e.loc:
86 print('Error: {0}'.format(e))
87 else:
88 if e.loc.filename not in self.sources:
89 print('Error: {0}'.format(e))
90 return
91 print("File: {}".format(e.loc.filename))
92 source = self.sources[e.loc.filename]
93 lines = source.split('\n')
94 ro, co = e.row, e.col
95 prerow = ro - 2
96 if prerow < 1:
97 prerow = 1
98 afterrow = ro + 3
99 if afterrow > len(lines):
100 afterrow = len(lines)
101
102 # print preceding source lines:
103 for r in range(prerow, ro):
104 printLine(r, lines[r-1])
105 # print source line containing error:
106 printLine(ro, lines[ro-1])
107 print(' '*(len(str(ro)+':')+co-1) + '^ Error: {0}'.format(e.msg))
108 # print trailing source line:
109 for r in range(ro+1, afterrow+1):
110 printLine(r, lines[r-1])
111 print('==============')