Antlr4 simplifies math expression

I am working on a project to create a program using antlr4 to simplify math expression.

For example:

x ^ 2 + 2SQRT4 * 8 + x ^ 2 → 2x ^ 2 + 16SQRT4

I've already created a grammar:

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 the walk tree to use Listeners and change the input. Is there a way to change the input that the Listener uses internally?

Update:

Using your answers, I am writing code using visitor, 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;

      

The 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());
    }

      

Now I have a problem because I walk through my tree and look for an expression like x * (5 + y) and changing them to x * 5 + x * y is tricky. I thought if antlr could do it for me if I use:

INT MULT LPAR plusOrMinus RPAR

      

But I have no idea how the antlr tree should give expression.

+3


source to share


1 answer


Now I want the walk tree to use Listeners and change the input. Is there a way to change the input that the Listener uses internally?



AFAIK that's not possible at the moment. It's easier to create your own structure on top of it and transform it according to your needs. Maybe later: https://theantlrguy.atlassian.net/wiki/display/~admin/2012/12/08/Tree+rewriting+in+ANTLR+v4

+3


source







All Articles