#!/usr/bin/env python
from pyparsing import *
class MyFatalException(Exception):
def __init__(self, s, loc, msg):
Exception.__init__(self, msg)
self.s = s
self.loc = loc
def validate_number(s, loc, tokens):
if int(tokens[0]) != 0:
raise ParseFatalException(s, loc, "number musth be 0")
def fail(s, loc, tokens):
raise ParseFatalException(s, loc, "Unknown token %s" % tokens[0])
def fail_value(s, loc, expr, err):
# print "In fail_value..."
# raise ParseFatalException(s, loc, "Number expected")
raise MyFatalException(s, loc, "Number expected")
number = Word(nums).setParseAction(validate_number).setFailAction(fail_value)
operator = Literal("=")
error = Word(alphas).setParseAction(fail)
rules = MatchFirst([
Literal('x') - operator - number,
error
])
expr = operatorPrecedence(rules, [
(Literal("and"), 2, opAssoc.RIGHT),
])
def try_parse(program):
try:
res = expr.parseString(program, parseAll=True)
print res
except (ParseException, ParseFatalException, MyFatalException) as e:
msg = str(e)
print("%s: %s" % (msg, program))
print(" " * (len("%s: " % msg) + (e.loc)) + "^^^")
def main():
print "Correct code"
try_parse("x = 0")
try_parse("x = 0 and x = 0")
try_parse("x = 0 and (x = 0 and (x = 0 and (x = 0)))")
print "Good errors"
try_parse("x = 1")
try_parse("x + 0")
try_parse("x = a")
try_parse("x = a and x = 0")
try_parse("x = 0 and x = 1")
try_parse("x = 0 and x = a")
try_parse("x = 0 and foo = 0")
try_parse("x = 0 and (x = 0 and (x = 0 and (x = a)))")
print "Bad errors"
try_parse("x = 0 and x + 0")
main()