闪电龟龟--笔记

万物寻其根,通其堵,便能解其困。
  博客园  :: 新随笔  :: 管理
import re
import collections
# 写将要匹配的正则
NUM = r'(?P<NUM>\d+)'
PLUS = r'(?P<PLUS>\+)'
MINUS = r'(?P<MINUS>-)'
TIMES = r'(?P<TIMES>\*)'
DIVIDE = r'(?P<DIVIDE>/)'
LPAREN = r'(?P<LPAREN>\()'
RPAREN = r'(?P<RPAREN>\))'
WS = r'(?P<WS>\s+)'
# 构建compile()对象
master_pat = re.compile('|'.join([NUM, PLUS, MINUS, TIMES, DIVIDE, LPAREN, RPAREN, WS]))

# 构建一个生成器
def gennerate_tokens(text):
    Token = collections.namedtuple('Token', ['type', 'value'])  # 构建一个元组
    scanner = master_pat.scanner(text)  # 创建scanner()对象
    # 进行扫描
    for m in iter(scanner.match, None):
        tok = Token(m.lastgroup, m.group())  # 添加元组
        if tok.type != 'WS':
            yield tok

class ExpressionEvaluator(object):
    def parse(self, text):
        self.tokens = gennerate_tokens(text)
        self.tok = None
        self.nexttok = None
        self._advance()
        return self.expr()
    def _advance(self):
        # 进行往下移动
        self.tok, self.nexttok = self.nexttok, next(self.tokens, None)
    def _accept(self, toktype):
        # 判断下一个节点的类型是否正确
        if self.nexttok and self.nexttok.type == toktype:
            self._advance()  # 如果节点类型正确,那么就往下一个节点
            return True
        else:
            return False
    def _except(self, toktype):
        # 用来判断是否是理想环境(如括号是否封闭)
        if not self._accept(toktype):
            raise SyntaxError('Excepted' + toktype)
    def expr(self):
        """ 进行加减操作 """
        exprval = self.term()
        while self._accept('PLUS') or self._accept('MINUS'):
            op = self.tok.type  # 获取当前操作类型
            right = self.term()  # 先计算右边部分
            if op == 'PLUS':
                exprval += right
            elif op == 'MINUS':
                exprval -= right
        return exprval
    def term(self):
        """ 进行乘除操作 """
        termval = self.factor()
        while self._accept('TIMES') or self._accept('DIVIDE'):
            op = self.tok.type  # 获取当前操作
            right = self.factor()  # 计算右边部分
            if op == 'TIMES':
                termval *= right
            elif op == 'DIVIDE':
                termval /= right
        return termval
    def factor(self):
        if self._accept('NUM'):
            return int(self.tok.value)
        elif self._accept('LPAREN'):
            exprval = self.expr()
            self._except('RPAREN')
            return exprval
        else:
            raise SyntaxError("Excepted NUMBER or LPAREN...")

def descent_parser():
    e = ExpressionEvaluator()
    print(e.parse('2'))
    print(e.parse('2 + 3'))
    print(e.parse('2 - 3'))
    print(e.parse('2 + 3 * 5'))
    print(e.parse('4 - 6 / 2'))
    print(e.parse('2 + (3 + 1)/2'))

# 入口函数
if __name__ == "__main__":
    descent_parser()
"""
D:\笔记\python电子书\Python3>python index.py
2
5
-1
17
1.0
4.0
"""