1. #!/usr/bin/env python                            
  2.  
  3. from pyparsing import *
  4.  
  5. class MyFatalException(Exception):
  6.     def __init__(self, s, loc, msg):
  7.         Exception.__init__(self, msg)
  8.         self.s = s
  9.         self.loc = loc
  10.  
  11. def validate_number(s, loc, tokens):
  12.     if int(tokens[0]) != 0:
  13.         raise ParseFatalException(s, loc, "number musth be 0")
  14.  
  15. def fail(s, loc, tokens):
  16.     raise ParseFatalException(s, loc, "Unknown token %s" % tokens[0])
  17.  
  18. def fail_value(s, loc, expr, err):
  19. #    print "In fail_value..."
  20. #    raise ParseFatalException(s, loc, "Number expected")
  21.     raise MyFatalException(s, loc, "Number expected")
  22.  
  23. number =  Word(nums).setParseAction(validate_number).setFailAction(fail_value)
  24. operator = Literal("=")
  25.  
  26. error = Word(alphas).setParseAction(fail)
  27. rules = MatchFirst([
  28.     Literal('x') - operator - number,
  29.     error
  30.     ])
  31.  
  32. expr = operatorPrecedence(rules, [
  33.     (Literal("and"), 2, opAssoc.RIGHT),
  34.     ])
  35.  
  36.  
  37. def try_parse(program):
  38.     try:
  39.         res = expr.parseString(program, parseAll=True)
  40.         print res
  41.     except (ParseException, ParseFatalException, MyFatalException) as e:
  42.         msg = str(e)
  43.         print("%s: %s" % (msg, program))
  44.         print(" " * (len("%s: " % msg) + (e.loc)) + "^^^")
  45.  
  46.  
  47. def main():
  48.     print "Correct code"
  49.     try_parse("x = 0")
  50.     try_parse("x = 0 and x = 0")
  51.     try_parse("x = 0 and (x = 0 and (x = 0 and (x = 0)))")
  52.  
  53.     print "Good errors"
  54.     try_parse("x = 1")
  55.     try_parse("x + 0")
  56.     try_parse("x = a")
  57.     try_parse("x = a and x = 0")
  58.     try_parse("x = 0 and x = 1")
  59.     try_parse("x = 0 and x = a")
  60.     try_parse("x = 0 and foo = 0")
  61.     try_parse("x = 0 and (x = 0 and (x = 0 and (x = a)))")
  62.  
  63.     print "Bad errors"
  64.     try_parse("x = 0 and x + 0")
  65.  
  66.  
  67. main()