clean up exception pretty printing

This commit is contained in:
Johannes Frohnmeyer 2023-04-18 14:54:39 +02:00
parent 7f8da417a3
commit 9fbba868da
Signed by: Johannes
GPG Key ID: E76429612C2929F4
4 changed files with 33 additions and 60 deletions

View File

@ -31,6 +31,10 @@ public class Lexer {
this.file = file;
}
public CodeLocation location() {
return new CodeLocation(start, current - 1, source, file);
}
/**
* Scans for the next token storing it in {@link Lexer#token} and {@link Lexer#lexeme}. Produces {@link Token#EOF} if the end of source code has been reached and {@link Token#Error} if there has been an error
*/

View File

@ -16,7 +16,6 @@ import io.gitlab.jfronny.muscript.error.*;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.stream.Collectors;
public class Parser {
private final Lexer lexer;
@ -63,8 +62,8 @@ public class Parser {
includes.addAll(parseMultiScript(file, filesystem, alreadyIncluded));
}
} else {
throw new ParseException(LocationalError.builder()
.setLocation(new LocationalError.Location(s, 0, row), new LocationalError.Location(s, s.length() - 1, row))
throw new ParseException(PrettyPrintError.builder()
.setLocation(new PrettyPrintError.Location(s, 0, row), new PrettyPrintError.Location(s, s.length() - 1, row))
.setMessage("Includes MUST be located at the top of the file")
.build());
}
@ -91,7 +90,7 @@ public class Parser {
advance();
Expr<?> expr = expression();
if (!isAtEnd())
throw new ParseException(LocationalError.create(lexer.source, lexer.start, lexer.current - 1, "Unexpected element after end of expression"));
throw new ParseException(PrettyPrintError.builder(lexer.location()).setMessage("Unexpected element after end of expression").build());
return expr;
}
@ -108,7 +107,7 @@ public class Parser {
expressions.add(expression());
match(Token.Semicolon); // Consume semicolon if present
}
if (expressions.isEmpty()) throw new ParseException(LocationalError.create(lexer.source, lexer.start, lexer.current - 1, "Missing any elements in closure"));
if (expressions.isEmpty()) throw new ParseException(PrettyPrintError.builder(lexer.location()).setMessage("Missing any elements in closure").build());
return new Script(expressions);
}
@ -434,11 +433,12 @@ public class Parser {
}
private ParseException error(String message) {
return new ParseException(LocationalError.create(lexer.source, current.current - 1, message));
int loc = current.current - 1;
return new ParseException(PrettyPrintError.builder(location(loc, loc)).setMessage(message).build());
}
private ParseException error(String message, Expr<?> expr) {
return new ParseException(LocationalError.create(expr.location, message));
return new ParseException(PrettyPrintError.builder(expr.location).setMessage(message).build());
}
private TokenData consume(Token token, String message) {
@ -510,14 +510,14 @@ public class Parser {
// Parse Exception
public static class ParseException extends RuntimeException {
public final LocationalError error;
public final PrettyPrintError error;
public ParseException(LocationalError error) {
public ParseException(PrettyPrintError error) {
super(error.toString());
this.error = error;
}
public ParseException(LocationalError error, Throwable cause) {
public ParseException(PrettyPrintError error, Throwable cause) {
super(error.toString(), cause);
this.error = error;
}

View File

@ -13,6 +13,8 @@ public class LocationalException extends RuntimeException {
private final CodeLocation location;
private final List<StackFrame> callStack = new LinkedList<>();
private String messageCache;
public LocationalException(CodeLocation location) {
super();
this.location = location;
@ -33,16 +35,21 @@ public class LocationalException extends RuntimeException {
this.location = location;
}
public LocationalError asPrintable() {
return LocationalError.builder()
.setSource(location.source())
.setLocation(location.chStart(), location.chEnd())
.setMessage(getLocalizedMessage())
@Override
public String getLocalizedMessage() {
// Not getMessage() to fix locations
return messageCache != null ? messageCache : (messageCache = asPrintable().toString());
}
public PrettyPrintError asPrintable() {
return PrettyPrintError.builder(location)
.setMessage(super.getMessage())
.setCallStack(callStack)
.build();
}
public LocationalException appendStack(StackFrame frame) {
messageCache = null;
callStack.add(frame);
return this;
}

View File

@ -5,8 +5,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
//TODO maybe this can be eliminated since the source is now included?
/**
* Class for storing errors with code context
* Can be generated from a LocationalException with asPrintable
@ -15,11 +13,7 @@ import java.util.*;
* @param start The location of the start of this error. Both it and its components must not be null.
* @param end The location of the end of this error. May be null.
*/
public record LocationalError(String message, Location start, @Nullable Location end, List<? extends StackFrame> callStack) {
public LocationalError(String message, Location start, @Nullable Location end) {
this(message, start, end, List.of());
}
public record PrettyPrintError(String message, Location start, @Nullable Location end, List<? extends StackFrame> callStack) {
/**
* A location in the source code
*
@ -54,42 +48,6 @@ public record LocationalError(String message, Location start, @Nullable Location
}
}
/**
* 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 start The index of the start of the expression that caused this error
* @param message The error message
* @return An error using the provided information
*/
public static LocationalError create(String source, int start, String message) {
return builder().setSource(source).setLocation(start).setMessage(message).build();
}
/**
* 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 start The index of the start of the expression that caused this error
* @param end The index of the end of the expression that caused this error
* @param message The error message
* @return An error using the provided information
*/
public static LocationalError create(String source, int start, int end, String message) {
return builder().setSource(source).setLocation(start, end).setMessage(message).build();
}
/**
* Generates an error by getting the relevant data from what is available while lexing/parsing
*
* @param location The location of the piece of code causing this
* @param message The error message
* @return An error using the provided information
*/
public static LocationalError create(CodeLocation location, String message) {
return builder().setSource(location.source()).setLocation(location.chStart(), location.chEnd()).setMessage(message).build();
}
/**
* Converts this error to a human-readable error message
*
@ -116,6 +74,10 @@ public record LocationalError(String message, Location start, @Nullable Location
return new Builder();
}
public static Builder builder(CodeLocation location) {
return builder().setSource(location.source()).setLocation(location.chStart(), location.chEnd());
}
public static class Builder {
private String message;
private Location start;
@ -163,8 +125,8 @@ public record LocationalError(String message, Location start, @Nullable Location
return this;
}
public LocationalError build() {
return new LocationalError(message, start, end, callStack);
public PrettyPrintError build() {
return new PrettyPrintError(message, start, end, callStack);
}
}
}