当前位置: 首页 > news >正文

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 = textself.pos = 0self.current_char = self.text[self.pos] if self.pos < len(self.text) else Nonedef error(self):raise Exception('Invalid character')def advance(self):self.pos += 1if self.pos < len(self.text):self.current_char = self.text[self.pos]else:self.current_char = Nonedef 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_charself.advance()return int(result)def get_next_token(self):while self.current_char is not None:if self.current_char.isspace():self.skip_whitespace()continueif 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_charself.advance()return Token(TOKEN_VARIABLE, var_name)self.error()return Token(TOKEN_EOF, None)# 词法单元类
class Token:def __init__(self, type, value):self.type = typeself.value = valuedef __str__(self):return f'Token({self.type}, {repr(self.value)})'# 抽象语法树节点类
class AST:passclass BinOp(AST):def __init__(self, left, op, right):self.left = leftself.op = opself.right = rightclass Num(AST):def __init__(self, token):self.token = tokenself.value = token.valueclass Assign(AST):def __init__(self, left, op, right):self.left = leftself.token = self.op = opself.right = rightclass Var(AST):def __init__(self, token):self.token = tokenself.value = token.value# 语法分析器
class Parser:def __init__(self, lexer):self.lexer = lexerself.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_tokenif 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_tokenif 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 nodedef expr(self):node = self.term()while self.current_token.type in (TOKEN_PLUS, TOKEN_MINUS):token = self.current_tokenif 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 nodedef assignment_statement(self):left = Var(self.current_token)self.eat(TOKEN_VARIABLE)token = self.current_tokenself.eat(TOKEN_ASSIGN)right = self.expr()node = Assign(left, token, right)return nodedef 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 = parserself.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.valuedef visit_Assign(self, node):var_name = node.left.valuevar_value = self.visit(node.right)self.GLOBAL_SCOPE[var_name] = var_valuereturn var_valuedef visit_Var(self, node):var_name = node.valueval = self.GLOBAL_SCOPE.get(var_name)if val is None:raise Exception(f'Variable {var_name} is not defined')else:return valdef interpret(self):tree = self.parser.parse()if tree is None:return ''return self.visit(tree)# 主函数
def main():while True:try:text = input('>> ')except EOFError:breakif not text:continuelexer = 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 特性的支持。
http://www.xdnf.cn/news/249031.html

相关文章:

  • C++的基础知识(引用、类、封装、继承、多态、函数重载)
  • 驱动读写实验
  • GRPO:利用组内平均奖励来计算优势
  • 蓝桥杯Python案例
  • 计算机组成原理实验(5) 堆栈寄存器实验
  • 2025五一杯数学建模ABC题赛题已出
  • ctfshow web入门 web44
  • Python学习笔记(第一部分)
  • 基于深度学习的人脸属性识别算法研究
  • 随机森林实战:从原理到垃圾邮件分类
  • 超稳定性理论
  • 第十四章:生产之路:LLM 应用部署、运维与优化
  • MOOS-ivp使用(一)——水下机器人系统的入门与使用
  • 【2025最新面经】暑期实习常问知识点
  • 前端面经 4
  • 【C++学习笔记】深入理解虚函数和多态
  • 简单句练习--语法基础
  • 50、【OS】【Nuttx】【OSTest】参数解析:函数定义
  • 当算力遇上堵车:AI如何让城市血管不再“血栓”?
  • OpenStack Yoga版安装笔记(25)Nova Cell理解
  • 黑马Java基础笔记-6
  • 伽利略如何测量光速?一场跨越山头的失败实验
  • VBA数据结构深度解析:基础类型、自定义类型与数组操作指南
  • Dagster资产工厂实战:从Python到YAML配置的高效ETL流程
  • 408真题笔记
  • 第十三章:LLM 应用质量保证:评估体系、工具与实战
  • 深入解析三大查找算法:线性查找、二分查找与哈希查找的原理与应用
  • 进程(Process)和操作系统(Operation System)
  • ctfshow web入门 web46
  • 用spring-boot-maven-plugin打包成单个jar有哪些缺点优化方案