fork download
  1. import pyparsing as pp
  2.  
  3. # works with and without packrat
  4. pp.ParserElement.enablePackrat()
  5.  
  6. pp.ParserElement.setDefaultWhitespaceChars(' \t')
  7.  
  8. operand = pp.Word(pp.nums)
  9. var = pp.Word(pp.alphas)
  10.  
  11. arith_expr = pp.Forward()
  12. arith_expr.ignore(pp.pythonStyleComment)
  13. lpar = pp.Suppress("(")
  14. rpar = pp.Suppress(")")
  15.  
  16. # code to implement selective ignore of NL's inside ()'s
  17. NL = pp.Suppress("\n")
  18. base_ignore = arith_expr.ignoreExprs[:]
  19. ignore_stack = base_ignore[:]
  20. def lpar_pa():
  21. ignore_stack.append(NL)
  22. arith_expr.ignore(NL)
  23. #~ print('post-push', arith_expr.ignoreExprs)
  24. def rpar_pa():
  25. ignore_stack.pop(-1)
  26. arith_expr.ignore(None)
  27. for e in ignore_stack:
  28. arith_expr.ignore(e)
  29. #~ print('post-pop', arith_expr.ignoreExprs)
  30. def reset_stack(*args):
  31. arith_expr.ignore(None)
  32. for e in base_ignore:
  33. arith_expr.ignore(e)
  34. #~ print('post-reset', arith_expr.ignoreExprs)
  35. lpar.addParseAction(lpar_pa)
  36. rpar.addParseAction(rpar_pa)
  37. arith_expr.setFailAction(reset_stack)
  38. arith_expr.addParseAction(reset_stack)
  39.  
  40. # now define the infix notation as usual
  41. arith_expr <<= pp.infixNotation(operand | var,
  42. [
  43. ("-", 1, pp.opAssoc.RIGHT),
  44. (pp.oneOf("* /"), 2, pp.opAssoc.LEFT),
  45. (pp.oneOf("- +"), 2, pp.opAssoc.LEFT),
  46. ],
  47. lpar=lpar, rpar=rpar
  48. )
  49.  
  50. assignment = var + '=' + arith_expr
  51.  
  52. # Try it out!
  53. assignment.runTests([
  54. """a = 1 + 3""",
  55. """a = (1 + 3)""",
  56. """a = 1 + 2 + (
  57. 3 +
  58. 1)""",
  59. """a = 1 + 2 + ((
  60. 3 +
  61. 1))""",
  62. """a = 1 + 2 +
  63. 3""",
  64. """a = (1 + (2 + 3) +
  65. 4)""",
  66. ], fullDump=False)
Success #stdin #stdout 0.06s 13468KB
stdin
Standard input is empty
stdout
a = 1 + 3
FAIL-EXCEPTION: 'NoneType' object has no attribute 'copy'

a = (1 + 3)
FAIL-EXCEPTION: 'NoneType' object has no attribute 'copy'

a = 1 + 2 + ( 
3 +
1)
FAIL-EXCEPTION: 'NoneType' object has no attribute 'copy'

a = 1 + 2 + (( 
3 +
1))
FAIL-EXCEPTION: 'NoneType' object has no attribute 'copy'

a = 1 + 2 +   
3
FAIL-EXCEPTION: 'NoneType' object has no attribute 'copy'

a = (1 + (2 + 3) +
4)
FAIL-EXCEPTION: 'NoneType' object has no attribute 'copy'