1.介绍
本系列文章参照该教程学习总结,欢迎查看原文。我个人的学习代码已经放到我的github
词法分析、语法分析、语义分析等定义请参考编译器解释器中的词法分析、语法分析、语义分析
2. 更多的AST
本节作者继续深化前一章的内容,增加一些一元操作。
这里再来复习下一元操作符和二元操作符的概念:
- 一元运算符:一元运算符只对一个表达式执行操作,该表达式可以是数值数据类型类别中的任何一种数据类型。例如一元的 '-'表示对表达式取反
- 二元运算符:二元运算是由两个元素形成第三个元素的一种规则。例如数的加法及乘法;更一般地,由两个集合形成第三个集合的产生方法,或构成规则称为二次运算
一元加减号的例子:
看了以上例子后,我们重新修改文法的规则。这里注意一元运算的优先级比我们之前的二元运算的优先级要高。
之前的文法规则是这样的:
现在的文法规则是:
从这个规则可以看出来,在这条产生式的右端(主体部分)增加了一元运算符的判断。这个判断需要放在其他INTEGER等基本表达式的前面优先判断。这里在主体中又引入了factor规则本身,用于递归。这样可以表达类似”----2“ 这样的表达式
完整的文法规则如下所示:
3. 修改代码
根据之前修改后得到的文法,我们需要引入更多的ASTNode类,在这里试一元运算符
class UnaryOp(AST):
def __init__(self, op, expr):
self.token = self.op = op
self.expr = expr
此外根据文法,我们还要修改factor这条规则:
def factor(self):
"""factor : (PLUS | MINUS) factor | INTEGER | LPAREN expr RPAREN"""
token = self.current_token
if token.type == PLUS:
self.eat(PLUS)
node = UnaryOp(token, self.factor())
return node
elif token.type == MINUS:
self.eat(MINUS)
node = UnaryOp(token, self.factor())
return node
elif token.type == INTEGER:
self.eat(INTEGER)
return Num(token)
elif token.type == LPAREN:
self.eat(LPAREN)
node = self.expr()
self.eat(RPAREN)
return node
同样的,我们也需要增加相应访问节点的方法:
def visit_UnaryOp(self, node):
op = node.op.type
if op == PLUS:
return +self.visit(node.expr)
elif op == MINUS:
return -self.visit(node.expr)