2015-05-25 80 views
0

我有一個遞歸下降解析器項目,我早些時候發佈了一個關於堆棧溢出錯誤的問題。我已經能夠解決這個問題,但它現在返回一個ClassCastException。遞歸下降解析器 - ClassCastException

從主SWING GUI窗體中,我傳入輸入字符串,然後將其構建到字符串的鏈接列表中。然後我將它傳遞給parser.java。誤差表示:

java.lang.ClassCastException:java.lang.String中不能轉換到 compilerfinalproject.Token

下面是一些示例輸入:

  1. 1 + 2 3
  2. (1 + 2) - (3 + 4)
  3. (1 + 2 + 3)* 4

下面是我的tokenizer代碼。

import java.util.LinkedList; 

public class Tokenizer { 

    Tokenizer() {} // EMPTY CONSTRUCTOR FOR INSTANTIATION AT CompilerFinal.java 

    Tokenizer(String expression) { // CONSTRUCTOR FOR CALLING FROM LOCAL Tokenize METHOD 
     this.expression = expression.toCharArray(); // SET EXPRESSION TO TOKENIZE 
     this.pos = 0; // INITIALIZE AT INDEX 0 
    } 

    int pos; // STRING INDEX DECLARATION 
    char[] expression; // EXPRESSION DECLARATION 
    LinkedList <String> tokens = new LinkedList<>(); // ARRAYLIST FOR ALL TOKENS 

    enum tokenClass {PLUS, MINUS, MULTIPLY, DIVIDE, EXPONENT, NUMBER, IDENTIFIER, OPEN, CLOSE, NEGATIVE, DEFAULT} // TOKEN CLASSES (DEFAULT FOR INITIALIZATION PURPOSES ONLY) 

    class Lexeme { // EACH LEXEME HAS TOKEN CLASS AND TOKEN VALUE 
     String tokenClass, token; 
     Lexeme(String tokenClass, String token) { 
      this.tokenClass = tokenClass; 
      this.token = token; 
     } 
    } 

    Lexeme getToken() { // METHOD TO GET TOKENS 
     StringBuilder token = new StringBuilder(); // BUILDS TOKEN PER CHARACTER 
     boolean endOfToken = false; // FLAG WHETHER TO END TOKEN 
     tokenClass type = tokenClass.DEFAULT; // DEFAULT VALUE FOR TOKENCLASS 
     while (!endOfToken && hasMoreTokens()) // LOOP UNTIL A TOKEN IS COMPLETED 
     { 
      while(expression[pos] == ' ') // SKIP ALL LEADING SPACES 
       pos++; 
      switch (expression[pos]) 
      { 
       case '+': 
        if(type != tokenClass.NUMBER && type != tokenClass.IDENTIFIER) 
        { 
         type = tokenClass.PLUS; // SET TOKEN CLASS AS OPERATOR 
         token.append(expression[pos]); 
         pos++; 
        } 
        endOfToken = true; // END TOKEN IMMEDIATELY 
        break; 

       case '-': 
        if(type != tokenClass.NUMBER && type != tokenClass.IDENTIFIER) 
        { 
         type = tokenClass.MINUS; // SET TOKEN CLASS AS OPERATOR 
         token.append(expression[pos]); 
         pos++; 
        } 
        endOfToken = true; // END TOKEN IMMEDIATELY 
        break; 

       case '*': 
        if(type != tokenClass.NUMBER && type != tokenClass.IDENTIFIER) 
        { 
         type = tokenClass.MULTIPLY; // SET TOKEN CLASS AS OPERATOR 
         token.append(expression[pos]); 
         pos++; 
        } 
        endOfToken = true; // END TOKEN IMMEDIATELY 
        break; 

       case '/': 
        if(type != tokenClass.NUMBER && type != tokenClass.IDENTIFIER) 
        { 
         type = tokenClass.DIVIDE; // SET TOKEN CLASS AS OPERATOR 
         token.append(expression[pos]); 
         pos++; 
        } 
        endOfToken = true; // END TOKEN IMMEDIATELY 
        break; 

       case '^': 
        if(type != tokenClass.NUMBER && type != tokenClass.IDENTIFIER) 
        { 
         type = tokenClass.EXPONENT; // SET TOKEN CLASS AS OPERATOR 
         token.append(expression[pos]); 
         pos++; 
        } 
        endOfToken = true; // END TOKEN IMMEDIATELY 
        break; 

       case '(': // OPEN PARENTHESES 
        if(type != tokenClass.NUMBER && type != tokenClass.IDENTIFIER) 
        { 
         type = tokenClass.OPEN; // SET TOKEN CLASS AS OPEN 
         token.append(expression[pos]); 
         pos++; 
        } 
        endOfToken = true; // END TOKEN IMMEDIATELY 
        break; 

       case ')': // CLOSE PARENTHESES 
        if(type != tokenClass.NUMBER && type != tokenClass.IDENTIFIER) 
        { 
         type = tokenClass.CLOSE; // SET TOKEN CLASS AS CLOSE 
         token.append(expression[pos]); 
         pos++; 
        } 
        endOfToken = true; // END TOKEN IMMEDIATELY 
        break; 

       case ' ': // SKIP WHITESPACE 
        endOfToken = true; 
        pos++; 
        break; 

       default: 
        if(Character.isDigit(expression[pos]) || expression[pos] == '.') // FOR NUMBERS AND DECIMAL POINTS 
        { 
         token.append(expression[pos]); 
         type = tokenClass.NUMBER; // SET TOKENCLASS AS NUMBER 
        } 
        else if(Character.isAlphabetic(expression[pos])) // FOR IDENTIFIERS 
        { 
         token.append(expression[pos]); 
         type = tokenClass.IDENTIFIER; 
        } 
        pos++; // NO END TOKEN TO TAKE INTO ACCOUNT MULTIPLE DIGIT NUMBERS 
        break; 
      } 
     } 
     return new Lexeme(type.name().toLowerCase(), token.toString()); 
    } 

