[pypy-svn] r44536 - pypy/dist/pypy/rlib/parsing
cfbolz at codespeak.net
cfbolz at codespeak.net
Tue Jun 26 00:55:38 CEST 2007
Author: cfbolz
Date: Tue Jun 26 00:55:38 2007
New Revision: 44536
Modified:
pypy/dist/pypy/rlib/parsing/makepackrat.py
Log:
try to generate nice error messages
Modified: pypy/dist/pypy/rlib/parsing/makepackrat.py
==============================================================================
--- pypy/dist/pypy/rlib/parsing/makepackrat.py (original)
+++ pypy/dist/pypy/rlib/parsing/makepackrat.py Tue Jun 26 00:55:38 2007
@@ -10,6 +10,7 @@
Exception.__init__(self, error)
+
class TreeOptimizer(RPythonVisitor):
def visit_or(self, t):
if len(t.children) == 1:
@@ -248,6 +249,33 @@
def __str__(self):
return "ErrorInformation(%s, %s)" % (self.pos, self.expected)
+ def get_line_column(self, source):
+ uptoerror = source[:self.pos]
+ lineno = uptoerror.count("\n")
+ columnno = self.pos - uptoerror.rfind("\n")
+ return lineno, columnno
+
+ def nice_error_message(self, filename='<filename>', source=""):
+ if source:
+ lineno, columnno = self.get_line_column(source)
+ result = [" File %s, line %s" % (filename, lineno + 1)]
+ result.append(source.split("\n")[lineno])
+ result.append(" " * columnno + "^")
+ else:
+ result.append("<couldn't get source>")
+ if self.expected:
+ failure_reasons = self.expected
+ if len(failure_reasons) > 1:
+ all_but_one = failure_reasons[:-1]
+ last = failure_reasons[-1]
+ expected = "%s or '%s'" % (
+ ", ".join(["'%s'" % e for e in all_but_one]), last)
+ else:
+ expected = failure_reasons[0]
+ result.append("ParseError: expected %s" % (expected, ))
+ else:
+ result.append("ParseError")
+ return "\n".join(result)
class Status(object):
# status codes:
@@ -634,10 +662,27 @@
if '__doc__' not in dct or dct['__doc__'] is None:
return type.__new__(cls, name_, bases, dct)
from pypackrat import PyPackratSyntaxParser
- import sys, new
+ import sys, new, inspect
frame = sys._getframe(1)
- p = PyPackratSyntaxParser(dct['__doc__'])
- t = p.file()
+ source = dct['__doc__']
+ p = PyPackratSyntaxParser(source)
+ try:
+ t = p.file()
+ except BacktrackException, exc:
+ print exc.error.nice_error_message("<docstring>", source)
+ lineno, _ = exc.error.get_line_column(source)
+ errorline = source.split("\n")[lineno]
+ try:
+ code = frame.f_code
+ source = inspect.getsource(code)
+ lineno_in_orig = source.split("\n").index(errorline)
+ if lineno_in_orig >= 0:
+ print "probable error position:"
+ print "file:", code.co_filename
+ print "line:", lineno_in_orig + code.co_firstlineno + 1
+ except (IOError, ValueError):
+ pass
+ raise exc
t = t.visit(TreeOptimizer())
visitor = ParserBuilder()
t.visit(visitor)
@@ -649,6 +694,8 @@
#XXX XXX XXX
if 'BacktrackException' not in frame.f_globals:
raise Exception("must import BacktrackException")
+ if 'Status' not in frame.f_globals:
+ raise Exception("must import Status")
for key, value in pcls.__dict__.iteritems():
if isinstance(value, type(lambda: None)):
value = new.function(value.func_code, frame.f_globals)
More information about the Pypy-commit
mailing list