![[编程原理]用python实现parser](http://pic.xiahunao.cn/yaotu/[编程原理]用python实现parser)
按你的要求statement 里使用 readprint_stmt 里使用 depth。全文如下[编程原理]用python实现parser在本文中 我将会分享我自己是实现一个基础parser的方法在此之前 你需要实现classToken:def__init__(self,ttype,value):self.ttypettype self.valuevalue#不安全匹配 会对检查自己的type和value是不是任意一边都相同defmatch(self,target):return(self.ttypetarget)or(self.valuetarget)classTokenizer:def__init__(self,text,keyword,op):...deftokenizer(self):...tokenizer负责分割字符串 token则最为token的容器为了本篇篇幅限制暂且不展示Parser实现我们需要一个parser类classParser:...在init中 我们需要获取由tokenizer解析出来的tokendef__init__(self,tokens):self.idx0self.tokenstokens我们需要一个函数来方便的获取当前tokendefnow(self):returnself.tokens[self.idx]然后我们需要一个函数来查看下一个tokendefpeek(self):ifself.idxlen(self.tokens)-1:returnself.tokens[self.idx1]为了方便 我们需要一个函数将推进进度和返回token封装在一起defadvance(self):aself.now()self.idx1returna为了方便 我们需要一个函数来快速对当前语句进行判断我们是不是遇到了语句defread(self,started,end):#注意 read本身只是进行判断 并不会进行advancenowself.now()peekself.peek()returnnow.match(started)orpeek.match(end)工具都已经基本实现完了 我们要开始设计语法了为了方便 我们设计只设计一种语句 (print_stmt)PrintStmt: ‘print’ ‘(’ id ‘)’我们开始进入正题 开始实现对print语法的解析defprint_stmt(self):#我们将在程序入口检测到语句就吃掉print#我们在程序入口检测到语句就吃掉print#我们将会使用depth方法body[]depth0# 吃掉 printself.advance()# 使用 depth 解析括号内的内容whileself.idxlen(self.tokens):tokself.now()iftok.match(():depth1self.advance()continueiftok.match()):depth-1self.advance()ifdepth0:breakcontinueifdepth0:body.append(self.advance().value)else:breakreturn(print_stmt,body)到这里 print_stmt 的解析就完成了它返回一个元组第一个元素是节点类型第二个元素是语句体内容。接下来我们需要一个统一的语句分发入口根据当前 token 来判断进入哪个解析函数defstatement(self):# 使用 read 判断是否遇到 print 语句ifself.read(print,)):returnself.print_stmt()raiseSyntaxError(fUnknown statement:{self.now().value})最后我们需要一个程序入口不断解析语句直到 token 耗尽defparse(self):body[]whileself.idxlen(self.tokens):body.append(self.statement())return(program,body)至此一个最基础的 parser 就实现完成了。使用方式大致如下tokensTokenizer(print(x),keywords,ops).tokenizer()parserParser(tokens)astparser.parse()print(ast)# 输出: (program, [(print_stmt, [x])])总结一下整个流程Tokenizer 负责把源代码字符串切分成一个个 Token。Parser 拿到 Token 列表后通过 now / peek / advance / read 这些工具函数在 Token 流中移动。statement 里用 read 做语句分发print_stmt 里用 depth 处理括号。用 parse 做整体入口最终生成 AST抽象语法树。这只是一个最小的实现。真实的 parser 还需要处理· 表达式解析加减乘除、优先级· 嵌套语句if / while / 函数定义· 错误恢复· 运算符优先级与结合性但核心思想是一样的用游标在 Token 流上移动用递归下降的方式逐层匹配语法规则。