造个轮子--用Python写个编程语言-逻辑运算

@[TOC]

前言

在上一篇文章里面,实现了基本的变量,并且详细地阐述了基本原理,所以的话,这里要实现的就是这个判断,由于架子基本上打好了,后面的操作无法就是确定这个AST的一个执行顺序,也就是我们希望解释器执行的一个情况。

那么这里要实现的效果是这样的: 在这里插入图片描述

这里的实现的话,就比较简单了,如果前面理解的话,只是多了些操作的东西而已。

关键词

那么老规矩,我们需要先来定义我们的关键词。

先定义我们的类型,和合法的字符:


TT_INT = "整数"
TT_FLOAT = "浮点数"
TT_PLUS = "加号"
TT_DIV = "除号"
TT_MINUS = "减号"
TT_LPAREN = "左括号"
TT_RPAREN = "右括号"
TT_POW	= '次幂'
TT_MUL = "乘"
TT_EOF = 'EOF'
TT_IDENTIFIER = '设'
TT_KEYWORD = '关键字'
TT_EQ = '赋值'
TT_EE = '等于'
TT_NE = '不等于'
TT_LT = '小于'
TT_GT = '大于'
TT_LTE = '小于等于'
TT_GTE = '大于等于'
KEYWORDS = [
    '设',
    '且',
    '或',
    '否'

]

在这里插入图片描述

解析token

之后的话,是解析我们的token,这里的话,完全是老规矩。 在这里插入图片描述

主要是这里,我们有>=,<=这种字符,我们要进行处理

那么这块的话,主要是这几个方法:

    def make_not_equals(self):
        pos_start = self.pos.copy()
        self.advance()

        if self.current_char == '=':
            self.advance()
            return Token(TT_NE, pos_start=pos_start, pos_end=self.pos), None

        self.advance()
        return None, ExpectedCharError(pos_start, self.pos, "'=' (after '!')")

    def make_equals(self):
        tok_type = TT_EQ
        pos_start = self.pos.copy()
        self.advance()

        if self.current_char == '=':
            self.advance()
            tok_type = TT_EE

        return Token(tok_type, pos_start=pos_start, pos_end=self.pos)

    def make_less_than(self):
        tok_type = TT_LT
        pos_start = self.pos.copy()
        self.advance()

        if self.current_char == '=':
            self.advance()
            tok_type = TT_LTE

        return Token(tok_type, pos_start=pos_start, pos_end=self.pos)

    def make_greater_than(self):
        tok_type = TT_GT
        pos_start = self.pos.copy()
        self.advance()

        if self.current_char == '=':
            self.advance()
            tok_type = TT_GTE

        return Token(tok_type, pos_start=pos_start, pos_end=self.pos)

通过这几个方法我们就可以实现这个效果。完成<=,>=这样的关键字的Token的生成

解析器

之后的话,就是我们的语法解析器了。

在这里的话,核心代码的修改主要在这块:

这块的话,前面重复过多次了,就不重复说明了。

  def arith_expr(self):
        return self.bin_op(self.term, (TT_PLUS, TT_MINUS))

    def comp_expr(self):
        res = ParseResult()

        if self.current_tok.matches(TT_KEYWORD, '否'):
            op_tok = self.current_tok
            res.register_advancement()
            self.advance()

            node = res.register(self.comp_expr())
            if res.error: return res
            return res.success(UnaryOpNode(op_tok, node))

        node = res.register(self.bin_op(self.arith_expr, (TT_EE, TT_NE, TT_LT, TT_GT, TT_LTE, TT_GTE)))

        if res.error:
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                "Expected int, float, identifier, '+', '-', '(' or 'NOT'"
            ))

        return res.success(node)

    def expr(self):
        res = ParseResult()

        if self.current_tok.matches(TT_KEYWORD, '设'):
            res.register_advancement()
            self.advance()

            if self.current_tok.type != TT_IDENTIFIER:
                return res.failure(InvalidSyntaxError(
                    self.current_tok.pos_start, self.current_tok.pos_end,
                    "Expected identifier"
                ))

            var_name = self.current_tok
            res.register_advancement()
            self.advance()

            if self.current_tok.type != TT_EQ:
                return res.failure(InvalidSyntaxError(
                    self.current_tok.pos_start, self.current_tok.pos_end,
                    "Expected '='"
                ))

            res.register_advancement()
            self.advance()
            expr = res.register(self.expr())
            if res.error: return res
            return res.success(VarAssignNode(var_name, expr))

        node = res.register(self.bin_op(self.comp_expr, ((TT_KEYWORD, '且'), (TT_KEYWORD, '或'))))

        if res.error:
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                "Expected 'VAR', int, float, identifier, '+', '-', '(' or 'NOT'"
            ))

        return res.success(node)

