| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- # Copyright (c) 2016-2018 Rocky Bernstein
- """
- More complex expression parsing
- """
- from __future__ import print_function
- import sys
- from spark_parser.ast import AST
- from scanner import ExprScanner
- from spark_parser import GenericASTBuilder, DEFAULT_DEBUG
- class ExprParser(GenericASTBuilder):
- """A more complete expression Parser.
- Note: function parse() comes from GenericASTBuilder
- """
- def __init__(self, debug=DEFAULT_DEBUG):
- super(ExprParser, self).__init__(AST, 'expr', debug=debug)
- self.debug = debug
- def nonterminal(self, nt, args):
- has_len = hasattr(args, '__len__')
- if (has_len and len(args) == 1 and
- hasattr(args[0], '__len__') and len(args[0]) == 1):
- # Remove singleton derivations
- rv = GenericASTBuilder.nonterminal(self, nt, args[0])
- del args[0] # save memory
- else:
- rv = GenericASTBuilder.nonterminal(self, nt, args)
- return rv
- ##########################################################
- # Expression grammar rules. Grammar rule functions
- # start with the name p_ and are collected automatically
- ##########################################################
- def p_expr(self, args):
- '''
- expr ::= expr BOOL_OP term
- expr ::= expr SHIFT_OP term
- expr ::= term
- term ::= term MULT_OP factor
- factor ::= term
- term ::= term ADD_OP atom
- term ::= atom
- atom ::= NUMBER
- atom ::= LPAREN expr RPAREN
- '''
- def parse_expr(python_str, out=sys.stdout,
- show_tokens=False, parser_debug=DEFAULT_DEBUG):
- assert isinstance(python_str, str)
- tokens = ExprScanner().tokenize(python_str)
- if show_tokens:
- for t in tokens:
- print(t)
- # Some kinds of parsing debugging options you might want to consider...
- #
- # The most verbose debugging::
- # parser_debug = {'rules': True,
- # 'transition': True,
- # 'reduce' : True,
- # 'dups': True
- # }
- #
- # The kind of debugging I generally use:
- # parser_debug = {'rules': False,
- # 'transition': False,
- # 'reduce' : True, # show grammar rule reductions
- # 'dups': True
- # }
- parser = ExprParser(parser_debug)
- parser.check_grammar()
- return parser.parse(tokens)
- if __name__ == '__main__':
- if len(sys.argv) == 1:
- expression = "(1 + 3)/2"
- else:
- expression = " ".join(sys.argv[1:])
- ast = parse_expr(expression, show_tokens=True)
- print(ast)
|