2016-01-26 3 views
0

Итак, я пытаюсь реализовать шунтирующий двор для работы с Logic, я думал, что это будет легко, пока я не столкнулся с проблемой установки приоритета для материала условного (->) и bi-conditional (< ->), поскольку они должны быть представлены как String, а не char. Мне нужно иметь возможность читать файл с таким заявлением, как (A|B) -> !C (что означает: (A ИЛИ B) подразумевает NOT C) и переводит его в постфиксную нотацию. Я продолжаю получать исключение NullPointerException в строке 115, и я действительно не уверен, почему, могу ли я установить только случай, используя значения char? Или мне нужно найти другой метод установки приоритета для символов. Вот мой кодImplemeting Shunting yard с логикой

import java.io.IOException; 
import java.io.FileReader; 
import java.io.BufferedReader; 
import java.util.Scanner; 
import java.io.File; 
import java.util.ArrayList; 
import java.io.Reader; 

public class ShuntingYard 
{ 

public static ArrayList<String> symbols = new ArrayList<String>(); 
public static ArrayList<String> letters = new ArrayList<String>(); 
public static String path = ""; 
public static void main(String args[]) 
{ 
    ShuntingYard sy = new ShuntingYard(); 

    //Scans in File. 
    Scanner scan = new Scanner(System.in); 
    String prompt = "Please specify the file path.\n Use the form: D:\\DiscreteMath\\inputFile.txt"; 
    System.out.println(prompt); 
    path = scan.next(); 
    File file = new File(path); 
    String infix = ""; 

    try{ 

     scan = new Scanner(file); 
     infix = scan.nextLine(); 

    } 
    catch(IOException e) 
    { 
     System.err.println(" No file"); 
    } 
    // calls postfix function 
    String postfix = sy.postfix(infix); 
    System.out.println("\nPostfix expression : " + postfix); 
    String al = "A,B,C,D,E,"; 

} 
public enum Precedence 
{ 
    //configure precedence of symbols and operands. 
    lparen(0), rparen(1), not(2), and(3), or(4), mc(5), bc(6), eos(7), operand(8); 

    private int index; 
    Precedence(int index) 
    { 
     this.index = index; 
    } 
    public int getIndex() 
    { 
     return index; 
    } 
} 
private static final int[] isp = {0,19,12,12,13,13,0}; 
private static final int[] icp = {20,19,12,12,13,13,0}; 
private static final String[] operators = {"{","}","!","&","|","->","<->"," "}; 

//initializes stack 
private Precedence[] stack; 

private int top; 

private Precedence pop() 
{ 
    return stack[top--]; 
} 
private void push(Precedence ele) 
{ 
    stack[++top] = ele; 
} 
//Sets Precedence of symbols. 
public Precedence getToken(String symbol) 
{ 
    switch(symbol) 
    { 
     case "(" : return Precedence.lparen; 
     case ")" : return Precedence.rparen; 
     case "!" : return Precedence.not; 
     case "&" : return Precedence.and; 
     case "|" : return Precedence.or; 
     case "->" : return Precedence.mc; 
     case "<->" : return Precedence.bc; 
     case " " : return Precedence.eos; 
     default : return Precedence.operand; 
    } 
} 
//Changes infix to postfix notation then returns a string value. 
public String postfix(String infix) 
{ 
    String postfix = ""; 
    top = 0; 
    stack = new Precedence[infix.length()]; 
    Precedence token; 
    for(int i = 0; i<infix.length(); i++) 
    { 
     token = getToken(Character.toString(infix.charAt(i))); 

     if(token == Precedence.operand) 
     { 
      postfix = postfix + infix.charAt(i); 
     } 
     else if(token == Precedence.rparen) 
     { 
      while(stack[top] != Precedence.lparen) 
      { 
       postfix = postfix + operators[pop().getIndex()]; 
      } 
      pop(); 
     } 
     else 
     { 
      while(isp[stack[top].getIndex()] >= icp[token.getIndex()]) 
      { 
       postfix = postfix + operators[pop().getIndex()]; 
      } 
      push(token); 
     } 
    } 
    while((token = pop()) != Precedence.eos) 
    { 
     postfix = postfix + operators[token.getIndex()]; 
    } 
    return postfix; 
} 

}

+0

