ANTLR4 简化数学表达式



我正在做一个项目,使用 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

相关内容

  • 没有找到相关文章

最新更新