Math ANTLR4语法中的不同乘法类型

Math ANTLR4语法中的不同乘法类型,math,expression,antlr4,Math,Expression,Antlr4,在输入用ANTLR4解析的数学表达式时,应允许两种类型的乘法5*x和5x。下面的语法接受了这两种情况,但有一个新的否定规则产生了错误的输出。示例:表达式x^2-5x现在被解析为x^2*-5x 我应该如何更改语法以便它正确解析输入 编辑:我已经更新了下面的语法,以便它反映当前状态,并且我还在这里插入了日志消息以显示我的问题。主要问题是在exitSimpleMultiplication 5x调用之前没有enterNatural 5和enterVariable x调用 EDIT2:我一直在玩弄语法,发

在输入用ANTLR4解析的数学表达式时,应允许两种类型的乘法5*x和5x。下面的语法接受了这两种情况,但有一个新的否定规则产生了错误的输出。示例:表达式x^2-5x现在被解析为x^2*-5x

我应该如何更改语法以便它正确解析输入

编辑:我已经更新了下面的语法,以便它反映当前状态,并且我还在这里插入了日志消息以显示我的问题。主要问题是在exitSimpleMultiplication 5x调用之前没有enterNatural 5和enterVariable x调用

EDIT2:我一直在玩弄语法,发现如果我在simplifiedMultiplication中使用规则而不是标记,效果会更好。更新的语法贴在下面

现在,解析5x是可行的,但解析2x^2仍然不可行,它会导致2x^2,s。在下面记录消息

我还发布了listener类

// Parser Rules

expression
    : primary                                            # aPrimary
    | composite                                          # aComposite
    | expression '^' expression                          # exponentiation
    | '-' expression                                     # negation
    | expression '/' expression                          # division
    | expression '*' expression                          # multiplication
    | simpleMultiplication                               # aSimpleMultiplication
    | expression operator=('+' | '-') expression         # additive
    | expression '=' expression                          # equation
    ;

primary
    : NATURAL                                            # natural
    | VARIABLE                                           # variable
    ;

composite
    : '(' expression ')'                                 # parentheses
    | '|' expression '|'                                 # abs
    | function                                           # aFunction
    ;

simpleMultiplication
    : primary primary
    | primary composite
    | composite primary
    | composite composite
    ;

function
    : FUNC '(' expression ')'
    ;

// Lexer Rules

FUNC : 'sqrt' | 'exp' | 'ln' | 'log' | 'abs' ;

ADD  : '+' ;
SUB  : '-' ;

NATURAL : [0-9]+ ;

VARIABLE : 'x' ;

WS  : [ \t\r\n]+ -> skip ;
侦听器类:

public class AntlrExpressionListener extends ExpressionsBaseListener {

    private final Deque<Expression> stack = new LinkedList();

    private final Map<String, Expression> identifiers = new HashMap();

    private Variable x;

    /**
     * Returns the parsed expression.
     * 
     * @return 
     */
    Expression getExpression() {
        return stack.pop();
    }

    void add(Reference ref) {
        identifiers.put(ref.name(), ref);
    }

    @Override
    public void exitAdditive(ExpressionsParser.AdditiveContext ctx) {
        Expression rhs = stack.pop();
        Expression lhs = stack.pop();

        if (ctx.operator.getType() == ExpressionsParser.ADD) {
            stack.push(Sum.add(lhs, rhs));
        } else if (ctx.operator.getType() == ExpressionsParser.SUB) {
            stack.push(Sum.subtract(lhs, rhs));
        } else {
            throw new IllegalStateException("Unexpected operation: " + ctx.operator);
        }
    }

    @Override
    public void exitMultiplication(ExpressionsParser.MultiplicationContext ctx) {
        Expression rhs = stack.pop();
        Expression lhs = stack.pop();

        stack.push(new Multiplication(lhs, rhs));
    }

    @Override
    public void exitSimpleMultiplication(ExpressionsParser.SimpleMultiplicationContext ctx) {
        Expression rhs = stack.pop();
        Expression lhs = stack.pop();

        stack.push(new Multiplication(lhs, rhs));
    }