Запуск через отладчик ошибки легко отслеживать. В первом прогоне через постфиксный метод он считывает первый токен, который является Precedence.lparen, а не операндом или rparen, следовательно, он переходит в блок else. В этот момент стек пуст, заполненный нулем, дающий исключение нулевого указателя. –

ответ

0

Проблема заключается в том, что вы не проверяли пустой стек. Если вы добавите чек для пустых стеков в двух местах, код может работать.

import java.util.ArrayList; 
import java.util.Arrays; 

public class ShuntingYard 
{ 

public static ArrayList<String> symbols = new ArrayList<String>(); 
public static ArrayList<String> letters = new ArrayList<String>(); 
public static String path = ""; 
public static void main(String args[]) 
{ 
    ShuntingYard sy = new ShuntingYard(); 

    //Scans in File. 
// Scanner scan = new Scanner(System.in); 
// String prompt = "Please specify the file path.\n Use the form: D:\\DiscreteMath\\inputFile.txt"; 
// System.out.println(prompt); 
// path = scan.next(); 
// File file = new File(path); 
    String infix = "(A|B)&C"; // String infix = "(A|B) -> !C"; 

// try{ 
// 
//  scan = new Scanner(file); 
//  infix = scan.nextLine(); 
// 
// } 
// catch(IOException e) 
// { 
//  System.err.println(" No file"); 
// } 
    // calls postfix function 
    String postfix = sy.postfix(infix); 
    System.out.println("\nPostfix expression : " + postfix); 
    String al = "A,B,C,D,E,"; 
    // line 38 
} 
public enum Precedence 
{ 
    //configure precedence of symbols and operands. 
    lparen(0), rparen(1), not(2), and(3), or(4), mc(5), bc(6), eos(7), operand(8); 

    private int index; 
    Precedence(int index) 
    { 
     this.index = index; 
    } 
    public int getIndex() 
    { 
     return index; 
    } 
} 
private static final int[] isp = {0,19,12,12,13,13,0}; 
private static final int[] icp = {20,19,12,12,13,13,0}; 
private static final String[] operators = {"{","}","!","&","|","->","<->"," "}; 

//initializes stack 
private Precedence[] stack; 

private int top; 

private Precedence pop() 
{ 
    return stack[top--]; 
} 
private void push(Precedence ele) 
{ 
    stack[++top] = ele; 
} 
//Sets Precedence of symbols. 
public Precedence getToken(String symbol) 
{ 
    switch(symbol) 
    { 
     case "(" : return Precedence.lparen; 
     case ")" : return Precedence.rparen; 
     case "!" : return Precedence.not; 
     case "&" : return Precedence.and; 
     case "|" : return Precedence.or; 
     case "->" : return Precedence.mc; 
     case "<->" : return Precedence.bc; 
     case " " : return Precedence.eos; 
     default : return Precedence.operand; 
    } 
} 
//Changes infix to postfix notation then returns a string value. 
public String postfix(String infix) 
{ 
    String postfix = ""; 
    top = -1; 
    stack = new Precedence[infix.length()]; 
    Precedence token; 
    for(int i = 0; i<infix.length(); i++) 
    { 
     token = getToken(Character.toString(infix.charAt(i))); 
     System.out.println("Token "+ infix.charAt(i) + " " + token); 
     if(token == Precedence.operand) 
     { 
      postfix = postfix + infix.charAt(i); 
     } 
     else if(token == Precedence.rparen) 
     { 
      while(stack[top] != Precedence.lparen) 
      { 
       postfix = postfix + operators[pop().getIndex()]; 
      } 
      pop(); 
     } 
     else 
     { 
      while(top>=0 && isp[stack[top].getIndex()] >= icp[token.getIndex()]) 
      { 
       postfix = postfix + operators[pop().getIndex()]; 
      } 
      push(token); 
     } System.out.println("Postfix '"+postfix+"' Stack "+Arrays.deepToString(stack)); 
    } 
    while(top>=0 && ( (token = pop()) != Precedence.eos)) 
    { 
     postfix = postfix + operators[token.getIndex()]; 
    } 
    return postfix; 
} 
} 

Я добавил некоторые отладочные операторы печати, чтобы увидеть, что происходит.

код не работает с двумя операторами характера, как ->

Также используйте java.util.Deque для стека

Deque<Precedence> stack = new ArrayDeque<Precedence>(); 

, которые обеспечивают стандартный интерфейс для стека.

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