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