zoukankan      html  css  js  c++  java
  • 干货-递归下降分析器 笔记(具体看Python Cookbook, 3rd edition 的2.19章节)

    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
    """
  • 相关阅读:
    HashPasswordForStoringInConfigFile中的Md5算法并非常用的Md5算法
    (转)C#实现MD5加密
    pb将datawindow数据导出EXCEL
    (转)笔记320 SQLSERVER中的加密函数 2013-7-11
    Sqlserver2005附加数据库时出错提示操作系统错误5(拒绝访问)错误5120的解决办法
    PowerDesigner中Name与Code同步的问题
    (转) PowerDesigner中Table视图同时显示Code和Name
    SQLServer2012在登录远程服务器实例时报错:尝试读取或写入受保护的内存
    PB代码动态解析执行器
    XenServer安全重启xapi的方法
  • 原文地址:https://www.cnblogs.com/namejr/p/10004649.html
Copyright © 2011-2022 走看看