-
Notifications
You must be signed in to change notification settings - Fork 7
/
Errors.py
158 lines (138 loc) · 5.4 KB
/
Errors.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#/*-------------------------------------------------------------------------
#Errors.py -- Error handling routines
#Compiler Generator Coco/R,
#Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
#extended by M. Loeberbauer & A. Woess, Univ. of Linz
#ported from Java to Python by Ronald Longo
#
#This program is free software; you can redistribute it and/or modify it
#under the terms of the GNU General Public License as published by the
#Free Software Foundation; either version 2, or (at your option) any
#later version.
#
#This program is distributed in the hope that it will be useful, but
#WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
#or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
#for more details.
#
#You should have received a copy of the GNU General Public License along
#with this program; if not, write to the Free Software Foundation, Inc.,
#59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#As an exception, it is allowed to write an extension of Coco/R that is
#used as a plugin in non-free software.
#
#If not otherwise stated, any source code generated by Coco/R (other than
#Coco/R itself) does not fall under the GNU General Public License.
#-------------------------------------------------------------------------*/
import sys
class ErrorRec( object ):
def __init__( self, l, c, s ):
self.line = l
self.col = c
self.num = 0
self.str = s
class Errors( object ):
errMsgFormat = "file %(file)s : (%(line)s, %(col)s) %(text)s\n"
eof = False
count = 0 # number of errors detected
fileName = ''
listName = ''
mergeErrors = False
mergedList = None # PrintWriter
errors = [ ]
minErrDist = 2
errDist = minErrDist
# A function with prototype: f( errorNum=None ) where errorNum is a
# predefined error number. f returns a tuple, ( line, column, message )
# such that line and column refer to the location in the
# source file most recently parsed. message is the error
# message corresponging to errorNum.
@staticmethod
def Init( fn, dir, merge, getParsingPos, errorMessages ):
Errors.theErrors = [ ]
Errors.getParsingPos = getParsingPos
Errors.errorMessages = errorMessages
Errors.fileName = fn
listName = dir + 'listing.txt'
Errors.mergeErrors = merge
if Errors.mergeErrors:
try:
Errors.mergedList = open( listName, 'w' )
except IOError:
raise RuntimeError( '-- Compiler Error: could not open ' + listName )
@staticmethod
def storeError( line, col, s ):
if Errors.mergeErrors:
Errors.errors.append( ErrorRec( line, col, s ) )
else:
Errors.printMsg( Errors.fileName, line, col, s )
@staticmethod
def SynErr( errNum, errPos=None ):
line,col = errPos if errPos else Errors.getParsingPos( )
msg = Errors.errorMessages[ errNum ]
Errors.storeError( line, col, msg )
Errors.count += 1
@staticmethod
def SemErr( errMsg, errPos=None ):
line,col = errPos if errPos else Errors.getParsingPos( )
Errors.storeError( line, col, errMsg )
Errors.count += 1
@staticmethod
def Warn( errMsg, errPos=None ):
line,col = errPos if errPos else Errors.getParsingPos( )
Errors.storeError( line, col, errMsg )
@staticmethod
def Exception( errMsg ):
print errMsg
sys.exit( 1 )
@staticmethod
def printMsg( fileName, line, column, msg ):
vals = { 'file':fileName, 'line':line, 'col':column, 'text':msg }
sys.stdout.write( Errors.errMsgFormat % vals )
@staticmethod
def display( s, e ):
Errors.mergedList.write('**** ')
for c in xrange( 1, e.col ):
if s[c-1] == '\t':
Errors.mergedList.write( '\t' )
else:
Errors.mergedList.write( ' ' )
Errors.mergedList.write( '^ ' + e.str + '\n')
@staticmethod
def Summarize( sourceBuffer ):
if Errors.mergeErrors:
# Initialize the line iterator
srcLineIter = iter(sourceBuffer)
srcLineStr = srcLineIter.next( )
srcLineNum = 1
try:
# Initialize the error iterator
errIter = iter(Errors.errors)
errRec = errIter.next( )
# Advance to the source line of the next error
while srcLineNum < errRec.line:
Errors.mergedList.write( '%4d %s\n' % (srcLineNum, srcLineStr) )
srcLineStr = srcLineIter.next( )
srcLineNum += 1
# Write out all errors for the current source line
while errRec.line == srcLineNum:
Errors.display( srcLineStr, errRec )
errRec = errIter.next( )
except:
pass
# No more errors to report
try:
# Advance to end of source file
while True:
Errors.mergedList.write( '%4d %s\n' % (srcLineNum, srcLineStr) )
srcLineStr = srcLineIter.next( )
srcLineNum += 1
except:
pass
Errors.mergedList.write( '\n' )
Errors.mergedList.write( '%d errors detected\n' % Errors.count )
Errors.mergedList.close( )
sys.stdout.write( '%d errors detected\n' % Errors.count )
if (Errors.count > 0) and Errors.mergeErrors:
sys.stdout.write( 'see ' + Errors.listName + '\n' )