(Antlr4 4-1)利用访问器构建一个计算器(Python语言实现)

先来编写一下语法, 并标记备选分支

语法文件

004/LabeledExpr.g4

grammar LabeledExpr;
import CommonLexerRules;

prog
    : stat +
    ;
stat
    : expr NEWLINE              # printExpr
    | ID '=' expr NEWLINE       # assign
    | NEWLINE                   # blank
    ;
expr
    : expr op=('*'|'/') expr       # MulDiv
    | expr op=('+'|'-') expr       # AddSub
    | INT                       # int
    | ID                        # id
    | '(' expr ')'              # parens
    ;

MUL: '*' ;
DIV: '/' ;
ADD: '+' ;
SUB: '-' ;

词法文件

004/CommonLexerRules.g4

lexer grammar CommonLexerRules;

ID: [a-zA-Z]+ ;
INT: [0-9]+ ;
NEWLINE: '\r'? '\n' ;
WS: [ \t]+ -> skip ;

生成词法分析器、语法分析器以及访问器

antlr4vpy3 LabeledExpr.g4

编写自定义的访问器代码

004/EvalVisitor.py

from LabeledExprVisitor import LabeledExprVisitor
from LabeledExprParser import LabeledExprParser


class EvalVisitor(LabeledExprVisitor):
    memory = {}

    def visitAssign(self, ctx: LabeledExprParser.AssignContext):
        id = ctx.ID().getText()
        value = self.visit(ctx.expr())
        self.memory[id] = value
        return value

    def visitPrintExpr(self, ctx:LabeledExprParser.PrintExprContext):
        value = self.visit(ctx.expr())
        print(value)
        return 0

    def visitInt(self, ctx:LabeledExprParser.IntContext):
        return int(ctx.INT().getText())

    def visitId(self, ctx:LabeledExprParser.IdContext):
        id = ctx.ID().getText()
        if id in self.memory:
            return self.memory[id]
        return 0

    def visitMulDiv(self, ctx:LabeledExprParser.MulDivContext):
        left = self.visit(ctx.expr(0))
        right = self.visit(ctx.expr(1))
        if ctx.op.type == LabeledExprParser.MUL:
            return left * right
        return left / right

    def visitAddSub(self, ctx:LabeledExprParser.AddSubContext):
        left = self.visit(ctx.expr(0))
        right = self.visit(ctx.expr(1))
        if ctx.op.type == LabeledExprParser.ADD:
            return left + right
        return left - right

    def visitParens(self, ctx:LabeledExprParser.ParensContext):
        return self.visit(ctx.expr())

编写应用的代码

004/calc.py

import sys
from antlr4 import *
from LabeledExprLexer import LabeledExprLexer
from LabeledExprParser import LabeledExprParser
from EvalVisitor import EvalVisitor

input_ = FileStream(sys.argv[1])
lexer = LabeledExprLexer(input_)
tokens = CommonTokenStream(lexer)
parser = LabeledExprParser(tokens)
tree = parser.prog()
eval = EvalVisitor()
eval.visit(tree)

测试文件

004/t.expr

193
a = 5
b = 6
a+b*2
(1+2)*3

测试

(venv) D:\PythonProjects\learnAntlr\004>python calc.py t.expr
193
17
9

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值