def test_formattedReporting(self): """ Parse errors can be formatted into a nice human-readable view containing the erroneous input and possible fixes. """ g = self.compile(""" dig = '1' | '2' | '3' bits = <dig>+ """) input = "123x321" e = self.assertRaises(ParseError, g.bits, input) self.assertEqual(e.formatError(), dedent(""" 123x321 ^ Parse error at line 1, column 3: expected one of '1', '2', or '3'. trail: [dig] """)) input = "foo\nbaz\nboz\ncharlie\nbuz" e = ParseError(input, 12, expected('token', 'foo') + expected(None, 'b')) self.assertEqual(e.formatError(), dedent(""" charlie ^ Parse error at line 4, column 0: expected one of 'b', or token 'foo'. trail: [] """)) input = '123x321' e = ParseError(input, 3, expected('digit')) self.assertEqual(e.formatError(), dedent(""" 123x321 ^ Parse error at line 1, column 3: expected a digit. trail: [] """))
def test_predSuccess(self): """ L{OMetaBase.pred} returns True and empty error info on success. """ o = OMetaBase("") v, e = o.pred(lambda: (True, ParseError(o.input, 0, None))) self.assertEqual((v, e), (True, ParseError(o.input, 0, None)))
def test_predFailure(self): """ L{OMetaBase.pred} returns True and empty error info on success. """ o = OMetaBase("") with self.assertRaises(ParseError) as e: o.pred(lambda: (False, ParseError(o.input, 0, None))) self.assertEqual(e.exception, ParseError(o.input, 0, None))
def test_digit(self): """ L{OMetaBase.rule_digit} matches digits. """ o = OMetaBase("1a") v, e = o.rule_digit() self.assertEqual((v, e), ("1", ParseError("1a", 0, None))) exc = self.assertRaises(ParseError, o.rule_digit) self.assertEqual(exc, ParseError(o.input, 1, expected("digit")))
def test_letter(self): """ L{OMetaBase.rule_letter} matches letters. """ o = OMetaBase("a1") v, e = o.rule_letter() self.assertEqual((v, e), ("a", ParseError(o.input, 0, None))) exc = self.assertRaises(ParseError, o.rule_letter) self.assertEqual(exc, ParseError(o.input, 1, expected("letter")))
def test_predFailure(self): """ L{OMetaBase.pred} returns True and empty error info on success. """ o = OMetaBase("") exc = self.assertRaises(ParseError, o.pred, lambda: (False, ParseError(o.input, 0, None))) self.assertEqual(exc, ParseError(o.input, 0, None))
def test_end(self): """ L{OMetaBase.rule_end} matches the end of input and raises L{ParseError} if input is left. """ o = OMetaBase("abc") exc = self.assertRaises(ParseError, o.rule_end) self.assertEqual(exc, ParseError(o.input, 1, None)) o.many(o.rule_anything) self.assertEqual(o.rule_end(), (True, ParseError("abc", 3, None)))
def test_letterOrDigit(self): """ L{OMetaBase.rule_letterOrDigit} matches alphanumerics. """ o = OMetaBase("a1@") v, e = o.rule_letterOrDigit() self.assertEqual((v, e), ("a", ParseError(None, 0, None))) v, e = o.rule_letterOrDigit() self.assertEqual((v, e), ("1", ParseError(None, 1, None))) exc = self.assertRaises(ParseError, o.rule_letterOrDigit) self.assertEqual(exc, ParseError(o.input, 2, expected("letter or digit")))
def test_customLabelsFormatting(self): """ Custom labels replace the 'expected' part of the exception. """ input = "foo\nbaz\nboz\ncharlie\nbuz" label = 'Fizz Buzz' e = ParseError(input, 12, None).withMessage([("Custom Exception:", label, None)]) self.assertEqual(e.formatError(), dedent(""" charlie ^ Parse error at line 4, column 0: expected a Fizz Buzz. trail: [] """))
def test_listpattern(self): """ L{OMetaBase.rule_listpattern} matches contents of lists. """ o = OMetaBase([["a"]], tree=True) v, e = o.listpattern(lambda: o.exactly("a")) self.assertEqual((v, e), (["a"], ParseError("a", 0, None)))
def test_many(self): """ L{OMetaBase.many} returns a list of parsed values and the error that caused the end of the loop. """ data = "ooops" o = OMetaBase(data) self.assertEqual( o.many(lambda: o.rule_exactly('o')), (['o'] * 3, ParseError(o.input, 3, expected(None, 'o'))))
def test_label(self): """ L{OMetaBase.label} returns a list of parsed values and the error that caused the end of the loop. """ data = "ooops" label = 'CustomLabel' o = OMetaBase(data) with self.assertRaises(ParseError) as e: o.label(lambda: o.rule_exactly('x'), label) self.assertEqual( e.exception, ParseError(o.input, 0, expected(label)).withMessage([ ("Custom Exception:", label, None) ]))
def invokeRule(*args, **kwargs): """ Invoke a Parsley rule. Passes any positional args to the rule. """ try: ret, err = self._grammar.apply(name, *args) except ParseError as e: self._grammar.considerError(e) err = self._grammar.currentError else: try: extra, _ = self._grammar.input.head() except EOFError: return ret else: # problem is that input remains, so: err = ParseError(err.input, err.position + 1, [["message", "expected EOF"]], err.trail) raise err
def __init__(self, line, msg, lineNum, colStart, colBound): ParsleyParseError.__init__(self, line, None, msg) self.line = line self.lineNum = lineNum self.colStart = colStart self.colBound = colBound
""" Invoke a Parsley rule. Passes any positional args to the rule. """ try: ret, err = self._grammar.apply(name, *args) except ParseError, e: self._grammar.considerError(e) err = self._grammar.currentError else: try: extra, _ = self._grammar.input.head() except EOFError: return ret else: # problem is that input remains, so: err = ParseError(err.input, err.position + 1, [["message", "expected EOF"]], err.trail) raise err return invokeRule def makeProtocol(source, senderFactory, receiverFactory, bindings=None, name='Grammar'): """ Create a Twisted ``Protocol`` factory from a Parsley grammar. :param source: A grammar, as a string. :param senderFactory: A one-argument callable that takes a twisted
def error(self, typ, val, trail=None): raise ParseError(''.join(self.input.data), typ, val, trail=trail)