Want more features on Pastebin? Sign Up, it's FREE!
Guest

Eike Welk

By: a guest on Sep 6th, 2008  |  syntax: Python  |  size: 4.23 KB  |  views: 39  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
This paste has a previous version, view the difference. Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #
  2. # simpleArith.py
  3. #
  4. # Example of defining an arithmetic expression parser using
  5. # the operatorGrammar helper method in pyparsing.
  6. #
  7. # Copyright 2006, by Paul McGuire
  8. #
  9.  
  10. from pyparsing import *
  11. ParserElement.enablePackrat() #comment this out once for comparison
  12.  
  13.  
  14. # To use the operatorGrammar helper:
  15. #   1.  Define the "atom" operand term of the grammar.
  16. #       For this simple grammar, the smallest operand is either
  17. #       and integer or a variable.  This will be the first argument
  18. #       to the operatorGrammar method.
  19. #   2.  Define a list of tuples for each level of operator
  20. #       precedence.  Each tuple is of the form
  21. #       (opExpr, numTerms, rightLeftAssoc, parseAction), where
  22. #       - opExpr is the pyparsing expression for the operator;
  23. #          may also be a string, which will be converted to a Literal
  24. #       - numTerms is the number of terms for this operator (must
  25. #          be 1 or 2)
  26. #       - rightLeftAssoc is the indicator whether the operator is
  27. #          right or left associative, using the pyparsing-defined
  28. #          constants opAssoc.RIGHT and opAssoc.LEFT.
  29. #       - parseAction is the parse action to be associated with
  30. #          expressions matching this operator expression (the
  31. #          parse action tuple member may be omitted)
  32. #   3.  Call operatorGrammar passing the operand expression and
  33. #       the operator precedence list, and save the returned value
  34. #       as the generated pyparsing expression.  You can then use
  35. #       this expression to parse input strings, or incorporate it
  36. #       into a larger, more complex grammar.
  37. #
  38.  
  39.  
  40. #dummy parse actions
  41. def action_op_prefix(s, loc, toks):
  42. #    print "pre: ",  toks
  43.     return
  44.  
  45. def action_op_infix(s, loc, toks):
  46. #    print "in : ",  toks
  47.     return
  48.  
  49. def action_op_infix_left(s, loc, toks):
  50. #    print "inL: ",  toks
  51.     return
  52.  
  53.  
  54. #The leaf nodes of the parse tree: integer numbers and variable names
  55. integer = Word(nums).setParseAction(lambda t:int(t[0]))
  56. variable = (NotAny(Keyword('not') | Keyword('and') | Keyword('or')) +
  57.             Word(alphas,exact=1))
  58.  
  59. #Let parentheses work with power and unary '-' too
  60. expression = Forward()
  61. primary = integer | variable | Suppress('(') + expression + Suppress(')')
  62.  
  63. #Power and unary operations are intertwined to get correct operator precedence:
  64. #   -a**-b == -(a ** (-b))
  65. power,  u_expr = Forward(), Forward()
  66. #Exponentiation: a**b;
  67. #Strongest binding on left side, weaker than unary operations (-a) on right side.
  68. power1 = Group(primary + '**' + u_expr)          .setParseAction(action_op_infix)
  69. power << (power1 | primary)
  70. #Unary arithmetic operations: -a; +a
  71. u_expr1 = Group(oneOf('- +') + u_expr)           .setParseAction(action_op_prefix)
  72. u_expr << (u_expr1 | power)
  73.  
  74. #All other operators are defined here. Those with the strongest binding come first.
  75. expression << operatorPrecedence( u_expr,
  76.     [(oneOf('* /'),   2, opAssoc.LEFT,           action_op_infix_left),
  77.      (oneOf('+ -'),   2, opAssoc.LEFT,           action_op_infix_left),
  78.      (oneOf('< > <= >= == !='), 2, opAssoc.LEFT, action_op_infix_left),
  79.      (Keyword('not'), 1, opAssoc.RIGHT,          action_op_prefix),
  80.      (Keyword('and'), 2, opAssoc.LEFT,           action_op_infix_left),
  81.      (Keyword('or'),  2, opAssoc.LEFT,           action_op_infix_left),
  82.      ])
  83.  
  84. test = [
  85.         "1**2**3**4",
  86.         "-2**-3 == -(2**(-3))", #why does this expression take so long?
  87.         "3----++-2",
  88.         "1 and 2 or not a and b",
  89.         "not a <= a and c > d",
  90.         "9 + 2 - 3 + 4",
  91.         "9 + 2 * 4",
  92.         "(9 + 2) * 3",
  93.         "(9 + -2) * 3**-4**5",
  94.         "M*X + B",
  95.         "M*(X + B)",
  96. #        "2+3*4-2+3*4-2+3*4**-2**+3*4-2+3*4 and -2+3*4-2+3*4 or -2+3*4**-2**+3*4**-2**+3*4\
  97. #         -2+3*4-2+3*4-2+3*4-2+3*4-2+3*4-2 or 3*4-2 and not 3*4*2+3*4-2+3*4-2+3*4**-2**3*4\
  98. #         -2+3*4-2+3*(4-2+3)*4*-2+3*4**-2**+3**4**-2**+3**(4-(2+3)*4-2+3*4-2+3*4-2)+3*4-+3\
  99. #         *4-2+3*4-2+3*4*2+3*4-2+3*4-2+3*4**-2**+3**4**-2 < +3*4-2 or 3**4-2+3*4-2+3*4**-2\
  100. #         **+3**-4**-2*+3*4-2+3*4-2==+3*4 or -2+3*4<-2+3*4-2+3*4-2+3*4-2+3*4+1-2-3-------4"
  101.          ]
  102.  
  103. #test the parser
  104. print
  105. for t in test:
  106.     print t
  107.     print expression.parseString(t)
  108. #    print power.parseString(t)
  109.     print
clone this paste RAW Paste Data