0

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);
    }
}
starball
  • 20,030
  • 7
  • 43
  • 238
  • 1
    Looks like a bug in the java compiler. It should either produce a compiler error or produce a valid class file, and never produce an invalid class file like it did here. I'd suggest making a [mcve] first - something that I can copy and paste into my IDE and reproduce the problem. – Sweeper Mar 17 '23 at 01:27
  • From the looks of it, it seems like it might be getting stuck on the giant switch statement you wrote. Perhaps changing it to the old style (C-like) switch statement might help. – Sweeper Mar 17 '23 at 01:30
  • Also, include which compiler you are using in the question. If you are using the eclipse compiler, try compiling it with javac, and vice versa. – Sweeper Mar 17 '23 at 01:34
  • Found [this](https://stackoverflow.com/q/69197046/5133585) which seems similar. If you are using Eclipse, please update. – Sweeper Mar 17 '23 at 01:40
  • I'm using VS Code. This works in IntelliJ IDEA, but I find VS Code to be much cleaner. I've tried moving this code to a different computer running a different JDK and ran into the same issue. – andykasen13 Mar 24 '23 at 14:21
  • I turned it into an old-style switch statement and nothing changed: https://drive.google.com/file/d/1OYw9T2AHfxoEyRR6BahjAqEA__L0UcFX/view?usp=sharing – andykasen13 Mar 24 '23 at 14:48

0 Answers0