I'm trying to write some code for my Programming Languages class and I keep getting this 'Bad type on operand stack' java.lang.VerifyError error. This is happening in my Lexer class.
I honestly have no idea what this error means. Do I need a new JDK? I'm using JavaSE-17.
Here is my output:
Running /Users/user/OneDrive/Documents/ALLOFMYCODE/Programming-Languages-main/My Language/testInput/comments.mariokart...
Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
MarioKart/LexicalAnalysis/Lexer.getNextLexeme()LMarioKart/LexicalAnalysis/Lexeme; @620: invokespecial
Reason:
Type 'java/lang/Object' (current frame, stack[3]) is not assignable to 'MarioKart/LexicalAnalysis/Type'
Current Frame:
bci: @620
flags: { }
locals: { 'MarioKart/LexicalAnalysis/Lexer', integer }
stack: { uninitialized 594, uninitialized 594, integer, 'java/lang/Object' }
Bytecode:
0000000: 2ab6 015e 3c1b ab00 0000 02c4 0000 0018
0000010: 0000 0009 0000 00ca 0000 000a 0000 00ca
0000020: 0000 000d 0000 00ca 0000 0020 0000 00ca
0000030: 0000 0021 0000 0153 0000 0022 0000 0162
0000040: 0000 0026 0000 0167 0000 0028 0000 00ea
0000050: 0000 0029 0000 00f9 0000 002a 0000 02a6
0000060: 0000 002b 0000 0197 0000 002c 0000 0144
0000070: 0000 002d 0000 01d6 0000 002e 0000 0135
0000080: 0000 002f 0000 0215 0000 003b 0000 0126
0000090: 0000 003c 0000 026a 0000 003d 0000 0288
00000a0: 0000 003e 0000 024c 0000 005b 0000 00cc
00000b0: 0000 005d 0000 00db 0000 007b 0000 0108
00000c0: 0000 007c 0000 017f 0000 007d 0000 0117
00000d0: 01b0 bb01 5459 2ab4 0119 b201 60b7 0159
00000e0: b0bb 0154 592a b401 19b2 0163 b701 59b0
00000f0: bb01 5459 2ab4 0119 b201 66b7 0159 b0bb
0000100: 0154 592a b401 19b2 0169 b701 59b0 bb01
0000110: 5459 2ab4 0119 b201 6cb7 0159 b0bb 0154
0000120: 592a b401 19b2 016f b701 59b0 bb01 5459
0000130: 2ab4 0119 b201 72b7 0159 b0bb 0154 592a
0000140: b401 19b2 0175 b701 59b0 bb01 5459 2ab4
0000150: 0119 b201 78b7 0159 b0bb 0154 592a b401
0000160: 19b2 00c5 b701 59b0 2ab6 017b b02a 1026
0000170: b601 7e99 0174 bb01 5459 2ab4 0119 b200
0000180: e8b7 0159 b02a 107c b601 7e99 015c bb01
0000190: 5459 2ab4 0119 b200 edb7 0159 b02a 102b
00001a0: b601 7e99 0012 bb01 5459 2ab4 0119 b200
00001b0: bbb7 0159 b02a 103d b601 7e99 0012 bb01
00001c0: 5459 2ab4 0119 b200 a7b7 0159 b0bb 0154
00001d0: 592a b401 19b2 0093 b701 59b0 2a10 2db6
00001e0: 017e 9900 12bb 0154 592a b401 19b2 00c0
00001f0: b701 59b0 2a10 3db6 017e 9900 12bb 0154
0000200: 592a b401 19b2 00a7 b701 59b0 bb01 5459
0000210: 2ab4 0119 b200 98b7 0159 b02a 102f b601
0000220: 7e99 000a 2ab6 0180 a700 bf2a 103d b601
0000230: 7e99 0012 bb01 5459 2ab4 0119 b200 b6b7
0000240: 0159 b0bb 0154 592a b401 19b2 00a2 b701
0000250: 59b0 bb01 5459 2ab4 0119 2a10 3db6 017e
0000260: 9900 09b2 00d9 a700 06b2 00d4 b701 59b0
0000270: bb01 5459 2ab4 0119 2a10 3db6 017e 9900
0000280: 09b2 00e3 a700 06b2 00de b701 59b0 bb01
0000290: 5459 2ab4 0119 2a10 3db6 017e 9900 09b2
00002a0: 00ca a700 06b2 008e b701 59b0 bb01 5459
00002b0: 2ab4 0119 2a10 3db6 017e 9900 09b2 00b1
00002c0: a700 06b2 009d b701 59b0 2abb 0183 5913
00002d0: 0185 b701 871b b601 8913 018d b601 8fb6
00002e0: 0192 b601 9601 b001 b0
Stackmap Table:
append_frame(@208,Integer)
same_frame(@210)
same_frame(@225)
same_frame(@240)
same_frame(@255)
same_frame(@270)
same_frame(@285)
same_frame(@300)
same_frame(@315)
same_frame(@330)
same_frame(@345)
same_frame(@360)
same_frame(@365)
same_frame(@389)
same_frame(@413)
same_frame(@437)
same_frame(@461)
same_frame(@476)
same_frame(@500)
same_frame(@524)
same_frame(@539)
same_frame(@555)
same_frame(@579)
same_frame(@594)
full_frame(@617,{Object[#1],Integer},{Uninitialized[#594],Uninitialized[#594],Integer})
full_frame(@620,{Object[#1],Integer},{Uninitialized[#594],Uninitialized[#594],Integer,Object[#3]})
same_frame(@624)
full_frame(@647,{Object[#1],Integer},{Uninitialized[#624],Uninitialized[#624],Integer})
full_frame(@650,{Object[#1],Integer},{Uninitialized[#624],Uninitialized[#624],Integer,Object[#3]})
same_frame(@654)
full_frame(@677,{Object[#1],Integer},{Uninitialized[#654],Uninitialized[#654],Integer})
full_frame(@680,{Object[#1],Integer},{Uninitialized[#654],Uninitialized[#654],Integer,Object[#3]})
same_frame(@684)
full_frame(@707,{Object[#1],Integer},{Uninitialized[#684],Uninitialized[#684],Integer})
full_frame(@710,{Object[#1],Integer},{Uninitialized[#684],Uninitialized[#684],Integer,Object[#3]})
same_frame(@714)
same_frame(@743)
at MarioKart.MarioKart.runFile(MarioKart.java:36)
at MarioKart.MarioKart.main(MarioKart.java:15)
And here is my code:
package MarioKart.LexicalAnalysis;
import java.util.ArrayList;
import java.util.HashMap;
import MarioKart.MarioKart;
import static MarioKart.LexicalAnalysis.Type.*;
public class Lexer {
//--------------------- Instance Variables ----------------------
private final String source;
private final ArrayList<Lexeme> lexemes = new ArrayList<>();
private int currentPosition = 0;
private int startOfCurrentLexeme = 0;
private int lineNumber = 1;
private final HashMap<String, Type> keywords;
//--------------------- getKeywords() ---------------------------
private HashMap<String, Type> getKeywords() {
HashMap<String, Type> keywords = new HashMap<>();
keywords.put("requires", REQUIRES);
keywords.put("summon", SUMMON);
keywords.put("using", USING);
keywords.put("garage", GARAGE);
keywords.put("from", FROM);
keywords.put("to", TO);
keywords.put("return", RETURN);
keywords.put("timeTrial", TIMETRIAL);
keywords.put("first", FIRST);
keywords.put("second", SECOND);
keywords.put("third", THIRD);
keywords.put("fourth", FOURTH);
keywords.put("fifth", FIFTH);
keywords.put("sixth", SIXTH);
keywords.put("seventh", SEVENTH);
keywords.put("eighth", EIGHTH);
keywords.put("ninth", NINTH);
keywords.put("tenth", TENTH);
keywords.put("eleventh", ELEVENTH);
keywords.put("twelfth", TWELFTH);
keywords.put("last", LAST);
keywords.put("tiesWith", EQUALS);
keywords.put("boost", PLUS);
keywords.put("slip", MINUS);
keywords.put("superStar", TIMES);
keywords.put("blueShell", DIVIDED_BY);
keywords.put("multiMushroom", PLUS_EQUALS);
keywords.put("redShell", MINUS_EQUALS);
keywords.put("goldenMushroom", TIMES_EQUALS);
keywords.put("fallOffTheMap", DIVIDED_EQUALS);
keywords.put("overtake", PLUS_PLUS);
keywords.put("getPassed", MINUS_MINUS);
keywords.put("not", NOT);
keywords.put("isTiedWith", EQUALS_EQUALS);
keywords.put("isNotTiedWith", NOT_EQUALS);
keywords.put("isFurtherThan", GREATER_THAN);
keywords.put("isBetterThan", GREATER_THAN_OR_EQUAL_TO);
keywords.put("isBehind", LESS_THAN);
keywords.put("isWorseThan", LESS_THAN_OR_EQUAL_TO);
keywords.put("and", AND);
keywords.put("or", OR);
keywords.put("int", INT);
keywords.put("real", REAL);
keywords.put("boolean", BOOLEAN);
keywords.put("string", STRING);
keywords.put("array", ARRAY);
return keywords;
}
//---------- Constructor --------
public Lexer(String source) {
this.source = source;
this.keywords = getKeywords();
this.currentPosition = 0;
this.startOfCurrentLexeme = 0;
this.lineNumber = 1;
}
//---------------------- Helper Methods -----------------------
private boolean isAtEnd() {
return currentPosition >= source.length();
}
private char peek() {
if (isAtEnd()) return '\0';
return source.charAt(currentPosition);
}
private char peekNext() {
if(currentPosition + 1 >= source.length()) return '\0';
return source.charAt(currentPosition + 1);
}
private boolean match(char expected) {
if(isAtEnd() || source.charAt(currentPosition) != expected ) return false;
currentPosition++;
return true;
}
private char advance() {
char currentChar = source.charAt(currentPosition);
if(currentChar == '\n' || currentChar == '\r') lineNumber++;
currentPosition++;
return currentChar;
}
// -------------------- Supplemental Helper Methods --------------------
private boolean isDigit(char c) {
return c >= '0' && c <= '9';
}
private boolean isAlpha(char c) {
return (c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
(c == '_');
}
private boolean isAlphaNumeric(char c) {
return isAlpha(c) || isDigit(c);
}
// --------------------- Error Reporting -----------------------
private void error(String message) {
MarioKart.syntaxError(message, lineNumber);
}
//----------------------- lex() function ----------------------------
public ArrayList<Lexeme> lex() {
while(!isAtEnd()) {
startOfCurrentLexeme = currentPosition;
Lexeme nextLexeme = getNextLexeme();
if(nextLexeme != null) lexemes.add(nextLexeme);
}
lexemes.add(new Lexeme(lineNumber, END_OF_FILE));
return lexemes;
}
// --------------------- lex Helper Functions ---------------------------
private Lexeme getNextLexeme() {
char c = advance();
switch(c) {
//Ignore whitespace
case ' ', '\t', '\n', '\r' -> {
return null;
}
//one digit
case '[' -> { return new Lexeme(lineNumber, OPEN_BRACKET); }
case ']' -> { return new Lexeme(lineNumber, CLOSED_BRACKET); }
case '(' -> { return new Lexeme(lineNumber, OPEN_PARENTHESIS); }
case ')' -> { return new Lexeme(lineNumber, CLOSED_PARENTHESIS); }
case '{' -> { return new Lexeme(lineNumber, OPEN_CURLY); }
case '}' -> { return new Lexeme(lineNumber, CLOSED_CURLY); }
case ';' -> { return new Lexeme(lineNumber, SEMICOLON); }
case '.' -> { return new Lexeme(lineNumber, DOT); }
case ',' -> { return new Lexeme(lineNumber, COMMA); }
case '!' -> { return new Lexeme(lineNumber, NOT); }
case '%' -> { return new Lexeme(lineNumber, MOD); }
case '"' -> { return lexString(); }
case '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' -> { return lexNumber(); }
//two digits
case '&' -> { if(match('&')) return new Lexeme(lineNumber, AND); }
case '|' -> { if(match('|')) return new Lexeme(lineNumber, OR); }
//one OR two digits :(
case '+' -> {
if(match('+')) return new Lexeme(lineNumber, PLUS_PLUS);
else if(match('=')) return new Lexeme(lineNumber, PLUS_EQUALS);
else return new Lexeme(lineNumber, PLUS);
}
case '-' -> {
if(match('-')) return new Lexeme(lineNumber, MINUS_MINUS);
else if(match('=')) return new Lexeme(lineNumber, PLUS_EQUALS);
else return new Lexeme(lineNumber, MINUS);
}
case '/' -> {
if(match('/')) lexComments();
else if(match('=')) return new Lexeme(lineNumber, DIVIDED_EQUALS);
else return new Lexeme(lineNumber, DIVIDED_BY);
}
//only two options
case '>' -> { return new Lexeme(lineNumber, match('=') ? GREATER_THAN_OR_EQUAL_TO : GREATER_THAN); }
case '<' -> { return new Lexeme(lineNumber, match('=') ? LESS_THAN_OR_EQUAL_TO : LESS_THAN); }
case '=' -> { return new Lexeme(lineNumber, match('=') ? EQUALS_EQUALS : EQUALS); }
case '*' -> { return new Lexeme(lineNumber, match('=') ? TIMES_EQUALS : TIMES); }
//put NOTHING beneath these cases pls
default -> {
if(isDigit(c)) return lexNumber();
else if(isAlpha(c)) return lexIdentifierOrKeyword();
else {
error("bro what is '" + c + "'. i do not recognize it. but then again i dont recognize half of what goes on in my calc class sooooooo");
return null;
}
}
}
return null;
}
private Lexeme lexString() {
while( !(isAtEnd() || peek() == '"')) advance();
String str = source.substring(startOfCurrentLexeme + 1, currentPosition);
if(isAtEnd()) error("you didn't close your string :(. String: '" + str + "'");
else advance();
return new Lexeme(lineNumber, str, STRING);
}
private void lexComments() {
while( !(isAtEnd() || peek() == '\n')) advance();
}
private Lexeme lexNumber() {
boolean isInteger = true;
while(isDigit(peek())) advance();
//checking if int or real
if (peek() == '.') {
isInteger = false;
if(!isDigit(peekNext())) {
String malformedReal = source.substring(startOfCurrentLexeme, currentPosition + 2);
error("that isn't a number!!! silly goose. your failure: '" + malformedReal + "'");
}
advance();
while(isDigit(peek())) advance();
}
String numberString = source.substring(startOfCurrentLexeme, currentPosition);
if(isInteger) {
int intValue = Integer.parseInt(numberString);
return new Lexeme(lineNumber, intValue, INT);
} else {
double realValue = Double.parseDouble(numberString);
return new Lexeme(lineNumber, realValue, REAL);
}
}
private Lexeme lexIdentifierOrKeyword() {
while(isAlphaNumeric(peek())) advance();
String text = source.substring(startOfCurrentLexeme, currentPosition);
Type type = keywords.get(text);
if (type == null) return new Lexeme(lineNumber, text, IDENTIFIER);
else if(type == TRUE) return new Lexeme(lineNumber, true, TRUE);
else if(type == FALSE) return new Lexeme(lineNumber, false, FALSE);
return new Lexeme(lineNumber, type);
}
}