我有一个Recursive Descent Parser项目,我之前发布了一个关于堆栈溢出错误的问题。我已经能够解决这个问题,但它现在返回一个ClassCastException。
从主SWING GUI表单中,我传递输入字符串,然后将其构建为字符串的链接列表。然后我将它传递给parser.java。错误说:
java.lang.ClassCastException:java.lang.String无法强制转换为 compilerfinalproject.Token
以下是一些示例输入:
以下是我的令牌代码。
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 :(得分: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
的步骤。