我正在做一个项目,使用 antlr4 创建程序以简化数学表达式。
例如:
x^2 + 2SQRT4 * 8 + x^2 --> 2x^2 + 16SQRT4
我已经创建了语法:
grammar Short
INT :[0-9]+;
POW :'^';
NL :'n';
WS :[ tr]+ -> skip;
ID :[a-zA-Z_][a-zA-Z_0-9]*;
PLUS :'+';
EQUALS :'=';
MINUS :'-';
MULT :'*';
DIV :'/';
LPAR :'(';
RPAR :')';
SQRT :'SQRT';
input
: setVar NL input # ToSetVar
| plusOrMinus NL? EOF # Calculate
;
setVar
: ID EQUAL plusOrMinus # SetVariable
;
plusOrMinus
: plusOrMinus PLUS multOrDiv # Plus
| plusOrMinus MINUS multOrDiv # Minus
| multorDiv # ToMultOrDiv
;
multOrDiv
: multOrDiv MULT pow # Multiplication
| multOrDiv DIV pow # Division
| pow # ToPow
;
pow
: sqrt (POW pow)? # Power
;
sqrt
:unaryMinus (SQRT sqrt)? # Sqrt
;
unaryMinus
: MINUS unaryMinus # ChangeSign
| atom # ToAtom
;
atom
| INT # Int
| ID # Variable
| LPAR plusOrMinus RPAR # Braces
;
现在我想使用侦听器并更改输入的步行树。有没有办法从内部更改侦听器使用的输入?
更新:
使用您的答案,我使用访问者编写代码,这是我定制的树:
public class Node {
private double firstN = 0;
private String firstS = null;
private String key = "";
private double secondN = 0;
private String secondS = null;
private boolean brances = false;
private int bbrances = 0;
private int ebrances = 0;
private Node parent = null;
private Node right = null;
private Node left = null;
public Node(Node l, String keye, Node r) {
left = l;
key = keye;
right = r;
}
public Node(int fNumber, String keye, int sNumber) {
firstN = fNumber;
secondN = sNumber;
key = keye;
}
public Node(String fLetter, String keye, int sNumber) {
firstS = fLetter;
secondN = sNumber;
key = keye;
}
public Node(String fLetter, String keye, String sLetter) {
firstS = fLetter;
secondS = sLetter;
key = keye;
}
public Node(int fNumber, String keye, String sLetter) {
firstN = fNumber;
secondS = sLetter;
key = keye;
}
public Node(int fNumber, String fLetter, String keye, int sNumber) {
firstN = fNumber;
firstS = fLetter;
secondN = sNumber;
key = keye;
}
public Node(int fNumber, String fLetter, String keye, String sLetter) {
firstN = fNumber;
firstS = fLetter;
secondS = sLetter;
key = keye;
}
public Node(String fLetter, String keye, int sNumber, String sLetter) {
firstS = fLetter;
secondN = sNumber;
secondS = sLetter;
key = keye;
}
public Node(int fNumber, String keye, int sNumber, String sLetter) {
firstN = fNumber;
secondN = sNumber;
secondS = sLetter;
key = keye;
}
public Node(int fNumber, String fLetter, String keye, int sNumber,
String sLetter) {
firstN = fNumber;
firstS = fLetter;
secondN = sNumber;
secondS = sLetter;
key = keye;
}
public Node() {
// TODO Auto-generated constructor stub
}
public double getFirstNumber() {
return firstN;
}
public double getSecondNumber() {
return secondN;
}
public String getFirstString() {
return firstS;
}
public String getSecondString() {
return secondS;
}
public String getKey() {
return key;
}
public boolean getBrances() {
return brances;
}
public int getBBrances() {
return bbrances;
}
public int getEBrances() {
return ebrances;
}
public Node getParent() {
return parent;
}
public Node getLeftNode() {
return left;
}
public Node getRightNode() {
return right;
}
public void changeFirstNumber(double number) {
firstN = number;
return;
}
public void changeSecondNumber(double number) {
secondN = number;
return;
}
public void changeFirstString(String letter) {
firstS = letter;
return;
}
public void changeSecondString(String letter) {
secondS = letter;
return;
}
public void changeKey(String letter) {
key = letter;
return;
}
public void changeBrances(boolean number) {
brances = number;
return;
}
public void changeBBrances(int number) {
bbrances = number;
return;
}
public void changeEBrances(int number) {
ebrances = number;
return;
}
public void changeParent() {
parent = null;
return;
}
public void changeParent(Node node) {
parent = node;
return;
}
public void changeLeftNode() {
left = null;
return;
}
public void changeLeftNode(Node node) {
left = node;
return;
}
public void changeRightNode() {
right = null;
return;
}
public void changeRightNode(Node node) {
right = node;
return;
}
public void display() {
if (brances == true) {
System.out.print("(");
left.display();
System.out.print(key);
right.display();
System.out.print(")");
} else {
if (left == null) {
if (firstN != 0)
System.out.print(firstN);
if (firstS != null)
System.out.print(firstS);
if (key != null)
System.out.print(key);
if (secondN != 0)
System.out.print(secondN);
if (secondS != null)
System.out.print(secondS);
} else {
left.display();
System.out.print(key);
right.display();
}
}
}
public void displayNode() {
// System.out.println("brances" + bbrances + " "+ ebrances);
if (bbrances > 0) for (int i=0; bbrances > i; i++) System.out.println("(");
if (left == null && right == null) {
System.out.println(firstN + firstS + key + secondN + secondS);
System.out.println("back");
} else if (left == null){
System.out.println(firstN + firstS + key + secondN + secondS);
System.out.println("right");
right.displayNode();
}
else if (right == null){
System.out.println("left");
left.displayNode();
System.out.println(firstN + firstS + key + secondN + secondS);
System.out.println("back");
}
else {
System.out.println("left");
left.displayNode();
System.out.println(key);
System.out.println("right");
right.displayNode();
System.out.println("back");
}
if (ebrances > 0) for (int i=0; ebrances > i; i++) System.out.println(")");
}
}
游客:
import org.antlr.v4.runtime.misc.NotNull;
公共类 NewVisitator 扩展了 HelloBaseVisitor {
@Override
public Node visitPlus(@NotNull HelloParser.PlusContext ctx) {
Node node =new Node();
Node left = visit(ctx.plusOrMinus());
left.changeParent(node);
Node right = visit(ctx.multOrDiv());
right.changeParent(node);
node.changeKey("+");
node.changeLeftNode(left);
node.changeRightNode(right);
return node;
// return visit(ctx.plusOrMinus()) + visit(ctx.multOrDiv());
}
@Override
public Node visitMinus(@NotNull HelloParser.MinusContext ctx) {
// return visit(ctx.plusOrMinus()) - visit(ctx.multOrDiv());
Node node =new Node();
Node left = visit(ctx.plusOrMinus());
Node right = visit(ctx.multOrDiv());
left.changeParent(node);
right.changeParent(node);
node.changeKey("-");
node.changeLeftNode(left);
node.changeRightNode(right);
return node;
}
@Override
public Node visitMultiplication(@NotNull HelloParser.MultiplicationContext ctx) {
// return visit(ctx.multOrDiv()) * visit(ctx.pow());
Node node =new Node();
Node left = visit(ctx.multOrDiv());
Node right = visit(ctx.pow());
left.changeParent(node);
right.changeParent(node);
node.changeKey("*");
node.changeLeftNode(left);
node.changeRightNode(right);
return node;
}
@Override
public Node visitDivision(@NotNull HelloParser.DivisionContext ctx) {
// return visit(ctx.multOrDiv()) / visit(ctx.pow());
Node node =new Node();
Node left = visit(ctx.multOrDiv());
Node right = visit(ctx.pow());
left.changeParent(node);
right.changeParent(node);
node.changeKey("/");
node.changeLeftNode(left);
node.changeRightNode(right);
return node;
}
@Override
public Node visitPower(@NotNull HelloParser.PowerContext ctx) {
Node node =new Node();
Node left = visit(ctx.sqrt());
Node right = visit(ctx.pow());
left.changeParent(node);
right.changeParent(node);
node.changeKey("^");
node.changeLeftNode(left);
node.changeRightNode(right);
return node;
}
@Override
public Node visitSqurt(@NotNull HelloParser.SqurtContext ctx) {
Node node =new Node();
Node left = visit(ctx.unaryMinus());
Node right = visit(ctx.sqrt());
left.changeParent(node);
right.changeParent(node);
node.changeKey("SQRT");
node.changeLeftNode(left);
node.changeRightNode(right);
return node;
}
@Override
public Node visitBraces(@NotNull HelloParser.BracesContext ctx) {
Node node =visit(ctx.plusOrMinus());
node.changeBrances(true);
return node;
}
@Override
public Node visitInt(@NotNull HelloParser.IntContext ctx) {
//return Double.parseDouble(ctx.INT().getText());
Node node = new Node();
node.changeFirstNumber(Integer.valueOf(ctx.INT().getText()));
return node;
}
@Override
public Node visitVariable(@NotNull HelloParser.VariableContext ctx) {
// return variables.get(ctx.ID().getText());
Node node = new Node();
node.changeFirstString(ctx.ID().getText());
return node;
}
@Override
public Node visitCalculate(@NotNull HelloParser.CalculateContext ctx) {
return visit(ctx.plusOrMinus());
}
A 现在我遇到了问题,因为走我的树并寻找像 x*(5+y( 这样的表达式并将它们更改为 x*5+x*y 很难。正在考虑如果我使用,antlr 是否可以为我做到这一点:
INT MULT LPAR plusOrMinus RPAR
但我不知道antlr树应该如何回馈表达。
现在我想使用侦听器并更改输入的步行树。有没有办法从内部更改侦听器使用的输入?
AFAIK,目前这是不可能的。在它之上构建自己的结构并将其转换为您的需求更容易。也许以后: https://theantlrguy.atlassian.net/wiki/display/~admin/2012/12/08/Tree+rewriting+in+ANTLR+v4