ANTLR 4 如何处理一元/负数 [英] ANTLR 4 How to handle unary/negative numbers

查看:27
本文介绍了ANTLR 4 如何处理一元/负数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Antlr 4 设置一个简单的计算器.

I'm trying to setup a simple calculator with Antlr 4.

语法:

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 代码:

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".当我在方法中放置调试点时,永远不会进入.

If my input is 2 - -2. The code will never go into this method with this input. Notice that the input has a negative unary operator, this should be perceived as '-2'. When i put a debug point in the method is never enters.

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

With my grammar setup should it not be the case that it should always take into consideration the unary minus first?

当实现一元表达式和上瘾表达式时,似乎会出现此错误.在这种情况下,程序不会进入一元方法,输入'2 - -2'

It seems that this error arises when both unary and addictive expressions are implemented. The program will not go into the unary method in this case with input '2 - -2'

推荐答案

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

With my grammar setup should it not be the case that it should always take into consideration the unary minus first?

是的,它应该(而且确实如此).

Yes, it should (and it does).

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

I'm guessing you didn't regenerate your parser and lexer classes recently, because given your grammar (I only added SPACE : [ \t\r\n] -> skip;), when I run this class:

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());
    }
}

打印如下:

enterAdditiveExpr: 2--2
enterUnaryMinusExpr: -2

对于访问者,您需要像这样实施所有访问方法:

For a visitor, you'll need to implement all your visit-methods like this:

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);
    }
}

将打印:

visitInput: 2--2<EOF>
visitAdditiveExpr: 2--2
visitNum: 2
visitUnaryMinusExpr: -2
visitNum: 2
2 - -2 = 4

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

Here's a small demo of an expression parser/evaluator including basic loops and if statements using ANTLR4 + a Visitor: https://github.com/bkiers/Mu

这篇关于ANTLR 4 如何处理一元/负数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