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

查看:433
本文介绍了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天全站免登陆