Python实例题:Python实现Python解释器

目录

Python实例题

题目

实现思路

代码实现

代码解释

词法分析器(Lexer):

词法单元类(Token):

抽象语法树节点类(AST):

语法分析器(Parser):

解释器(Interpreter):

主函数(main):

运行思路

注意事项

Python实例题

题目

Python实现Python解释器

实现思路

  • 词法分析:将输入的 Python 代码分割成一个个的词法单元(Token),例如数字、运算符、变量名等。
  • 语法分析:根据词法单元构建抽象语法树(AST),表示代码的语法结构。
  • 语义分析与执行:遍历抽象语法树,根据节点的类型执行相应的操作,例如计算算术表达式、进行变量赋值等。

代码实现

# 定义词法单元类型
TOKEN_NUMBER = 'NUMBER'
TOKEN_PLUS = 'PLUS'
TOKEN_MINUS = 'MINUS'
TOKEN_MULTIPLY = 'MULTIPLY'
TOKEN_DIVIDE = 'DIVIDE'
TOKEN_ASSIGN = 'ASSIGN'
TOKEN_VARIABLE = 'VARIABLE'
TOKEN_EOF = 'EOF'


# 词法分析器
class Lexer:
    def __init__(self, text):
        self.text = text
        self.pos = 0
        self.current_char = self.text[self.pos] if self.pos < len(self.text) else None

    def error(self):
        raise Exception('Invalid character')

    def advance(self):
        self.pos += 1
        if self.pos < len(self.text):
            self.current_char = self.text[self.pos]
        else:
            self.current_char = None

    def skip_whitespace(self):
        while self.current_char is not None and self.current_char.isspace():
            self.advance()

    def integer(self):
        result = ''
        while self.current_char is not None and self.current_char.isdigit():
            result += self.current_char
            self.advance()
        return int(result)

    def get_next_token(self):
        while self.current_char is not None:
            if self.current_char.isspace():
                self.skip_whitespace()
                continue

            if self.current_char.isdigit():
                return Token(TOKEN_NUMBER, self.integer())

            if self.current_char == '+':
                self.advance()
                return Token(TOKEN_PLUS, '+')

            if self.current_char == '-':
                self.advance()
                return Token(TOKEN_MINUS, '-')

            if self.current_char == '*':
                self.advance()
                return Token(TOKEN_MULTIPLY, '*')

            if self.current_char == '/':
                self.advance()
                return Token(TOKEN_DIVIDE, '/')

            if self.current_char == '=':
                self.advance()
                return Token(TOKEN_ASSIGN, '=')

            if self.current_char.isalpha():
                var_name = ''
                while self.current_char is not None and (self.current_char.isalnum() or self.current_char == '_'):
                    var_name += self.current_char
                    self.advance()
                return Token(TOKEN_VARIABLE, var_name)

            self.error()

        return Token(TOKEN_EOF, None)


# 词法单元类
class Token:
    def __init__(self, type, value):
        self.type = type
        self.value = value

    def __str__(self):
        return f'Token({self.type}, {repr(self.value)})'


# 抽象语法树节点类
class AST:
    pass


class BinOp(AST):
    def __init__(self, left, op, right):
        self.left = left
        self.op = op
        self.right = right


class Num(AST):
    def __init__(self, token):
        self.token = token
        self.value = token.value


class Assign(AST):
    def __init__(self, left, op, right):
        self.left = left
        self.token = self.op = op
        self.right = right


class Var(AST):
    def __init__(self, token):
        self.token = token
        self.value = token.value


# 语法分析器
class Parser:
    def __init__(self, lexer):
        self.lexer = lexer
        self.current_token = self.lexer.get_next_token()

    def error(self):
        raise Exception('Invalid syntax')

    def eat(self, token_type):
        if self.current_token.type == token_type:
            self.current_token = self.lexer.get_next_token()
        else:
            self.error()

    def factor(self):
        token = self.current_token
        if token.type == TOKEN_NUMBER:
            self.eat(TOKEN_NUMBER)
            return Num(token)
        elif token.type == TOKEN_VARIABLE:
            self.eat(TOKEN_VARIABLE)
            return Var(token)
        elif token.type == TOKEN_PLUS:
            self.eat(TOKEN_PLUS)
            return BinOp(Num(Token(TOKEN_NUMBER, 0)), Token(TOKEN_PLUS, '+'), self.factor())
        elif token.type == TOKEN_MINUS:
            self.eat(TOKEN_MINUS)
            return BinOp(Num(Token(TOKEN_NUMBER, 0)), Token(TOKEN_MINUS, '-'), self.factor())

    def term(self):
        node = self.factor()

        while self.current_token.type in (TOKEN_MULTIPLY, TOKEN_DIVIDE):
            token = self.current_token
            if token.type == TOKEN_MULTIPLY:
                self.eat(TOKEN_MULTIPLY)
            elif token.type == TOKEN_DIVIDE:
                self.eat(TOKEN_DIVIDE)

            node = BinOp(left=node, op=token, right=self.factor())

        return node

    def expr(self):
        node = self.term()

        while self.current_token.type in (TOKEN_PLUS, TOKEN_MINUS):
            token = self.current_token
            if token.type == TOKEN_PLUS:
                self.eat(TOKEN_PLUS)
            elif token.type == TOKEN_MINUS:
                self.eat(TOKEN_MINUS)

            node = BinOp(left=node, op=token, right=self.term())

        return node

    def assignment_statement(self):
        left = Var(self.current_token)
        self.eat(TOKEN_VARIABLE)
        token = self.current_token
        self.eat(TOKEN_ASSIGN)
        right = self.expr()
        node = Assign(left, token, right)
        return node

    def statement(self):
        if self.current_token.type == TOKEN_VARIABLE:
            return self.assignment_statement()
        else:
            return self.expr()

    def parse(self):
        return self.statement()


