mirror of
https://gitlab.kit.edu/uskyk/typicalc.git
synced 2024-11-08 18:30:42 +00:00
parent
7310eec398
commit
0285305f13
@ -28,6 +28,7 @@ public class ModelImpl implements Model {
|
||||
@Override
|
||||
public Result<TypeInfererInterface, ParseError> getTypeInferer(String lambdaTerm,
|
||||
String typeAssumptions) {
|
||||
System.out.println(lambdaTerm);
|
||||
// Parse Lambda Term
|
||||
LambdaParser parser = new LambdaParser(lambdaTerm);
|
||||
Result<LambdaTerm, ParseError> result = parser.parse();
|
||||
|
@ -16,6 +16,7 @@ public class LambdaLexer {
|
||||
* the given term as a String
|
||||
*/
|
||||
private final String term;
|
||||
private final ParseError.ErrorType errorType;
|
||||
/**
|
||||
* current position in the term
|
||||
*/
|
||||
@ -27,8 +28,9 @@ public class LambdaLexer {
|
||||
*
|
||||
* @param term the term to lex
|
||||
*/
|
||||
public LambdaLexer(String term) {
|
||||
public LambdaLexer(String term, ParseError.ErrorType errorType) {
|
||||
this.term = term;
|
||||
this.errorType = errorType;
|
||||
Deque<Token> tokens = new ArrayDeque<>();
|
||||
while (true) {
|
||||
Result<Token, ParseError> token = parseNextToken();
|
||||
@ -89,13 +91,12 @@ public class LambdaLexer {
|
||||
advance();
|
||||
return new Result<>(t);
|
||||
} else {
|
||||
return new Result<>(null, ParseError.UNEXPECTED_CHARACTER
|
||||
.withCharacter(term.charAt(pos + 1), pos + 1, term, ParseError.ErrorType.TERM_ERROR));
|
||||
return new Result<>(null, ParseError.unexpectedCharacter2(
|
||||
term.charAt(pos + 1), pos + 1, term, errorType));
|
||||
}
|
||||
} else {
|
||||
return new Result<>(null,
|
||||
ParseError.UNEXPECTED_CHARACTER
|
||||
.withCharacter(' ', term.length(), term, ParseError.ErrorType.TERM_ERROR));
|
||||
ParseError.unexpectedCharacter2(' ', term.length(), term, errorType));
|
||||
}
|
||||
// bunch of single-character tokens
|
||||
case '.':
|
||||
@ -149,8 +150,7 @@ public class LambdaLexer {
|
||||
} while (pos < term.length() && Character.isLetterOrDigit(term.charAt(pos))
|
||||
&& (int) term.charAt(pos) < 128);
|
||||
if (pos < term.length() && (int) term.charAt(pos) >= 128) {
|
||||
return new Result<>(null, ParseError.UNEXPECTED_CHARACTER
|
||||
.withCharacter(term.charAt(pos), pos, term, ParseError.ErrorType.TERM_ERROR));
|
||||
return new Result<>(null, ParseError.unexpectedCharacter2(term.charAt(pos), pos, term, errorType));
|
||||
}
|
||||
String s = sb.toString();
|
||||
TokenType type;
|
||||
@ -182,8 +182,8 @@ public class LambdaLexer {
|
||||
} while (pos < term.length() && Character.isDigit(term.charAt(pos)));
|
||||
return new Result<>(new Token(TokenType.NUMBER, sb.toString(), term, startPos));
|
||||
} else {
|
||||
return new Result<>(null, ParseError.UNEXPECTED_CHARACTER.withCharacter(c, pos, term,
|
||||
ParseError.ErrorType.TERM_ERROR));
|
||||
return new Result<>(null, ParseError.unexpectedCharacter2(c, pos, term,
|
||||
errorType));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ public class LambdaParser {
|
||||
* @param term String to parse
|
||||
*/
|
||||
public LambdaParser(String term) {
|
||||
this.lexer = new LambdaLexer(term);
|
||||
this.lexer = new LambdaLexer(term, ParseError.ErrorType.TERM_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,7 +69,7 @@ public class LambdaParser {
|
||||
TokenType current = token.getType();
|
||||
Optional<ParseError> error = nextToken();
|
||||
if (current != type) {
|
||||
return Optional.of(ParseError.UNEXPECTED_TOKEN.withToken(lastToken,
|
||||
return Optional.of(ParseError.unexpectedToken(lastToken,
|
||||
ParseError.ErrorType.TERM_ERROR).expectedType(type));
|
||||
}
|
||||
return error;
|
||||
@ -91,8 +91,7 @@ public class LambdaParser {
|
||||
return t;
|
||||
}
|
||||
return new Result<>(null,
|
||||
ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(last, ParseError.ErrorType.TERM_ERROR)
|
||||
ParseError.unexpectedToken(last, ParseError.ErrorType.TERM_ERROR)
|
||||
.expectedTypes(ATOM_START_TOKENS));
|
||||
}
|
||||
|
||||
@ -109,8 +108,7 @@ public class LambdaParser {
|
||||
}
|
||||
}
|
||||
if (token.getType() == TokenType.EOF) {
|
||||
return new Result<>(null, ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(token, ParseError.ErrorType.TERM_ERROR)
|
||||
return new Result<>(null, ParseError.unexpectedToken(token, ParseError.ErrorType.TERM_ERROR)
|
||||
.expectedInput(ExpectedInput.TERM));
|
||||
}
|
||||
return parseApplication();
|
||||
@ -210,7 +208,7 @@ public class LambdaParser {
|
||||
try {
|
||||
n = Integer.parseInt(number);
|
||||
} catch (NumberFormatException e) {
|
||||
return new Result<>(null, ParseError.UNEXPECTED_CHARACTER.withToken(
|
||||
return new Result<>(null, ParseError.unexpectedCharacter(
|
||||
token, ParseError.ErrorType.TERM_ERROR));
|
||||
}
|
||||
error = nextToken();
|
||||
|
@ -1,8 +1,6 @@
|
||||
package edu.kit.typicalc.model.parser;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Errors that can occur when parsing a lambda term or type assumption.
|
||||
@ -10,17 +8,44 @@ import java.util.Optional;
|
||||
* @see LambdaLexer
|
||||
* @see LambdaParser
|
||||
*/
|
||||
public enum ParseError {
|
||||
public final class ParseError {
|
||||
|
||||
/**
|
||||
* the lambda term didn't meet the specified syntax
|
||||
*/
|
||||
UNEXPECTED_TOKEN,
|
||||
private ParseError(ErrorCause unexpectedToken) {
|
||||
this.causeEnum = unexpectedToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* the string contained a character not allowed in that context
|
||||
*/
|
||||
UNEXPECTED_CHARACTER;
|
||||
public enum ErrorCause {
|
||||
/**
|
||||
* the lambda term didn't meet the specified syntax
|
||||
*/
|
||||
UNEXPECTED_TOKEN,
|
||||
|
||||
/**
|
||||
* the string contained a character not allowed in that context
|
||||
*/
|
||||
UNEXPECTED_CHARACTER
|
||||
}
|
||||
|
||||
private final ErrorCause causeEnum;
|
||||
|
||||
public ErrorCause getCauseEnum() {
|
||||
return causeEnum;
|
||||
}
|
||||
|
||||
public static ParseError unexpectedToken(Token cause, ErrorType source) {
|
||||
var self = new ParseError(ErrorCause.UNEXPECTED_TOKEN);
|
||||
return self.withToken(cause, source);
|
||||
}
|
||||
|
||||
public static ParseError unexpectedCharacter(Token cause, ErrorType source) {
|
||||
var self = new ParseError(ErrorCause.UNEXPECTED_CHARACTER);
|
||||
return self.withToken(cause, source);
|
||||
}
|
||||
|
||||
public static ParseError unexpectedCharacter2(char cause, int position, String term, ErrorType errorType) {
|
||||
var self = new ParseError(ErrorCause.UNEXPECTED_CHARACTER);
|
||||
return self.withCharacter(cause, position, term, errorType);
|
||||
}
|
||||
|
||||
public enum ErrorType {
|
||||
/**
|
||||
@ -64,18 +89,32 @@ public enum ParseError {
|
||||
* @return this object
|
||||
*/
|
||||
public ParseError expectedType(Token.TokenType needed) {
|
||||
this.needed = Optional.of(List.of(needed));
|
||||
this.needed = Optional.of(new ArrayList<>(List.of(needed)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach expected token types to this error.
|
||||
* Set expected token types of this error.
|
||||
*
|
||||
* @param needed the possible token types
|
||||
* @return this object
|
||||
*/
|
||||
public ParseError expectedTypes(Collection<Token.TokenType> needed) {
|
||||
this.needed = Optional.of(needed);
|
||||
this.needed = Optional.of(new ArrayList<>(needed));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an expected token type to this error.
|
||||
*
|
||||
* @param needed the possible token type
|
||||
* @return this object
|
||||
*/
|
||||
public ParseError attachExpectedType(Token.TokenType needed) {
|
||||
if (this.needed.isEmpty()) {
|
||||
this.needed = Optional.of(new ArrayList<>());
|
||||
}
|
||||
this.needed.get().add(needed);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -109,9 +148,9 @@ public enum ParseError {
|
||||
/**
|
||||
* Attach a character and position to this error.
|
||||
*
|
||||
* @param cause the character
|
||||
* @param cause the character
|
||||
* @param position it's position
|
||||
* @param term the term that is parsed
|
||||
* @param term the term that is parsed
|
||||
* @return this object
|
||||
*/
|
||||
public ParseError withCharacter(char cause, int position, String term, ErrorType errorType) {
|
||||
@ -175,7 +214,36 @@ public enum ParseError {
|
||||
this.errorType = Optional.of(errorType);
|
||||
}
|
||||
|
||||
ParseError() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ParseError{"
|
||||
+ "cause=" + cause
|
||||
+ ", needed=" + needed
|
||||
+ ", expected=" + expected
|
||||
+ ", term='" + term + '\''
|
||||
+ ", wrongChar=" + wrongChar
|
||||
+ ", correctChar=" + correctChar
|
||||
+ ", position=" + position
|
||||
+ ", errorType=" + errorType
|
||||
+ '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
ParseError that = (ParseError) o;
|
||||
return wrongChar == that.wrongChar && correctChar == that.correctChar && position == that.position
|
||||
&& causeEnum == that.causeEnum && cause.equals(that.cause) && needed.equals(that.needed)
|
||||
&& expected.equals(that.expected) && term.equals(that.term) && errorType.equals(that.errorType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(causeEnum, cause, needed, expected, term, wrongChar, correctChar, position, errorType);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ public class TypeAssumptionParser {
|
||||
*/
|
||||
public Result<Map<VarTerm, TypeAbstraction>, ParseError> parse(String assumptions) {
|
||||
ParserState<Map<VarTerm, TypeAbstraction>> state = new InitialState(new LinkedHashMap<>());
|
||||
LambdaLexer lexer = new LambdaLexer(cleanAssumptionText(assumptions));
|
||||
LambdaLexer lexer = new LambdaLexer(
|
||||
cleanAssumptionText(assumptions), ParseError.ErrorType.TYPE_ASSUMPTION_ERROR);
|
||||
Optional<Token> extraToken = Optional.empty();
|
||||
while (true) {
|
||||
Token token1;
|
||||
@ -151,8 +152,8 @@ public class TypeAssumptionParser {
|
||||
case EOF:
|
||||
return new ParserResult<>(alreadyParsed);
|
||||
default:
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -171,8 +172,7 @@ public class TypeAssumptionParser {
|
||||
if (t.getType() == TokenType.COLON) {
|
||||
return new ParserResult<>(new ExpectingTypeDef(alreadyParsed, var));
|
||||
} else {
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
return new ParserResult<>(ParseError.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -201,8 +201,8 @@ public class TypeAssumptionParser {
|
||||
if (typeVariables.isEmpty()) {
|
||||
return new ParserResult<>(new ExpectingTypeVariables(alreadyParsed, var));
|
||||
} else {
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
}
|
||||
}
|
||||
if (state.isPresent()) {
|
||||
@ -245,8 +245,8 @@ public class TypeAssumptionParser {
|
||||
case COMMA:
|
||||
return new ParserResult<>(new InitialState(alreadyParsed));
|
||||
default:
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -281,8 +281,8 @@ public class TypeAssumptionParser {
|
||||
return handleInnerParenthesis(t);
|
||||
}
|
||||
if (parsedType.isPresent()) {
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
}
|
||||
Type type = parseLiteral(t.getText());
|
||||
// try parsing function type (see below)
|
||||
@ -296,8 +296,9 @@ public class TypeAssumptionParser {
|
||||
return handleInnerParenthesis(t);
|
||||
}
|
||||
if (parsedType.isEmpty()) {
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
.expectedInput(ExpectedInput.TYPE));
|
||||
}
|
||||
// parse function type
|
||||
state = Optional.of(new ParseTypeStateExpectArrow(typeVariableUniqueIndex).handle(t).getState());
|
||||
@ -315,6 +316,10 @@ public class TypeAssumptionParser {
|
||||
return new ParserResult<>(this);
|
||||
case RIGHT_PARENTHESIS:
|
||||
openParens -= 1;
|
||||
if (openParens < parenthesisInitial) { // too many closed parenthesis
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
}
|
||||
if (state.isPresent()) {
|
||||
return handleInner(t);
|
||||
}
|
||||
@ -336,28 +341,42 @@ public class TypeAssumptionParser {
|
||||
if (parsedType.isPresent()) {
|
||||
return new ParserResult<>(this); // parenthesized part may be start of function
|
||||
}
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
case COMMA:
|
||||
case EOF:
|
||||
if (state.isPresent()) {
|
||||
return handleInner(t).attachToken(t);
|
||||
}
|
||||
if (stateParenthesis.isPresent() && openParens == parenthesisInitial) {
|
||||
return handleInnerParenthesis(t).attachToken(t);
|
||||
if (stateParenthesis.isPresent()) {
|
||||
if (openParens != parenthesisInitial) { // parenthesis mismatch
|
||||
// feed dummy token to inner parser to get expected tokens at this point
|
||||
var it = handleInnerParenthesis(
|
||||
new Token(TokenType.EQUALS, "", "", 0))
|
||||
.attachToken(t);
|
||||
return it.modifyError(err -> err
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
.attachExpectedType(TokenType.RIGHT_PARENTHESIS));
|
||||
} else {
|
||||
return handleInnerParenthesis(t).attachToken(t);
|
||||
}
|
||||
}
|
||||
if (parsedType.isPresent() && openParens == parenthesisInitial) {
|
||||
return new ParserResult<>(parsedType.get()).attachToken(t);
|
||||
}
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
return new ParserResult<>(ParseError.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
.expectedInput(ExpectedInput.TYPE));
|
||||
default:
|
||||
if (state.isPresent()) {
|
||||
return handleInner(t);
|
||||
}
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
if (parsedType.isPresent()) {
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
.expectedType(TokenType.ARROW));
|
||||
}
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
@ -434,8 +453,7 @@ public class TypeAssumptionParser {
|
||||
return new ParserResult<>(this);
|
||||
}
|
||||
} else {
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
return new ParserResult<>(ParseError.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -456,20 +474,20 @@ public class TypeAssumptionParser {
|
||||
switch (t.getType()) {
|
||||
case VARIABLE:
|
||||
if (expectCommaOrDot) {
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
.expectedTypes(List.of(TokenType.COMMA, Token.TokenType.DOT)));
|
||||
}
|
||||
String input = t.getText();
|
||||
if (!TYPE_VARIABLE_PATTERN.matcher(input).matches()) {
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
}
|
||||
int i = Integer.parseInt(input.substring(1));
|
||||
TypeVariable variable = new TypeVariable(TypeVariableKind.USER_INPUT, i);
|
||||
if (variables.contains(variable)) {
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
}
|
||||
variable.setUniqueIndex(alreadyParsed.size());
|
||||
variables.add(variable);
|
||||
@ -480,8 +498,8 @@ public class TypeAssumptionParser {
|
||||
expectCommaOrDot = false;
|
||||
return new ParserResult<>(this);
|
||||
} else {
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
.expectedType(TokenType.VARIABLE));
|
||||
}
|
||||
case DOT:
|
||||
@ -490,18 +508,18 @@ public class TypeAssumptionParser {
|
||||
// parse actual type
|
||||
return new ParserResult<>(new ExpectingTypeDef(alreadyParsed, variables, var));
|
||||
} else {
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
.expectedType(TokenType.VARIABLE));
|
||||
}
|
||||
default:
|
||||
if (expectCommaOrDot) {
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
.expectedTypes(List.of(TokenType.COMMA, TokenType.DOT)));
|
||||
}
|
||||
return new ParserResult<>(ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
return new ParserResult<>(ParseError
|
||||
.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ public class ErrorView extends VerticalLayout implements LocaleChangeObserver {
|
||||
private final Paragraph hint;
|
||||
|
||||
public ErrorView(ParseError error) {
|
||||
System.out.println(error);
|
||||
this.error = error;
|
||||
VerticalLayout container = new VerticalLayout();
|
||||
container.setId(ERROR_CONTENT_ID);
|
||||
@ -72,7 +73,7 @@ public class ErrorView extends VerticalLayout implements LocaleChangeObserver {
|
||||
} else if (errorType.get() == ParseError.ErrorType.TYPE_ASSUMPTION_ERROR) {
|
||||
descriptionForError = "error.typeAssumptionForError";
|
||||
}
|
||||
switch (error) {
|
||||
switch (error.getCauseEnum()) {
|
||||
case UNEXPECTED_TOKEN:
|
||||
Optional<Token> cause = error.getCause();
|
||||
if (cause.isPresent()) {
|
||||
|
@ -6,8 +6,7 @@ import edu.kit.typicalc.util.Result;
|
||||
import nl.jqno.equalsverifier.EqualsVerifier;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class LambdaParserTest {
|
||||
private static final VarTerm X = new VarTerm("x");
|
||||
@ -97,62 +96,62 @@ class LambdaParserTest {
|
||||
void errorHandling() {
|
||||
LambdaParser parser = new LambdaParser("");
|
||||
ParseError error = parser.parse().unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, error.getCauseEnum());
|
||||
assertEquals(TokenType.EOF, error.getCause().get().getType());
|
||||
parser = new LambdaParser("λx.");
|
||||
error = parser.parse().unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, error.getCauseEnum());
|
||||
assertEquals(new Token(TokenType.EOF, "", "λx.", 3), error.getCause().get());
|
||||
assertEquals(ExpectedInput.TERM, error.getExpectedInput().get());
|
||||
parser = new LambdaParser("x)");
|
||||
error = parser.parse().unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, error.getCauseEnum());
|
||||
assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", "x)", 1), error.getCause().get());
|
||||
parser = new LambdaParser("??");
|
||||
assertEquals(ParseError.UNEXPECTED_CHARACTER, parser.parse().unwrapError());
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_CHARACTER, parser.parse().unwrapError().getCauseEnum());
|
||||
parser = new LambdaParser("aλ");
|
||||
assertEquals(ParseError.UNEXPECTED_CHARACTER, parser.parse().unwrapError());
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_CHARACTER, parser.parse().unwrapError().getCauseEnum());
|
||||
parser = new LambdaParser("ä");
|
||||
assertEquals(ParseError.UNEXPECTED_CHARACTER, parser.parse().unwrapError());
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_CHARACTER, parser.parse().unwrapError().getCauseEnum());
|
||||
parser = new LambdaParser("123333333333333");
|
||||
assertEquals(ParseError.UNEXPECTED_CHARACTER, parser.parse().unwrapError());
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_CHARACTER, parser.parse().unwrapError().getCauseEnum());
|
||||
parser = new LambdaParser("x 123333333333333");
|
||||
error = parser.parse().unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_CHARACTER, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_CHARACTER, error.getCauseEnum());
|
||||
assertEquals(new Token(TokenType.NUMBER, "123333333333333", "x 123333333333333", 2),
|
||||
error.getCause().get());
|
||||
parser = new LambdaParser("λ)");
|
||||
error = parser.parse().unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, error.getCauseEnum());
|
||||
assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", "λ)", 1), error.getCause().get());
|
||||
parser = new LambdaParser("λx=");
|
||||
error = parser.parse().unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, error.getCauseEnum());
|
||||
assertEquals(new Token(TokenType.EQUALS, "=", "λx=", 2), error.getCause().get());
|
||||
parser = new LambdaParser("λx..");
|
||||
error = parser.parse().unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, error.getCauseEnum());
|
||||
assertEquals(new Token(TokenType.DOT, ".", "λx..", 3), error.getCause().get());
|
||||
assertEquals(ExpectedInput.TERM, error.getExpectedInput().get());
|
||||
parser = new LambdaParser("let ) =");
|
||||
error = parser.parse().unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, error.getCauseEnum());
|
||||
assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", "let ) =", 4), error.getCause().get());
|
||||
parser = new LambdaParser("let x .");
|
||||
error = parser.parse().unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, error.getCauseEnum());
|
||||
assertEquals(new Token(TokenType.DOT, ".", "let x .", 6), error.getCause().get());
|
||||
parser = new LambdaParser("let x = )");
|
||||
error = parser.parse().unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, error.getCauseEnum());
|
||||
assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", "let x = )",8), error.getCause().get());
|
||||
parser = new LambdaParser("let x = y )");
|
||||
error = parser.parse().unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, error.getCauseEnum());
|
||||
assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", "let x = y )", 10), error.getCause().get());
|
||||
parser = new LambdaParser("let x = y in )");
|
||||
error = parser.parse().unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, error.getCauseEnum());
|
||||
assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", "let x = y in )", 13), error.getCause().get());
|
||||
}
|
||||
|
||||
@ -237,13 +236,24 @@ class LambdaParserTest {
|
||||
assertEquals(ExpectedInput.TERM, err.getExpectedInput().get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void changingErrors() {
|
||||
// parse error objects should behave normally
|
||||
ParseError err1 = getParseError("λx.λ");
|
||||
ParseError err2 = getParseError("λx.");
|
||||
ParseError err3 = getParseError("λx.λ");
|
||||
assertEquals(err1, err3);
|
||||
assertNotEquals(err2, err3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void equality() {
|
||||
EqualsVerifier.forClass(Token.class).usingGetClass().verify();
|
||||
EqualsVerifier.simple().forClass(ParseError.class).usingGetClass().verify();
|
||||
}
|
||||
|
||||
static ParseError getParseError(String term) {
|
||||
LambdaParser parser = new LambdaParser(term);
|
||||
var parser = new LambdaParser(term);
|
||||
return parser.parse().unwrapError();
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ class TypeAssumptionParserTest {
|
||||
Result<Map<VarTerm, TypeAbstraction>, ParseError> type = parser.parse("id: ∀ t1");
|
||||
assertTrue(type.isError());
|
||||
ParseError error = type.unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, error.getCauseEnum());
|
||||
assertEquals(Token.TokenType.EOF, error.getCause().get().getType());
|
||||
Collection<Token.TokenType> expected = error.getExpected().get();
|
||||
assertEquals(2, expected.size());
|
||||
@ -233,7 +233,7 @@ class TypeAssumptionParserTest {
|
||||
Result<Map<VarTerm, TypeAbstraction>, ParseError> type = parser.parse("id: ∀ t1, t1 : t1 -> t1");
|
||||
assertTrue(type.isError());
|
||||
ParseError error = type.unwrapError();
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, error);
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, error.getCauseEnum());
|
||||
assertEquals(Token.TokenType.VARIABLE, error.getCause().get().getType());
|
||||
assertEquals(10, error.getCause().get().getPos());
|
||||
}
|
||||
@ -258,25 +258,31 @@ class TypeAssumptionParserTest {
|
||||
|
||||
@Test
|
||||
void errors() {
|
||||
Map<String, ParseError> tests = new HashMap<>();
|
||||
Map<String, ParseError> tests = new LinkedHashMap<>();
|
||||
tests.put("",
|
||||
ParseError.UNEXPECTED_TOKEN.withToken(new Token(Token.TokenType.EOF, "", "", 0),
|
||||
ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
tests.put("ö", ParseError.UNEXPECTED_CHARACTER);
|
||||
ParseError.unexpectedToken(new Token(Token.TokenType.EOF, "", "type1:", 6),
|
||||
ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
.expectedInput(ExpectedInput.TYPE)
|
||||
.expectedType(Token.TokenType.UNIVERSAL_QUANTIFIER));
|
||||
tests.put("ö", ParseError.unexpectedCharacter2('ö', 6, "type1:ö", ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
tests.put("(x",
|
||||
ParseError.UNEXPECTED_TOKEN.withToken(new Token(Token.TokenType.EOF, "", "(x", 2),
|
||||
ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
ParseError.unexpectedToken(new Token(Token.TokenType.EOF, "", "type1:(x", 8),
|
||||
ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
.expectedTypes(List.of(Token.TokenType.ARROW, Token.TokenType.RIGHT_PARENTHESIS)));
|
||||
tests.put("-> x",
|
||||
ParseError.UNEXPECTED_TOKEN.withToken(new Token(Token.TokenType.ARROW, "->", "-> x", 0),
|
||||
ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
ParseError.unexpectedToken(new Token(Token.TokenType.ARROW, "->", "type1:-> x", 6),
|
||||
ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
.expectedInput(ExpectedInput.TYPE)
|
||||
.expectedType(Token.TokenType.UNIVERSAL_QUANTIFIER)
|
||||
);
|
||||
tests.put("x 11",
|
||||
ParseError.UNEXPECTED_TOKEN.withToken(new Token(Token.TokenType.NUMBER, "11", "x 11", 2),
|
||||
ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
tests.put("x )", ParseError.UNEXPECTED_TOKEN.withToken(new Token(Token.TokenType.RIGHT_PARENTHESIS, ")", "x )", 2),
|
||||
ParseError.unexpectedToken(new Token(Token.TokenType.NUMBER, "11", "type1:x 11", 8),
|
||||
ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)
|
||||
.expectedType(Token.TokenType.ARROW));
|
||||
tests.put("x )", ParseError.unexpectedToken(new Token(Token.TokenType.RIGHT_PARENTHESIS, ")", "type1:x )", 8),
|
||||
ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
tests.put("x -> (x) )", ParseError.unexpectedToken(new Token(Token.TokenType.RIGHT_PARENTHESIS, ")", "type1:x -> (x) )", 15),
|
||||
ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
tests.put("x -> (x) )", ParseError.UNEXPECTED_TOKEN
|
||||
.withToken(new Token(Token.TokenType.RIGHT_PARENTHESIS, ")", "x -> (x) )", 9),
|
||||
ParseError.ErrorType.TYPE_ASSUMPTION_ERROR));
|
||||
for (Map.Entry<String, ParseError> entry : tests.entrySet()) {
|
||||
TypeAssumptionParser parser = new TypeAssumptionParser();
|
||||
Result<Map<VarTerm, TypeAbstraction>, ParseError> type = parser.parse("type1:" + entry.getKey());
|
||||
@ -289,12 +295,12 @@ class TypeAssumptionParserTest {
|
||||
TypeAssumptionParser parser = new TypeAssumptionParser();
|
||||
Result<Map<VarTerm, TypeAbstraction>, ParseError> type = parser.parse("föhn: int");
|
||||
assertTrue(type.isError());
|
||||
assertEquals(ParseError.UNEXPECTED_CHARACTER, type.unwrapError());
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_CHARACTER, type.unwrapError().getCauseEnum());
|
||||
assertEquals(1, type.unwrapError().getPosition());
|
||||
parser = new TypeAssumptionParser();
|
||||
type = parser.parse("1typ:int");
|
||||
assertTrue(type.isError());
|
||||
assertEquals(ParseError.UNEXPECTED_TOKEN, type.unwrapError());
|
||||
assertEquals(ParseError.ErrorCause.UNEXPECTED_TOKEN, type.unwrapError().getCauseEnum());
|
||||
assertEquals(0, type.unwrapError().getPosition());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user