首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ANTLR 4如何处理一元/负数

ANTLR 4如何处理一元/负数
EN

Stack Overflow用户
提问于 2018-02-08 20:55:37
回答 1查看 2.1K关注 0票数 2

我正在尝试用Antlr 4安装一个简单的计算器。

语法:

代码语言:javascript
复制
grammar calcGrammar;
input : expression EOF;
expression :
    MINUS expression #unaryMinusExpr
    | expression op=(MULTIPLY | DIVIDE) expression #multiplicationExpr
    | expression op=(MINUS | ADD) expression #additiveExpr
    | NUMBER #num
    ;

NUMBER : [0-9]+ ;
DOUBLE : NUMBER '.' NUMBER;

LPAR  : '(';
RPAR  : ')';
ADD : ('+');
MINUS : ('-');
DIVIDE : ('/');
MULTIPLY : ('*');

Java代码:

代码语言:javascript
复制
public class Listener extends ListenerBaseVisitor {
@Override
public Object visitUnaryMinusExpr(ArithmeticGrammarParser.UnaryMinusExprContext ctx) {
System.out.println(ctx.children.get(0).getText());
}

    @Override
public Object visitAdditiveExpr(ArithmeticGrammarParser.AdditiveExprContext ctx) {
    System.out.println(ctx.children.get(0).getText());
    System.out.println(ctx.children.get(1).getText());
}

如果我的输入是2-2。使用此输入,代码将永远不会进入此方法。注意输入有一个负的一元运算符,这应该被认为是'-2‘。当我在方法中放置一个调试点时,永远不要进入。

在我的语法设置中,不应该总是首先考虑一元减号吗?

编辑:当实现一元和上瘾的表达式时,似乎会出现此错误。在这种情况下,程序将不会进入一元方法,输入“2--2”。

EN

回答 1

Stack Overflow用户

发布于 2018-02-08 21:10:47

在我的语法设置中,不应该总是首先考虑一元减号吗?

是的,它应该(而且确实)。

我猜您最近没有重新生成解析器和lexer类,因为在我运行这个类时,考虑到您的语法(我只添加了SPACE : [ \t\r\n] -> skip;):

代码语言:javascript
复制
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

public class Main {

    static class Listener extends calcGrammarBaseListener {

        @Override
        public void enterUnaryMinusExpr(calcGrammarParser.UnaryMinusExprContext ctx) {
            System.out.println("enterUnaryMinusExpr: " + ctx.getText());
        }

        @Override
        public void enterAdditiveExpr(calcGrammarParser.AdditiveExprContext ctx) {
            System.out.println("enterAdditiveExpr: " + ctx.getText());
        }
    }

    public static void main(String[] args) {
        String source = "2 - -2";
        calcGrammarLexer lexer = new calcGrammarLexer(CharStreams.fromString(source));
        calcGrammarParser parser = new calcGrammarParser(new CommonTokenStream(lexer));
        ParseTreeWalker.DEFAULT.walk(new Listener(), parser.input());
    }
}

印刷内容如下:

代码语言:javascript
复制
enterAdditiveExpr: 2--2
enterUnaryMinusExpr: -2

对于访问者来说,您需要实现所有的访问--如下所示:

代码语言:javascript
复制
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;

public class Main {

    static class Visitor extends calcGrammarBaseVisitor<Integer> {

        @Override
        public Integer visitInput(calcGrammarParser.InputContext ctx) {
            System.out.println("visitInput: " + ctx.getText());
            return visit(ctx.expression());
        }

        @Override
        public Integer visitUnaryMinusExpr(calcGrammarParser.UnaryMinusExprContext ctx) {
            System.out.println("visitUnaryMinusExpr: " + ctx.getText());
            return -1 * visit(ctx.expression());
        }

        @Override
        public Integer visitNum(calcGrammarParser.NumContext ctx) {
            System.out.println("visitNum: " + ctx.getText());
            return Integer.parseInt(ctx.getText());
        }

        @Override
        public Integer visitMultiplicationExpr(calcGrammarParser.MultiplicationExprContext ctx) {
            System.out.println("visitMultiplicationExpr: " + ctx.getText());
            if (ctx.op.getType() == calcGrammarLexer.MULTIPLY) {
                return visit(ctx.expression(0)) * visit(ctx.expression(1));
            }
            return visit(ctx.expression(0)) / visit(ctx.expression(1));
        }

        @Override
        public Integer visitAdditiveExpr(calcGrammarParser.AdditiveExprContext ctx) {
            System.out.println("visitAdditiveExpr: " + ctx.getText());
            if (ctx.op.getType() == calcGrammarLexer.ADD) {
                return visit(ctx.expression(0)) + visit(ctx.expression(1));
            }
            return visit(ctx.expression(0)) - visit(ctx.expression(1));
        }
    }

    public static void main(String[] args) {
        String expression = "2 - -2";
        calcGrammarLexer lexer = new calcGrammarLexer(CharStreams.fromString(expression));
        calcGrammarParser parser = new calcGrammarParser(new CommonTokenStream(lexer));
        Integer answer = new Visitor().visit(parser.input());
        System.out.printf("%s = %s\n", expression, answer);
    }
}

它将打印:

代码语言:javascript
复制
visitInput: 2--2<EOF>
visitAdditiveExpr: 2--2
visitNum: 2
visitUnaryMinusExpr: -2
visitNum: 2
2 - -2 = 4

下面是一个表达式解析器/计算器的小演示,包括使用ANTLR4 +一个访问者:https://github.com/bkiers/Mu的基本循环和if语句

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48694645

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档