1# © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2# 3# 2019 Cog Systems Pty Ltd. 4# 5# SPDX-License-Identifier: BSD-3-Clause 6 7import re 8 9 10class BaseError(Exception): 11 def get_context(self, text, pos, span=40): 12 start = max(pos - span, 0) 13 end = pos + span 14 before = text[start:pos].rsplit('\n', 1)[-1] 15 after = text[pos:end].split('\n', 1)[0] 16 before_spaces = re.sub(r'\S', ' ', before) 17 return before + after + '\n' + before_spaces + '^\n' 18 19 20class DSLError(BaseError): 21 def __init__(self, message, token, expecting=None, state=None): 22 meta = getattr(token, 'meta', token) 23 self.line = getattr(meta, 'line', '?') 24 self.column = getattr(meta, 'column', '?') 25 self.pos_in_stream = getattr(meta, 'start_pos', 26 getattr(meta, 'pos_in_stream', None)) 27 self.expecting = expecting 28 self.state = state 29 30 message = "\nError: %s\n" % message 31 message += "\nToken %s, at line %s col %s:\n" % ( 32 str(token), self.line, self.column) 33 if isinstance(self.pos_in_stream, int): 34 message += '\n' + self.get_context(token.program, 35 self.pos_in_stream) 36 if expecting: 37 message += '\nExpecting: %s\n' % expecting 38 39 super(DSLError, self).__init__(message) 40 41 42class DSLErrorWithRefs(BaseError): 43 def __init__(self, message, token, refs, expecting=None, state=None): 44 meta = getattr(token, 'meta', token) 45 self.line = getattr(meta, 'line', '?') 46 self.column = getattr(meta, 'column', '?') 47 self.pos_in_stream = getattr(meta, 'start_pos', 48 getattr(meta, 'pos_in_stream', None)) 49 self.expecting = expecting 50 self.state = state 51 52 message = "\nError: %s\n" % message 53 message += "\nAt line %d col %d:\n" % (self.line, self.column) 54 message += '\n' + self.get_context(token.program, self.pos_in_stream) 55 56 message += "\nRefs:" 57 for r in refs: 58 line = getattr(r, 'line', '?') 59 column = getattr(r, 'column', '?') 60 pos = getattr(r, 'pos_in_stream', None) 61 message += "\nAt line %d col %d:\n" % (line, column) 62 message += '\n' + self.get_context(token.program, pos) 63 64 if expecting: 65 message += '\nExpecting: %s\n' % expecting 66 67 super(DSLErrorWithRefs, self).__init__(message) 68 69 70class RangeError(DSLError): 71 pass 72