在输入使用ANTLR4解析的数学表达式时,应允许两种类型的乘法5 * x
和5x
。下面的语法已经接受了这两种情况,但是有一种新的否定规则会产生错误的输出。示例:现在解析表达式x^2 - 5x
,就好像它是(x^2) * (-5x)
。
我应该如何更改语法以便正确解析输入?
编辑:我已更新下面的语法,以便它反映当前状态,我还在此处插入了日志消息以显示我的问题。主要问题是在enterNatural (5)
电话会议之前没有enterVariable (x)
和exitSimpleMultiplication (5x)
来电。
EDIT2 :我一直在玩语法很多,并且发现如果我在simplifiedMultiplication
中使用规则(而不是令牌)会变得更好。更新了下面发布的语法。
现在,解析5x
正在解析但解析2x^2
仍未解析(导致(2x)^2
,s。日志消息如下)。
我也发布了听众类。
// 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());
}
}
记录消息:
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