Reputation: 41
I'm working on a project to create program using antlr4 to simplifying math expression.
For example:
x^2 + 2SQRT4 * 8 + x^2 --> 2x^2 + 16SQRT4
I already created gramma:
grammar Short
INT :[0-9]+;
POW :'^';
NL :'\n';
WS :[ \t\r]+ -> 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
;
Now i want walk tree using Listeners and change the input. Is there a way to change the input that Listener is using from inside?
Update:
Using yours answers i write the code using visitors an my custom made tree:
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(")");
}
}
Visitors:
import org.antlr.v4.runtime.misc.NotNull;
public class NewVisitator extends 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 now i have problem because walking my tree and looking for expression like x*(5+y) and changing them to x*5+x*y is hard. Is was thinking if antlr can do this for me if i use:
INT MULT LPAR plusOrMinus RPAR
But i dont have idea how antlr tree should give expression back.
Upvotes: 3
Views: 814
Reputation: 170227
Now i want walk tree using Listeners and change the input. Is there a way to change the input that Listener is using from inside?
AFAIK, that is not possible at the moment. It is easier to build your own structure on top of it and transform that to your needs. Perhaps later: https://theantlrguy.atlassian.net/wiki/display/~admin/2012/12/08/Tree+rewriting+in+ANTLR+v4
Upvotes: 3