# 解释器
class Interpreter:
    def __init__(self, parser):
        self.parser = parser
        self.GLOBAL_SCOPE = {}

    def visit(self, node):
        method_name = 'visit_' + type(node).__name__
        visitor = getattr(self, method_name, self.generic_visit)
        return visitor(node)

    def generic_visit(self, node):
        raise Exception(f'No visit_{type(node).__name__} method')

    def visit_BinOp(self, node):
        if node.op.type == TOKEN_PLUS:
            return self.visit(node.left) + self.visit(node.right)
        elif node.op.type == TOKEN_MINUS:
            return self.visit(node.left) - self.visit(node.right)
        elif node.op.type == TOKEN_MULTIPLY:
            return self.visit(node.left) * self.visit(node.right)
        elif node.op.type == TOKEN_DIVIDE:
            return self.visit(node.left) / self.visit(node.right)

    def visit_Num(self, node):
        return node.value

    def visit_Assign(self, node):
        var_name = node.left.value
        var_value = self.visit(node.right)
        self.GLOBAL_SCOPE[var_name] = var_value
        return var_value

    def visit_Var(self, node):
        var_name = node.value
        val = self.GLOBAL_SCOPE.get(var_name)
        if val is None:
            raise Exception(f'Variable {var_name} is not defined')
        else:
            return val

    def interpret(self):
        tree = self.parser.parse()
        if tree is None:
            return ''
        return self.visit(tree)


# 主函数
def main():
    while True:
        try:
            text = input('>> ')
        except EOFError:
            break
        if not text:
            continue

        lexer = Lexer(text)
        parser = Parser(lexer)
        interpreter = Interpreter(parser)
        result = interpreter.interpret()
        print(result)


if __name__ == "__main__":
    main()
    

代码解释

  • 词法分析器(Lexer)

    • Lexer 类将输入的代码字符串分割成一个个的词法单元(Token),根据字符的类型识别出数字、运算符、变量名等。
    • get_next_token 方法根据当前字符的类型返回对应的词法单元。
  • 词法单元类(Token)

    • Token 类表示一个词法单元,包含类型和值两个属性。
  • 抽象语法树节点类(AST)

    • AST 是抽象语法树节点的基类,BinOp 表示二元运算符节点,Num 表示数字节点,Assign 表示赋值语句节点,Var 表示变量节点。
  • 语法分析器(Parser)

    • Parser 类根据词法单元构建抽象语法树,通过递归下降的方法解析代码,处理表达式、赋值语句等。
    • parse 方法返回构建好的抽象语法树。
  • 解释器(Interpreter)

    • Interpreter 类遍历抽象语法树,根据节点的类型执行相应的操作,例如计算算术表达式、进行变量赋值等。
    • visit 方法根据节点类型调用相应的处理方法。
  • 主函数(main)

    • 循环读取用户输入的代码,调用词法分析器、语法分析器和解释器进行处理,并输出结果。

运行思路

  • 保存代码:将上述代码保存为 simple_python_interpreter.py 文件。
  • 运行脚本:在终端中运行 python simple_python_interpreter.py
  • 输入代码:在命令行输入简单的算术表达式或赋值语句,例如 a = 3 + 5a + 2 等,解释器会输出计算结果。

注意事项

  • 功能局限性:这个解释器仅支持基本的算术表达式和赋值语句,不支持 Python 语言的其他复杂特性,如函数定义、类定义、控制流语句等。
  • 错误处理:代码中对一些错误情况进行了简单的处理,但在实际应用中,可能需要更完善的错误处理机制,以提供更友好的错误提示。
  • 扩展性:可以通过扩展抽象语法树节点和解释器的处理方法,逐步添加对更多 Python 特性的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值