解释器

最后是我们的解释器。在这里我们需要为这种新加如的节点进行处理,所以核心是加入新的处理函数。

    def get_comparison_eq(self, other):
        if isinstance(other, Number):
            return Number(int(self.value == other.value)).set_context(self.context), None

    def get_comparison_ne(self, other):
        if isinstance(other, Number):
            return Number(int(self.value != other.value)).set_context(self.context), None

    def get_comparison_lt(self, other):
        if isinstance(other, Number):
            return Number(int(self.value < other.value)).set_context(self.context), None

    def get_comparison_gt(self, other):
        if isinstance(other, Number):
            return Number(int(self.value > other.value)).set_context(self.context), None

    def get_comparison_lte(self, other):
        if isinstance(other, Number):
            return Number(int(self.value <= other.value)).set_context(self.context), None

    def get_comparison_gte(self, other):
        if isinstance(other, Number):
            return Number(int(self.value >= other.value)).set_context(self.context), None

    def anded_by(self, other):
        if isinstance(other, Number):
            return Number(int(self.value and other.value)).set_context(self.context), None

    def ored_by(self, other):
        if isinstance(other, Number):
            return Number(int(self.value or other.value)).set_context(self.context), None

    def notted(self):
        return Number(1 if self.value == 0 else 0).set_context(self.context), None

    def copy(self):
        copy = Number(self.value)
        copy.set_pos(self.pos_start, self.pos_end)
        copy.set_context(self.context)
        return copy

那么在这里的话,我们就完成了基本这个逻辑运算了。因为核心的原理我们已经说清楚了,我们所有的代码基本上就是为指定的语法规则服务。比较核心的在这里,其实是AST的构建,而AST核心的是对语法规则的构建定义。这影响到你的代码到底如何执行递归,递归执行的顺序到底是怎么样的。

语法表示

所以在这块的话,我们现在来看到最新的语法表示:

expr		: KEYWORD:VAR IDENTIFIER EQ expr
			: comp-expr ((KEYWORD:AND|KEYWORD:OR) comp-expr)*

comp-expr	: NOT comp-expr
			: arith-expr ((EE|LT|GT|LTE|GTE) arith-expr)*

arith-expr	: term ((PLUS|MINUS) term)*

term		: factor ((MUL|DIV) factor)*

factor		: (PLUS|MINUS) factor
			: power

power		: atom (POW factor)*

atom 		: INT|FLOAT|IDENTIFIER
			: LPAREN expr RPAREN

全部评论

相关推荐

不愿透露姓名的神秘牛友
昨天 10:46
点赞 评论 收藏
分享
头像
11-06 10:58
已编辑
门头沟学院 嵌入式工程师
双非25想找富婆不想打工:哦,这该死的伦敦腔,我敢打赌,你简直是个天才,如果我有offer的话,我一定用offer狠狠的打在你的脸上
点赞 评论 收藏
分享
头像
11-26 15:46
已编辑
中南大学 后端
字节国际 电商后端 24k-35k
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务