[muscript] Generate error data in create method, not in toString
This commit is contained in:
parent
ed680f57a9
commit
a9cd45c39d
@ -3,29 +3,44 @@ package io.gitlab.jfronny.muscript.compiler;
|
||||
/**
|
||||
* Class for storing errors produced while parsing.
|
||||
*/
|
||||
public record Error(String source, int character, String message) {
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (character >= source.length()) {
|
||||
builder.append("Error at character ").append(character);
|
||||
}
|
||||
else {
|
||||
builder.append("Error at '").append(source.charAt(character)).append("' (character ").append(character).append(")");
|
||||
}
|
||||
builder.append(": ").append(message);
|
||||
|
||||
public record Error(String message, String line, int lineNumber, int column) {
|
||||
/**
|
||||
* Generates an error by getting the relevant data from what is available while lexing/parsing
|
||||
* @param source The complete source for the code that generated this error
|
||||
* @param character The index of the current character
|
||||
* @param message The error message
|
||||
* @return An error using the provided information
|
||||
*/
|
||||
public static Error create(String source, int character, String message) {
|
||||
int lineStart = source.lastIndexOf('\n', character);
|
||||
int lineEnd = source.indexOf('\n', character);
|
||||
if (lineEnd == -1) lineEnd = source.length();
|
||||
|
||||
String line = source.substring(lineStart + 1, lineEnd);
|
||||
int lineNumber = lineStart > 0 ? (int) source.substring(0, lineStart).chars().filter(c -> c == '\n').count() : 1;
|
||||
int lineIndex = lineStart > 0 ? (int) source.substring(0, lineStart).chars().filter(c -> c == '\n').count() : 0;
|
||||
int column = character - lineStart;
|
||||
|
||||
return new Error(message, source.substring(lineStart + 1, lineEnd), lineIndex + 1, column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this error to a human-readable error message
|
||||
* @return A string representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
if (column > line.length())
|
||||
builder.append("Error at character ").append(column);
|
||||
else
|
||||
builder.append("Error at '").append(line.charAt(column - 1)).append("' (character ").append(column).append(")");
|
||||
builder.append(": ").append(message);
|
||||
|
||||
String linePrefix = String.format("%1$6d", lineNumber) + " | ";
|
||||
|
||||
builder.append('\n').append(linePrefix).append(line);
|
||||
builder.append('\n').append(" ".repeat(linePrefix.length() + (character - lineStart - 1))).append("^-- Here");
|
||||
builder.append('\n').append(" ".repeat(linePrefix.length() + (column - 1))).append("^-- Here");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ public class Parser {
|
||||
|
||||
// Helpers
|
||||
private ParseException error(String message) {
|
||||
return new ParseException(new Error(lexer.source, current.current - 1, message));
|
||||
return new ParseException(Error.create(lexer.source, current.current - 1, message));
|
||||
}
|
||||
|
||||
private TokenData consume(Token token, String message) {
|
||||
|
@ -9,17 +9,17 @@ public class ErrorTest {
|
||||
@Test
|
||||
void invalidCode() {
|
||||
assertEquals("""
|
||||
Error at 'e' (character 8): Expected number but is Boolean
|
||||
Error at 'e' (character 9): Expected number but is Boolean
|
||||
1 | 15 + true
|
||||
^-- Here""",
|
||||
assertThrows(Parser.ParseException.class, () -> Parser.parse("15 + true")).error.toString());
|
||||
assertEquals("""
|
||||
Error at ''' (character 9): Expected number but is String
|
||||
Error at ''' (character 10): Expected number but is String
|
||||
1 | 15 + 'yes'
|
||||
^-- Here""",
|
||||
assertThrows(Parser.ParseException.class, () -> Parser.parse("15 + 'yes'")).error.toString());
|
||||
assertEquals("""
|
||||
Error at '=' (character 7): Unexpected character
|
||||
Error at '=' (character 8): Unexpected character
|
||||
1 | string = 'Value'
|
||||
^-- Here""",
|
||||
assertThrows(Parser.ParseException.class, () -> Parser.parse("string = 'Value'")).error.toString());
|
||||
|
Loading…
Reference in New Issue
Block a user