    boolean hasMoreTokens() { // CONDITION CHECKING 
     return pos < expression.length; 
    } 

    public LinkedList tokenize (String expression) { // CALLED FROM CompilerFinal.java TO GET TOKENS IN ARRAYLIST 
     Tokenizer tokenizer = new Tokenizer(expression); // INSTANTIATE 
     while (tokenizer.hasMoreTokens()) // GETTING ALL TOKENS 
     { 
      Lexeme nextToken = tokenizer.getToken(); 
      tokens.add(nextToken.token); 
     } 
     return tokens; 
    } 

    public String getLexeme (String expression) // CALLED FROM CompilerFinal.java FOR DISPLAYING IN GUI FORM 
    { 
     StringBuilder lexemeList = new StringBuilder(); 
     Tokenizer tokenizer = new Tokenizer(expression); // INSTANTIATE 
     lexemeList.append("LEXEMES:\n"); 
     while (tokenizer.hasMoreTokens()) // GETTING ALL TOKENS 
     { 
      Lexeme nextToken = tokenizer.getToken(); 
      lexemeList.append(nextToken.token).append("\t").append(nextToken.tokenClass).append("\n"); 
     } 
     return lexemeList.toString(); 
    } 

} 

下面是我的解析器代碼。我已經包含了我在評論中使用的語法。

import java.util.LinkedList; 

class Token { 
    public static final int PLUS = 0; 
    public static final int MINUS = 1; 
    public static final int MULTIPLY = 2; 
    public static final int DIVIDE = 3; 
    public static final int EXPONENT = 4; 
    public static final int NUMBER = 5; 
    public static final int IDENTIFIER = 6; 
    public static final int OPEN = 7; 
    public static final int CLOSE = 8; 
    //public static final int NEGATIVE = 7; 

    public final int token; // FIELDS TO HOLD DATA PER TOKEN 
    public final String sequence; 

    public Token (int token, String sequence) { 
     super(); 
     this.token = token; 
     this.sequence = sequence; 
    } 
} 

public class Parser { 

    private Token next; // POINTER FOR NEXT TOKEN 
    private final LinkedList<Token> tokens; // LIST OF TOKENS PRODUCED BY TOKENIZER 
    private int counter = 0; 