    @Override
    public void exitDivision(ExpressionsParser.DivisionContext ctx) {
        Expression rhs = stack.pop();
        Expression lhs = stack.pop();

        if (lhs instanceof IntegerNumber && rhs instanceof NaturalNumber) {
            stack.push(new Division(lhs, rhs).evaluate());
        } else {
            stack.push(new Division(lhs, rhs));
        }
    }

    @Override
    public void exitExponentiation(ExpressionsParser.ExponentiationContext ctx) {
        Expression rhs = stack.pop();
        Expression lhs = stack.pop();

        stack.push(new Exponentiation(lhs, rhs));
    }

    @Override
    public void exitNegation(ExpressionsParser.NegationContext ctx) {
        Expression arg = stack.pop();

        if (arg instanceof ANumber) {
            stack.push(((ANumber) arg).negate());
        } else {
            stack.push(new Negation(arg));
        }
    }

    @Override
    public void exitEquation(ExpressionsParser.EquationContext ctx) {
        Expression rhs = stack.pop();
        Expression lhs = stack.pop();
        Equality equation = new Equality(lhs, rhs);

        stack.push(Equation.convert(equation, x));
    }

    @Override
    public void exitFunction(ExpressionsParser.FunctionContext ctx) {
        String function = ctx.FUNC().getText();
        Expression arg = stack.pop();

        switch (function) {
            case "exp":
                stack.push(new Exp(arg));
                break;

            case "ln":
                stack.push(new Ln(arg));
                break;

            case "sqrt":
                stack.push(new Sqrt(arg));
                break;

            case "abs":
                stack.push(new Abs(arg));
                break;

            default:
                throw new IllegalStateException("Unexpected function name: " + function);
        }
    }

    @Override
    public void enterNatural(ExpressionsParser.NaturalContext ctx) {
        stack.push(Naturals.getInstance().create(ctx.getText()));
    }

    @Override
    public void enterVariable(ExpressionsParser.VariableContext ctx) {
        x = (Variable) identifiers.get(ctx.getText());

        if (x == null) {
            x = Numbers.variable(ctx.getText());
            identifiers.put(ctx.getText(), x);
        }

        stack.push(x);
    }

    @Override
    public void exitAbs(ExpressionsParser.AbsContext ctx) {
        Expression arg = stack.pop();

        stack.push(new Abs(arg));
    }

    @Override
    public void enterEveryRule(ParserRuleContext ctx) {
        System.out.printf("in:  %s : %s%n", ctx.getText(), ctx.toStringTree());
    }

    @Override
    public void exitEveryRule(ParserRuleContext ctx) {
        System.out.printf("out: %s : %s%n", ctx.getText(), ctx.toStringTree());
    }
}

