125 lines
3.1 KiB
Java
125 lines
3.1 KiB
Java
package it.cavallium.warppi.math.rules.dsl.errorutils;
|
|
|
|
import it.cavallium.warppi.math.rules.dsl.DslError;
|
|
import it.cavallium.warppi.math.rules.dsl.UndefinedSubFunction;
|
|
import it.cavallium.warppi.math.rules.dsl.frontend.*;
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
/**
|
|
* Creates human-readable error messages from instances of {@link DslError}.
|
|
*/
|
|
public class DslErrorMessageFormatter implements DslError.Visitor<String> {
|
|
/**
|
|
* Formats the given <code>DslError</code> as a human-readable message, according to its type.
|
|
*
|
|
* @param error The error to format.
|
|
* @return One or more lines of text which describe the error (without a trailing newline).
|
|
*/
|
|
public String format(final DslError error) {
|
|
return error.accept(this);
|
|
}
|
|
|
|
@Override
|
|
public String visit(final IncompleteNumberLiteral incompleteNumberLiteral) {
|
|
return String.format(
|
|
"Number has a decimal point but no digits following it: %s",
|
|
incompleteNumberLiteral.getLiteral()
|
|
);
|
|
}
|
|
|
|
@Override
|
|
public String visit(final UndefinedSubFunction undefinedSubFunction) {
|
|
return String.format(
|
|
"Sub-function %s is used in a replacement pattern,\nbut not defined in the target pattern",
|
|
undefinedSubFunction.getName()
|
|
);
|
|
}
|
|
|
|
@Override
|
|
public String visit(final UnexpectedCharacters unexpectedCharacters) {
|
|
final String plural = unexpectedCharacters.getLength() > 1 ? "s" : "";
|
|
return String.format("Unexpected character%s: %s", plural, unexpectedCharacters.getUnexpectedCharacters());
|
|
}
|
|
|
|
@Override
|
|
public String visit(final UnexpectedToken unexpectedToken) {
|
|
final String suggestions;
|
|
if (unexpectedToken.getSuggested().isEmpty()) {
|
|
suggestions = "";
|
|
} else {
|
|
suggestions = "\nSome suggestions are: " + unexpectedToken.getSuggested().stream()
|
|
.map(DslErrorMessageFormatter::tokenTypeName)
|
|
.collect(Collectors.joining(", "));
|
|
}
|
|
|
|
return String.format(
|
|
"Unexpected %s%s",
|
|
tokenTypeName(unexpectedToken.getUnexpected().type),
|
|
suggestions
|
|
);
|
|
}
|
|
|
|
@Override
|
|
public String visit(final UnterminatedComment unterminatedComment) {
|
|
return "Unterminated comment";
|
|
}
|
|
|
|
private static String tokenTypeName(final TokenType type) {
|
|
switch (type) {
|
|
case EOF:
|
|
return "end of input";
|
|
case COLON:
|
|
return "\":\"";
|
|
case ARROW:
|
|
return "\"->\"";
|
|
case COMMA:
|
|
return "\",\"";
|
|
case LEFT_PAREN:
|
|
return "\"(\"";
|
|
case RIGHT_PAREN:
|
|
return "\")\"";
|
|
case LEFT_BRACKET:
|
|
return "\"[\"";
|
|
case RIGHT_BRACKET:
|
|
return "\"]\"";
|
|
case EQUALS:
|
|
return "\"=\"";
|
|
case PLUS:
|
|
return "\"+\"";
|
|
case MINUS:
|
|
return "\"-\"";
|
|
case PLUS_MINUS:
|
|
return "\"+-\"";
|
|
case TIMES:
|
|
return "\"*\"";
|
|
case DIVIDE:
|
|
return "\"/\"";
|
|
case POWER:
|
|
return "\"^\"";
|
|
case REDUCTION:
|
|
case EXPANSION:
|
|
case CALCULATION:
|
|
case EXISTENCE:
|
|
case ARCCOS:
|
|
case ARCSIN:
|
|
case ARCTAN:
|
|
case COS:
|
|
case SIN:
|
|
case TAN:
|
|
case ROOT:
|
|
case SQRT:
|
|
case LOG:
|
|
case UNDEFINED:
|
|
case PI:
|
|
case E:
|
|
return '"' + type.name().toLowerCase() + '"';
|
|
case NUMBER:
|
|
return "number";
|
|
case IDENTIFIER:
|
|
return "identifier";
|
|
}
|
|
throw new RuntimeException("unknown token type");
|
|
}
|
|
}
|