expr_parser.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. # Copyright (c) 2016-2018 Rocky Bernstein
  2. """
  3. More complex expression parsing
  4. """
  5. from __future__ import print_function
  6. import sys
  7. from spark_parser.ast import AST
  8. from scanner import ExprScanner
  9. from spark_parser import GenericASTBuilder, DEFAULT_DEBUG
  10. class ExprParser(GenericASTBuilder):
  11. """A more complete expression Parser.
  12. Note: function parse() comes from GenericASTBuilder
  13. """
  14. def __init__(self, debug=DEFAULT_DEBUG):
  15. super(ExprParser, self).__init__(AST, 'expr', debug=debug)
  16. self.debug = debug
  17. def nonterminal(self, nt, args):
  18. has_len = hasattr(args, '__len__')
  19. if (has_len and len(args) == 1 and
  20. hasattr(args[0], '__len__') and len(args[0]) == 1):
  21. # Remove singleton derivations
  22. rv = GenericASTBuilder.nonterminal(self, nt, args[0])
  23. del args[0] # save memory
  24. else:
  25. rv = GenericASTBuilder.nonterminal(self, nt, args)
  26. return rv
  27. ##########################################################
  28. # Expression grammar rules. Grammar rule functions
  29. # start with the name p_ and are collected automatically
  30. ##########################################################
  31. def p_expr(self, args):
  32. '''
  33. expr ::= expr BOOL_OP term
  34. expr ::= expr SHIFT_OP term
  35. expr ::= term
  36. term ::= term MULT_OP factor
  37. factor ::= term
  38. term ::= term ADD_OP atom
  39. term ::= atom
  40. atom ::= NUMBER
  41. atom ::= LPAREN expr RPAREN
  42. '''
  43. def parse_expr(python_str, out=sys.stdout,
  44. show_tokens=False, parser_debug=DEFAULT_DEBUG):
  45. assert isinstance(python_str, str)
  46. tokens = ExprScanner().tokenize(python_str)
  47. if show_tokens:
  48. for t in tokens:
  49. print(t)
  50. # Some kinds of parsing debugging options you might want to consider...
  51. #
  52. # The most verbose debugging::
  53. # parser_debug = {'rules': True,
  54. # 'transition': True,
  55. # 'reduce' : True,
  56. # 'dups': True
  57. # }
  58. #
  59. # The kind of debugging I generally use:
  60. # parser_debug = {'rules': False,
  61. # 'transition': False,
  62. # 'reduce' : True, # show grammar rule reductions
  63. # 'dups': True
  64. # }
  65. parser = ExprParser(parser_debug)
  66. parser.check_grammar()
  67. return parser.parse(tokens)
  68. if __name__ == '__main__':
  69. if len(sys.argv) == 1:
  70. expression = "(1 + 3)/2"
  71. else:
  72. expression = " ".join(sys.argv[1:])
  73. ast = parse_expr(expression, show_tokens=True)
  74. print(ast)