表达式和simplifiedMultiplication都将*作为可选项。为什么呢?如果你移除了这个?从表达式“*”开始?表达,事情应该按照你希望的方式进行。@BartKiers:谢谢你的回答!simplifiedMultiplication只是一次失败的试验。如果删除问号,则5x将不匹配,仅为5*x。不,将问号保留为simplifiedMultiplication,但将其从替换项中删除:|表达式“*”?表达式。@BartKiers:我已经尝试过了,但在这种情况下,我在解析时遇到了一个错误,我使用侦听器和堆栈来创建适当的Java对象:simplifiedMultiplication将5x作为输入,但堆栈中既不包含5也不包含x,因为没有调用适当的侦听器和自然变量。奇怪。你能发布你的听众课程吗?
in:  2x^2-x-1=0 : ([] ([0] ([0 0] ([0 0 0] ([0 0 0 0] ([15 0 0 0 0] ([53 15 0 0 0 0] 2) ([54 15 0 0 0 0] x))) ^ ([20 0 0 0] ([13 20 0 0 0] 2))) - ([29 0 0] ([13 29 0 0] x))) - ([29 0] ([13 29 0] 1))) = ([32] ([13 32] 0)))
in:  2x^2-x-1 : ([0] ([0 0] ([0 0 0] ([0 0 0 0] ([15 0 0 0 0] ([53 15 0 0 0 0] 2) ([54 15 0 0 0 0] x))) ^ ([20 0 0 0] ([13 20 0 0 0] 2))) - ([29 0 0] ([13 29 0 0] x))) - ([29 0] ([13 29 0] 1)))
in:  2x^2-x : ([0 0] ([0 0 0] ([0 0 0 0] ([15 0 0 0 0] ([53 15 0 0 0 0] 2) ([54 15 0 0 0 0] x))) ^ ([20 0 0 0] ([13 20 0 0 0] 2))) - ([29 0 0] ([13 29 0 0] x)))
in:  2x^2 : ([0 0 0] ([0 0 0 0] ([15 0 0 0 0] ([53 15 0 0 0 0] 2) ([54 15 0 0 0 0] x))) ^ ([20 0 0 0] ([13 20 0 0 0] 2)))
in:  2x : ([0 0 0 0] ([15 0 0 0 0] ([53 15 0 0 0 0] 2) ([54 15 0 0 0 0] x)))
in:  2x : ([15 0 0 0 0] ([53 15 0 0 0 0] 2) ([54 15 0 0 0 0] x))
in:  2 : ([53 15 0 0 0 0] 2)
out: 2 : ([53 15 0 0 0 0] 2)
in:  x : ([54 15 0 0 0 0] x)
out: x : ([54 15 0 0 0 0] x)
out: 2x : ([15 0 0 0 0] ([53 15 0 0 0 0] 2) ([54 15 0 0 0 0] x))
out: 2x : ([0 0 0 0] ([15 0 0 0 0] ([53 15 0 0 0 0] 2) ([54 15 0 0 0 0] x)))
in:  2 : ([20 0 0 0] ([13 20 0 0 0] 2))
in:  2 : ([13 20 0 0 0] 2)
out: 2 : ([13 20 0 0 0] 2)
out: 2 : ([20 0 0 0] ([13 20 0 0 0] 2))
out: 2x^2 : ([0 0 0] ([0 0 0 0] ([15 0 0 0 0] ([53 15 0 0 0 0] 2) ([54 15 0 0 0 0] x))) ^ ([20 0 0 0] ([13 20 0 0 0] 2)))
in:  x : ([29 0 0] ([13 29 0 0] x))
in:  x : ([13 29 0 0] x)
out: x : ([13 29 0 0] x)
out: x : ([29 0 0] ([13 29 0 0] x))
out: 2x^2-x : ([0 0] ([0 0 0] ([0 0 0 0] ([15 0 0 0 0] ([53 15 0 0 0 0] 2) ([54 15 0 0 0 0] x))) ^ ([20 0 0 0] ([13 20 0 0 0] 2))) - ([29 0 0] ([13 29 0 0] x)))
in:  1 : ([29 0] ([13 29 0] 1))
in:  1 : ([13 29 0] 1)
out: 1 : ([13 29 0] 1)
out: 1 : ([29 0] ([13 29 0] 1))
out: 2x^2-x-1 : ([0] ([0 0] ([0 0 0] ([0 0 0 0] ([15 0 0 0 0] ([53 15 0 0 0 0] 2) ([54 15 0 0 0 0] x))) ^ ([20 0 0 0] ([13 20 0 0 0] 2))) - ([29 0 0] ([13 29 0 0] x))) - ([29 0] ([13 29 0] 1)))
in:  0 : ([32] ([13 32] 0))
in:  0 : ([13 32] 0)
out: 0 : ([13 32] 0)
out: 0 : ([32] ([13 32] 0))
out: 2x^2-x-1=0 : ([] ([0] ([0 0] ([0 0 0] ([0 0 0 0] ([15 0 0 0 0] ([53 15 0 0 0 0] 2) ([54 15 0 0 0 0] x))) ^ ([20 0 0 0] ([13 20 0 0 0] 2))) - ([29 0 0] ([13 29 0 0] x))) - ([29 0] ([13 29 0] 1))) = ([32] ([13 32] 0)))
(2x)^2 - x - 1 = 0