def skip_whitespace(s, start):
"""Find the first non-whitespace character in a string.
:param str s: an input string
:param int start: an index where the search starts
:return: index of the first non-whitespace character or len(s)"""
i = start
while i < len(s) and s[i].isspace():
i += 1
return i
def str_row_col(s, i):
"""Translate a string index i to a row and col number.
:param str s: an input string
:param int i: an index pointing into s
:return: a string position as (row, col)
:rtype: (int, int)"""
k = 0
(r, c) = (0, 0)
for (r, line) in enumerate(s.splitlines(True)):
c = i-k
if k+len(line) > i:
break
else:
k += len(line)
return (r+1, c+1)
class ParserError(Exception):
def __init__(self, msg, s, i):
self.msg = msg
(self.row, self.col) = str_row_col(s, i)
self.context = s[i:i+16]
def __str__(self):
return "{0} at row {1}, col {2}, got '{3}...' instead".format(self.msg, self.row, self.col, self.context)
class ParserWarning(ParserError):
pass