    public Parser(LinkedList tokens) 
    { 
     this.tokens = (LinkedList<Token>) tokens.clone(); // GET LINKEDLIST 
     this.tokens.getFirst(); // ASSIGNS FIRST ELEMENT OF LINKEDLIST 
    } 


    //////// START OF PARSING METHODS //////// 

    /* 
     GRAMMAR: 
     E -> TE' | TE'' 
     E' -> +E | e 
     E'' -> -E | e 

     T -> FT' | FT'' 
     T' -> *T | e 
     T'' -> /T | e 

     F -> (E) | -F | "NUMBER" | "IDENTIFIER" 
    */ 

    public boolean Parse() 
    { 
     return E(); // INVOKE START SYMBOL 
    } 

    private boolean term (int token) // GETS NEXT TOKEN 
    { 
     boolean flag = false; 

     if(next.token == token) 
      flag = true; 

     counter++; // INCREMENT COUNTER 

     if(counter < tokens.size()) // POINT TO NEXT TOKEN 
      next = tokens.get(counter); 

     return flag; 
    } 

    ///////// START OF LIST OF PRODUCTIONS ///////// 

    //////// E -> TE' | TE'' //////// 

    private boolean E() 
    { 
     return E1() || E2(); 
    } 

    private boolean E1() 
    { 
     // E -> TE' 

     int flag = counter; 
     boolean result = true; 

     if(!(T() && E_P())) 
     { 
      counter = flag; // BACKTRACK 

      if(counter < tokens.size()) // POINT TO PREVIOUS TOKEN 
       next = tokens.get(counter); 

      result = false; 
     } 
     return result; 
    } 

    private boolean E2() 
    { 
     // E -> TE'' 

     int flag = counter; 
     boolean result = true; 

     if(!(T() && E_PP())) 
     { 
      counter = flag; // BACKTRACK 

      if(counter < tokens.size()) // POINT TO PREVIOUS TOKEN 
       next = tokens.get(counter); 

      result = false; 
     } 
     return result; 
    } 


    //////// E' -> +E | e //////// 

    private boolean E_P() 
    { 
     return E_P1() || E_P2(); 
    } 

    private boolean E_P1() 
    { 
     // E' -> +E 

     int flag = counter; 
     boolean result = true; 

     if(!(term(Token.PLUS) && E())) 
     { 
      counter = flag; // BACKTRACK 

      if(counter < tokens.size()) // POINT TO PREVIOUS TOKEN 
       next = tokens.get(counter); 

      result = false; 
     } 
     return result; 
    } 

    private boolean E_P2() 
    { 
     // E' -> e 

     return true; 
    } 


    //////// E'' -> -E | e //////// 

    private boolean E_PP() 
    { 
     return E_PP1() || E_PP2(); 
    } 

    private boolean E_PP1() 
    { 
     // E'' -> -E 

     int flag = counter; 
     boolean result = true; 

     if(!(term(Token.MINUS) && E())) 
     { 
      counter = flag; // BACKTRACK 

      if(counter < tokens.size()) // POINT TO PREVIOUS TOKEN 
       next = tokens.get(counter); 

      result = false; 
     } 
     return result; 
    } 

    private boolean E_PP2() 
    { 
     // E'' -> e 

     return true; 
    } 


    //////// T -> FT' | FT'' //////// 

    private boolean T() 
    { 
     return T1() || T2(); 
    } 

    private boolean T1() 
    { 
     // T -> FT' 

     int flag = counter; 
     boolean result = true; 

     if(!(F() && T_P())) 
     { 
      counter = flag; // BACKTRACK 

      if(counter < tokens.size()) // POINT TO PREVIOUS TOKEN 
       next = tokens.get(counter); 

      result = false; 
     } 
     return result; 
    } 

    private boolean T2() 
    { 
     // T -> FT'' 
     int flag = counter; 
     boolean result = true; 

     if(!(F() && T_PP())) 
     { 
      counter = flag; // BACKTRACK 

      if(counter < tokens.size()) // POINT TO PREVIOUS TOKEN 
       next = tokens.get(counter); 

      result = false; 
     } 
     return result; 
    } 


    //////// T' -> *T | e //////// 

    private boolean T_P() 
    { 
     return T_P1() || T_P2(); 
    } 

