2014-12-16 4 views
3

Я работаю над проектом по созданию программы с использованием antlr4 для упрощения математического выражения.antlr4 упрощающий математическое выражение

Например:

х^2 + 2SQRT4 * 8 + х^2 -> 2x^2 + 16SQRT4

Я уже создал Грамма:

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 
    ; 

Теперь я хочу, чтобы дерево ходьбы использовало Listeners и меняло вход. Есть ли способ изменить ввод, который использует Listener изнутри?

Update:

Используя Ваши ответы я пишу код, используя посетитель моего сшитое по дереву:

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

Теперь у меня проблема, потому что я хожу по моему дереву и ищу выражение, подобное x * (5 + y) и меняя их на x * 5 + x * y. Является ли было думать, если ANTLR может сделать это для меня, если я использую:

INT MULT LPAR plusOrMinus RPAR 

Но я не имею понятия, как ANTLR дерево должно дать выражение обратно.

+1

Возможно, было бы проще сделать это с посетителем. Есть ли причина, по которой вы хотите сделать это с помощью слушателя? – JNYRanger

+0

Вы правы, я пишу это, чтобы использовать посетителя – Kristof

ответ

3

Теперь я хочу, чтобы дерево ходьбы использовало Listeners и меняло вход. Есть ли способ изменить ввод, который использует Listener изнутри?

AFAIK, это невозможно в данный момент. Легче создать свою собственную структуру поверх нее и преобразовать ее в соответствии с вашими потребностями. Возможно, позже: https://theantlrguy.atlassian.net/wiki/display/~admin/2012/12/08/Tree+rewriting+in+ANTLR+v4

Смежные вопросы