Math ANTLR4语法中的不同乘法类型
在输入用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类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:我一直在玩弄语法,发
// 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