Antlr4实现计算器程序

本文介绍使用Antlr4实现一个支持四则运算的程序,关于Antlr4的安装可以参考上一篇文章。

工具:Intellij IDEA + antlr4 plugin

1. 编辑antlr4的语法文件

grammar LabelExpr;
/** 起始规则 语法分析器起点 */
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
    ;

ID      : [a-zA-Z]+ ;   // 匹配标识符
INT     : [0-9]+ ;      // 匹配整数
NEWLINE : '\r'? '\n' ;     // 新行 即语句终止标志
WS      : [ \t]+ -> skip ; // 丢弃空白字符

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

在IDEA中可以直接使用ANTLR Preview窗口测试语法文件是否正确

然后生成Java的解析代码,继承其中的额LabelExprBaseVisitor类,实现处理逻辑

package labelExpr;

import java.util.HashMap;
import java.util.Map;

public class MyEvalVisitor extends LabelExprBaseVisitor<Integer> {

    /**
     * 保存运行中的结果
     */
    Map<String, Integer> memory = new HashMap<>();

    @Override
    public Integer visitAssign(LabelExprParser.AssignContext ctx) {
        String id = ctx.ID().getText();
        int value = visit(ctx.expr());
        memory.put(id, value);
        return value;
    }

    @Override
    public Integer visitPrintExpr(LabelExprParser.PrintExprContext ctx) {
        Integer value = visit(ctx.expr());
        System.out.println(value);
        return 0;
    }

    @Override
    public Integer visitInt(LabelExprParser.IntContext ctx) {
        return Integer.valueOf(ctx.INT().getText());
    }

    @Override
    public Integer visitId(LabelExprParser.IdContext ctx) {
        String id = ctx.ID().getText();
        if (memory.containsKey(id)) {
            return memory.get(id);
        }
        return 0;
    }

    @Override
    public Integer visitMulDiv(LabelExprParser.MulDivContext ctx) {
        int left = visit(ctx.expr(0));
        int right = visit(ctx.expr(1));
        if (ctx.op.getType() == LabelExprParser.MUL) {
            return left * right;
        } else {
            return left / right;
        }
    }

    @Override
    public Integer visitAddSub(LabelExprParser.AddSubContext ctx) {
        int left = visit(ctx.expr(0));
        int right = visit(ctx.expr(1));
        if (ctx.op.getType() == LabelExprParser.Add) {
            return left + right;
        } else {
            return left - right;
        }
    }

    @Override
    public Integer visitParens(LabelExprParser.ParensContext ctx) {
        return visit(ctx.expr());
    }
}

测试内容如下:

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

下面是测试代码和结果

package labelExpr;

import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;

import java.io.IOException;
import java.io.InputStream;

public class Main {

    public static void main(String[] args) throws IOException {
        InputStream is = Main.class.getClassLoader().getResourceAsStream("expr1.txt");

        LabelExprLexer lexer = new LabelExprLexer(CharStreams.fromStream(is));

        CommonTokenStream tokens = new CommonTokenStream(lexer);

        LabelExprParser parser = new LabelExprParser(tokens);

        ParseTree tree = parser.prog();

        MyEvalVisitor visitor = new MyEvalVisitor();
        visitor.visit(tree);

        is.close();
    }
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ANTLR4是一种强大的语法解析器生成器,它可以用于多种编程语言,包括C。使用ANTLR4,您可以定义自己的语法规则,并生成用于解析和分析C代码的解析器。ANTLR4生成的解析器能够将C代码转换为语法树,从而方便进行各种静态分析、代码转换和代码生成等操作。 使用ANTLR4来解析C代码的基本步骤如下: 1. 定义C语法规则:使用ANTLR4的语法规则定义语法规范,可以参考C语言的语法规范以及相关文档和资料。 2. 生成解析器代码:使用ANTLR4命令行工具将定义好的语法规则文件(通常以.g4为扩展名)作为输入,生成相应的解析器代码。 3. 编写应用程序:使用生成的解析器代码编写应用程序。您可以使用解析器来处理C代码,执行相应的操作,如静态分析、源码转换等。 4. 构建和运行应用程序:将应用程序编译并运行,开始对C代码进行解析和分析。 下面是一些相关问题: 相关问题: 1. 如何定义C语法规则文件? 2. ANTLR4支持哪些其他编程语言? 3. 使用ANTLR4解析C代码时,如何处理错误和异常情况? 4. 可以在ANTLR4中定义和使用自定义标记吗? 5. ANTLR4生成的解析器代码如何集成到现有的C项目中? 6. ANTLR4有哪些高级特性和扩展功能可用于解析C代码? 7. 如何使用ANTLR4生成C代码的抽象语法树(AST)? 8. ANTLR4的性能如何?是否有优化选项可用? 请注意,由于回答的长度限制,我可能无法一次回答所有

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值