141 lines
6.4 KiB
Java
141 lines
6.4 KiB
Java
package ssw.mj;
|
|
|
|
import java.io.Serial;
|
|
import java.text.MessageFormat;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
public class Errors {
|
|
public static class PanicMode extends Error {
|
|
@Serial
|
|
private static final long serialVersionUID = 1L;
|
|
// Nothing to implement here.
|
|
}
|
|
|
|
public enum Message {
|
|
// ----- error messages first used in ScannerTest
|
|
EMPTY_CHARCONST("empty character constant"),
|
|
UNDEFINED_ESCAPE("undefined escape character sequence ''\\{0}''"),
|
|
MISSING_QUOTE("missing '' at end of character constant"),
|
|
INVALID_CHAR("invalid character {0}"),
|
|
BIG_NUM("{0} too big for integer constant"),
|
|
EOF_IN_COMMENT("unexpected end of file in comment"),
|
|
EOF_IN_CHAR("unexpected end of file in char"),
|
|
ILLEGAL_LINE_END("illegal line end in character constant"),
|
|
|
|
// ----- error messages first used in ParserTest
|
|
INVALID_ADD_OP("unexpected token. + or - expected"), // cannot occur in current grammar version, but still must be placed correctly (in default case of respective switch)
|
|
INVALID_ASSIGN_OP("unexpected token. =, +=, -=, *=, /=, %= expected"), // cannot occur in current grammar version, but still must be placed correctly (in default case of respective switch)
|
|
INVALID_MUL_OP("unexpected token. *, /, % expected"), // cannot occur in current grammar version, but still must be placed correctly (in default case of respective switch)
|
|
INVALID_METHOD_DECL("invalid start of method decl: type name or void expected"), // cannot occur in current grammar version, but still must be placed correctly (in default case of respective switch)
|
|
INVALID_STATEMENT("unexpected token. identifier, if, while, break, return, read, print, '{' or ; expected"), // cannot occur in current grammar version, but still must be placed correctly (in default case of respective switch)
|
|
INVALID_DESIGNATOR_STATEMENT("unexpected token. assignment token (=, +=, -=, *=, /=, %=), method call (\"(\"), increment (++) or decrement (--) expected"),
|
|
INVALID_CONST_TYPE("number or character constant expected"),
|
|
INVALID_FACTOR("unexpected token. identifier, number, character constant, new or \"(\" expected"),
|
|
INVALID_REL_OP("unexpected token. ==, !=, >, >=, <, <= expected"),
|
|
TOKEN_EXPECTED("{0} expected"),
|
|
|
|
// ----- error messages first used in RecoverTest
|
|
DECLARATION_RECOVERY("start or follow of declaration expected"),
|
|
METHOD_DECL_RECOVERY("start or follow of method declaration expected"),
|
|
STATEMENT_RECOVERY("start or follow of statement expected"),
|
|
|
|
// ----- error messages first used in SymbolTableTest
|
|
INCOMPATIBLE_TYPES("incompatible types"), // mainly used in SimpleCodeGenerationTest, but also in SymbolTableTest
|
|
DUPLICATE_NAME_IN_SCOPE("{0} already declared in current scope"),
|
|
MAIN_WITH_PARAMS("main method must not have any parameters"),
|
|
MAIN_NOT_VOID("main method must return void"),
|
|
FIELD_NOT_FOUND("{0} is not a field"),
|
|
TYPE_EXPECTED("type expected"),
|
|
NAME_NOT_FOUND("{0} not found"),
|
|
TOO_MANY_FIELDS("too many fields"),
|
|
TOO_MANY_GLOBALS("too many global variables"),
|
|
TOO_MANY_LOCALS("too many local variables"),
|
|
CLASS_TYPE_EXPECTED("can only instantiate new object for a class"),
|
|
|
|
// ----- error messages first used in SimpleCodeGenerationTest
|
|
ARRAY_INDEX_EXPECTS_INT("array index must be an integer"),
|
|
ARRAY_SIZE_EXPECTS_INT("array size must be an integer"),
|
|
CANNOT_STORE_TO_READONLY("cannot store to readonly operand of kind {0}"),
|
|
VOID_CALL_IN_EXPRESSION("cannot use void method as part of expression"),
|
|
MAIN_NOT_FOUND("mainPC is -1, main not found (did you forget to set code.mainPC? ;))"),
|
|
INDEXED_ACCESS_TO_NON_ARRAY("indexed object is not an array"),
|
|
FIELD_ACCESS_TO_NON_CLASS("accessed object is not of kind class"),
|
|
ILLEGAL_OPERAND_KIND("cannot create operand symbol table object of type {0}"),
|
|
CANNOT_LOAD_OPERAND("already loaded (stack) or loadable operand (const, local, static, field, array element) expected"),
|
|
ILLEGAL_PRINT_ARGUMENT("can only print int or char values"),
|
|
ILLEGAL_READ_ARGUMENT("can only read int or char values"),
|
|
INC_DEC_EXPECTS_INT("increment and decrement only allowed for int"),
|
|
UNARY_MINUS_EXPECTS_INT("unary minus only allowed for int"),
|
|
|
|
// ----- error messages first used in CodeGenerationTest
|
|
ILLEGAL_REFERENCE_COMPARISON("only equality and unequality checks are allowed for reference types"),
|
|
ILLEGAL_METHOD_RETURN_TYPE("methods may only return int or char"),
|
|
WRONG_ARGUMENT_COUNT("number of arguments and formal parameters does not match"),
|
|
BREAK_OUTSIDE_LOOP("break is not within a loop"),
|
|
CALL_TO_NON_METHOD("called object is not a method"),
|
|
ARGUMENT_TYPE_MISMATCH("argument type does not match formal parameter type"),
|
|
MISSING_RETURN_VALUE("return expression required in non-void method"),
|
|
UNEXPECTED_RETURN_VALUE("no return expression allowed in void method"),
|
|
RETURN_TYPE_MISMATCH("return type must match method type");
|
|
|
|
private final String msg;
|
|
|
|
Message(String msg) {
|
|
this.msg = msg;
|
|
}
|
|
|
|
public String format(Object... params) {
|
|
int expectedParams = 0;
|
|
while (msg.contains("{" + expectedParams + "}")) {
|
|
expectedParams++;
|
|
}
|
|
if (params.length != expectedParams) {
|
|
throw new Error("incorrect number of error message parameters. Expected %d but got %d".formatted(expectedParams, params.length));
|
|
}
|
|
return MessageFormat.format(msg, params);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List of error messages.
|
|
*/
|
|
private final List<String> errors;
|
|
|
|
/**
|
|
* Initialization (must be called before compilation).
|
|
*/
|
|
public Errors() {
|
|
errors = new ArrayList<>();
|
|
}
|
|
|
|
/**
|
|
* Add a new error message to the list of errors.
|
|
*/
|
|
public void error(int line, int col, Message msg, Object... msgParams) {
|
|
errors.add("-- line " + line + " col " + col + ": " + msg.format(msgParams));
|
|
}
|
|
|
|
/**
|
|
* Returns the number of errors.
|
|
*/
|
|
public int numErrors() {
|
|
return errors.size();
|
|
}
|
|
|
|
/**
|
|
* String representation for JUnit test cases.
|
|
*/
|
|
public String dump() {
|
|
StringBuilder sb = new StringBuilder();
|
|
for (String error : errors) {
|
|
sb.append(error).append("\n");
|
|
}
|
|
return sb.toString();
|
|
}
|
|
|
|
public List<String> getErrors() {
|
|
return errors;
|
|
}
|
|
}
|