如何写一个简单的解释器(Interpreter)-8

今天的主要话题是单目运算符。具体来说:

  • 扩充现有的语法,处理单目运算加和单目运算减。
  • 增加一个新的UnaryOp AST节点类。
  • 扩充现有的解析器,生成包含UnaryOp AST节点的树形结构。
  • 扩充现有的解释器,增加一个visit_UnaryOp方法,来解析单目运算农夫。

单目运算符就是只有有个操作数的操作码,优先级比+, -, *, /要高。可以简单理解为正负号就对了。

 

我们更新一下factor规则如下,注意单目运算符优先级比四则运算要高。

factor规则经过扩展后,允许调用自己,这样就可以允许支持像- - - + - 3这种表达式了。

这是完整的语法:

转换为代码就是:

class UnaryOp(AST):
    def __init__(self, op, expr):
        self.token = self.op = op
        self.expr = expr

构造函数接受两个参数。op代表运算符的token,也就是加和减。expr代表一个AST节点。

我们升级的规则改为了factor规则,解析器中的factor方法也会改变。我们会给factor方法增加一下代码去处理“(PLUS | MINUS) 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


Interpreter 类也要扩展一个方法 visit_UnaryOp ,用来解析单独操作符。

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)

拿“5 - - - 2” 试试我们新的解释器。用Python命令行就可以。

>>> from spi import BinOp, UnaryOp, Num, MINUS, INTEGER, Token
>>> five_tok = Token(INTEGER, 5)
>>> two_tok = Token(INTEGER, 2)
>>> minus_tok = Token(MINUS, '-')
>>> expr_node = BinOp(
...     Num(five_tok),
...     minus_tok,
...     UnaryOp(minus_token, UnaryOp(minus_token, Num(two_tok)))
... )
>>> from spi import Interpreter
>>> inter = Interpreter(None)
>>> inter.visit(expr_node)
3

运行试试:

$ python spi.py
spi> - 3
-3
spi> + 3
3
spi> 5 - - - + - 3
8
spi> 5 - - - + - (3 + 4) - +2
10

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值