    private boolean T_P1() 
    { 
     // T' -> *T 

     int flag = counter; 
     boolean result = true; 

     if(!(term(Token.MULTIPLY) && T())) 
     { 
      counter = flag; // BACKTRACK 

      if(counter < tokens.size()) // POINT TO PREVIOUS TOKEN 
       next = tokens.get(counter); 

      result = false; 
     } 
     return result; 
    } 

    private boolean T_P2() 
    { 
     // T' -> e 

     return true; 
    } 


    //////// T'' -> /T | e //////// 

    private boolean T_PP() 
    { 
     return T_PP1() || T_PP2(); 
    } 

    private boolean T_PP1() 
    { 
     // T'' -> /T 

     int flag = counter; 
     boolean result = true; 

     if(!(term(Token.DIVIDE) && T())) 
     { 
      counter = flag; // BACKTRACK 

      if(counter < tokens.size()) // POINT TO PREVIOUS TOKEN 
       next = tokens.get(counter); 

      result = false; 
     } 
     return result; 
    } 

    private boolean T_PP2() 
    { 
     // T'' -> e 

     return true; 
    } 


    //////// F -> (E) | -F | "NUMBER" | "IDENTIFIER" //////// 

    private boolean F() 
    { 
     return F1() || F2() || F3() || F4(); 
    } 

    private boolean F1() 
    { 
     // F -> (E) 

     int flag = counter; 
     boolean result = true; 

     if(!(term(Token.OPEN) && T() && term(Token.CLOSE))) 
     { 
      counter = flag; // BACKTRACK 

      if(counter < tokens.size()) // POINT TO PREVIOUS TOKEN 
       next = tokens.get(counter); 

      result = false; 
     } 
     return result; 
    } 

    private boolean F2() 
    { 
     // F -> -F 

     int flag = counter; 
     boolean result = true; 

     if(!(term(Token.MINUS) && F())) 
     { 
      counter = flag; // BACKTRACK 

      if(counter < tokens.size()) // POINT TO PREVIOUS TOKEN 
       next = tokens.get(counter); 

      result = false; 
     } 
     return result; 
    } 

    private boolean F3() 
    { 
     // F -> NUMBER 

     int flag = counter; 
     boolean result = true; 

     if(!(term(Token.NUMBER))) 
     { 
      counter = flag; // BACKTRACK 

      if(counter < tokens.size()) // POINT TO PREVIOUS TOKEN 
       next = tokens.get(counter); 

      result = false; 
     } 
     return result; 
    } 

    private boolean F4() 
    { 
     // F -> NUMBER 

     int flag = counter; 
     boolean result = true; 

     if(!(term(Token.IDENTIFIER))) 
     { 
      counter = flag; // BACKTRACK 

      if(counter < tokens.size()) // POINT TO PREVIOUS TOKEN 
       next = tokens.get(counter); 

      result = false; 
     } 
     return result; 
    } 
} 
+0

什麼行引發異常?注意:您正在使用[原始類型](http://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it)。這很可能與這個例外有關。另外,請顯示調用'tokenize'的代碼。 – Radiodef

+0

與論壇網站不同,我們不使用「謝謝」,或「任何幫助表示讚賞」,或在[so]上簽名。請參閱「[應該'嗨','謝謝',標語和致敬從帖子中刪除?](http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be -removed - 從 - 個)。 –

回答

1

第一件事情,改變這種:

public LinkedList tokenize (String expression) {...} 

這樣:

public LinkedList<String> tokenize (String expression) {...} 

並改變這一點:

public Parser(LinkedList tokens) {...} 

這樣:

public Parser(LinkedList<Token> tokens) {...} 

LinkedList(沒有通用部分)被稱爲raw type,並有助於未經檢查的轉換。如果有更多地方使用原始類型,則還需要更改。從你的代碼中刪除所有的原始類型幾乎肯定會導致你的錯誤。

我強烈懷疑你有代碼基本上是這樣的:

Tokenizer t = ...; 

// passing LinkedList<String> as a LinkedList<Token> 
Parser p = new Parser(t.tokenize(...)); 

換句話說,你跳過了,你需要Strings轉換爲Tokens了一步。