diff --git a/src/main/java/edu/kit/typicalc/model/parser/TypeAssumptionParser.java b/src/main/java/edu/kit/typicalc/model/parser/TypeAssumptionParser.java index 33cb5d2..fda5193 100644 --- a/src/main/java/edu/kit/typicalc/model/parser/TypeAssumptionParser.java +++ b/src/main/java/edu/kit/typicalc/model/parser/TypeAssumptionParser.java @@ -1,55 +1,22 @@ package edu.kit.typicalc.model.parser; -import edu.kit.typicalc.model.parser.Token.TokenType; -import edu.kit.typicalc.model.term.*; +import com.helger.commons.collection.map.MapEntry; +import edu.kit.typicalc.model.term.VarTerm; import edu.kit.typicalc.model.type.*; import edu.kit.typicalc.util.Result; import java.util.*; -import java.util.function.UnaryOperator; import java.util.regex.Matcher; import java.util.regex.Pattern; - /** * Parser for type assumptions. */ public class TypeAssumptionParser { private static final Pattern TYPE_VARIABLE_PATTERN = Pattern.compile("t(\\d+)"); - - /** - * Parse the given type assumptions. - * - * @param assumptions the type assumptions - * @return if successful, a map of the type assumptions, otherwise an error - */ - public Result, ParseError> parse(String assumptions) { - ParserState> state = new InitialState(new LinkedHashMap<>()); - LambdaLexer lexer = new LambdaLexer( - cleanAssumptionText(assumptions), ParseError.ErrorType.TYPE_ASSUMPTION_ERROR); - Optional extraToken = Optional.empty(); - while (true) { - Token token1; - if (extraToken.isPresent()) { - token1 = extraToken.get(); - } else { - Result token = lexer.nextToken(); - if (token.isError()) { - return token.castError(); - } - token1 = token.unwrap(); - } - ParserResult> result = state.handle(token1); - if (result.isResult()) { - return new Result<>(result.getResult()); - } else if (result.isError()) { - return new Result<>(null, result.getError()); - } else { - state = result.getState(); - extraToken = result.extraToken(); - } - } - } + private int typeVariableUniqueIndex = 0; + private Token currentToken = new Token(Token.TokenType.EOF, "Init", "Init", -1); + private LambdaLexer lexer; private String cleanAssumptionText(String text) { return text.replace('₀', '0') @@ -65,468 +32,237 @@ public class TypeAssumptionParser { .replace('τ', 't'); } - private static class ParserResult { - private Optional> newState = Optional.empty(); - private Optional error = Optional.empty(); - private Optional result = Optional.empty(); - private Optional extraToken = Optional.empty(); - - ParserResult(ParseError e) { - this.error = Optional.of(e); - } - - ParserResult(ParserState state) { - this.newState = Optional.of(state); - } - - ParserResult(T result) { - this.result = Optional.of(result); - } - - boolean isTransition() { - return newState.isPresent(); - } - - ParserState getState() { - return newState.get(); - } - - boolean isError() { - return error.isPresent(); - } - - ParseError getError() { - return error.get(); - } - - ParserResult castError() { - return new ParserResult<>(error.get()); - } - - boolean isResult() { - return result.isPresent(); - } - - T getResult() { - return result.get(); - } - - ParserResult attachToken(Token t) { - this.extraToken = Optional.of(t); - return this; - } - - ParserResult copyToken(ParserResult other) { - this.extraToken = other.extraToken; - return this; - } - - ParserResult modifyError(UnaryOperator fun) { - if (error.isPresent()) { - error = Optional.of(fun.apply(error.get())); - } - return this; - } - - Optional extraToken() { - return this.extraToken; + private Type parseLiteral(String text) { + Matcher typeVariableMatcher = TYPE_VARIABLE_PATTERN.matcher(text); + if (typeVariableMatcher.matches()) { + int typeVariableIndex = Integer.parseInt(typeVariableMatcher.group(1)); + TypeVariable var = new TypeVariable(TypeVariableKind.USER_INPUT, typeVariableIndex); + var.setUniqueIndex(typeVariableUniqueIndex); + return var; + } else { + return new NamedType(text); } } - private interface ParserState { - ParserResult handle(Token t); + public Result, ParseError> parse(String assumptions) { + lexer = new LambdaLexer( + cleanAssumptionText(assumptions), ParseError.ErrorType.TYPE_ASSUMPTION_ERROR); + return parseTU(); } - private static class InitialState implements ParserState> { - private final Map alreadyParsed; - - InitialState(Map alreadyParsed) { - this.alreadyParsed = alreadyParsed; - } - - @Override - public ParserResult> handle(Token t) { - switch (t.getType()) { - case VARIABLE: - return new ParserResult<>(new ExpectingColon(alreadyParsed, new VarTerm(t.getText()))); - case EOF: - return new ParserResult<>(alreadyParsed); - default: - return new ParserResult<>(ParseError - .unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)); + /** + * parses Type Environment + * @return if successful, a map of the type assumptions, otherwise an error + */ + public Result, ParseError> parseTU() { + HashMap map = new HashMap<>(); + while (true) { + Result nextLexerToken = lexer.nextToken(); + if (nextLexerToken.isError()) { + return nextLexerToken.castError(); } - } - } + currentToken = nextLexerToken.unwrap(); - private static class ExpectingColon implements ParserState> { - private final Map alreadyParsed; - private final VarTerm var; - - ExpectingColon(Map alreadyParsed, VarTerm var) { - this.alreadyParsed = alreadyParsed; - this.var = var; - } - - @Override - public ParserResult> handle(Token t) { - if (t.getType() == TokenType.COLON) { - return new ParserResult<>(new ExpectingTypeDef(alreadyParsed, var)); - } else { - return new ParserResult<>(ParseError - .unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR) - .expectedType(TokenType.COLON)); + if (currentToken.getType() == Token.TokenType.EOF) { + return new Result<>(map, null); } - } - } - - private static class ExpectingTypeDef implements ParserState> { - private final Map alreadyParsed; - private final Set typeVariables; - private final VarTerm var; - private Optional> state = Optional.empty(); - - ExpectingTypeDef(Map alreadyParsed, VarTerm var) { - this.alreadyParsed = alreadyParsed; - this.typeVariables = new TreeSet<>(); - this.var = var; - } - - ExpectingTypeDef(Map alreadyParsed, Set typeVariables, VarTerm var) { - this.alreadyParsed = alreadyParsed; - this.typeVariables = typeVariables; - this.var = var; - } - - @Override - public ParserResult> handle(Token t) { - if (t.getType() == TokenType.UNIVERSAL_QUANTIFIER) { - if (typeVariables.isEmpty()) { - return new ParserResult<>(new ExpectingTypeVariables(alreadyParsed, var)); - } else { - return new ParserResult<>(ParseError - .unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)); - } - } - if (state.isPresent()) { - ParserState status = state.get(); - // already parsing type - ParserResult result = status.handle(t); - if (result.isResult()) { - alreadyParsed.put(var, new TypeAbstraction(result.getResult(), typeVariables)); - return new ParserResult<>(new ExpectingCommaBeforeNextType(alreadyParsed)) - .copyToken(result); - } else if (result.isError()) { - return result.castError(); - } else { - state = Optional.of(result.getState()); - return new ParserResult<>(this); - } - } - // attempt to parse as type - ParserResult result = new ParseTypeState1(alreadyParsed.size()).handle(t); + Result, ParseError> result = parseTA(); if (result.isError()) { - return result.modifyError(error -> error.expectedType(TokenType.UNIVERSAL_QUANTIFIER)).castError(); + return result.castError(); } - state = Optional.of(result.getState()); - return new ParserResult<>(this); - } - } + map.put(result.unwrap().getKey(), result.unwrap().getValue()); - private static class ExpectingCommaBeforeNextType implements ParserState> { - private final Map alreadyParsed; - - ExpectingCommaBeforeNextType(Map alreadyParsed) { - this.alreadyParsed = alreadyParsed; - } - - @Override - public ParserResult> handle(Token t) { - switch (t.getType()) { - case EOF: - return new ParserResult<>(alreadyParsed); - case COMMA: - return new ParserResult<>(new InitialState(alreadyParsed)); - default: - return new ParserResult<>(ParseError - .unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)); + if (currentToken.getType() == Token.TokenType.EOF) { + return new Result<>(map, null); + } + typeVariableUniqueIndex++; + if (currentToken.getType() != Token.TokenType.COMMA) { + return new Result<>(null, ParseError.unexpectedToken(currentToken, + ParseError.ErrorType.TYPE_ASSUMPTION_ERROR).expectedType(Token.TokenType.COMMA)); } } } /** - * Main type parsing state. + * Parses single Type Assumption + * @return if successful, a type assumption, otherwise an error */ - private static class ParseTypeState1 implements ParserState { - private Optional parsedType = Optional.empty(); - private Optional> state = Optional.empty(); - private Optional> stateParenthesis = Optional.empty(); - private int parenthesisInitial = 0; - private int openParens = 0; - - /** - * Attached to any parsed type variables. - */ - private final int typeVariableUniqueIndex; - - ParseTypeState1(int typeVariableUniqueIndex) { - this.typeVariableUniqueIndex = typeVariableUniqueIndex; + public Result, ParseError> parseTA() { + VarTerm term; + if (currentToken.getType() == Token.TokenType.VARIABLE) { + term = new VarTerm(currentToken.getText()); + } else { + return new Result<>(null, ParseError.unexpectedToken(currentToken, + ParseError.ErrorType.TYPE_ASSUMPTION_ERROR).expectedType(Token.TokenType.VARIABLE)); } - @Override - public ParserResult handle(Token t) { - switch (t.getType()) { - case VARIABLE: - if (state.isPresent()) { - return handleInner(t); - } - if (stateParenthesis.isPresent()) { - return handleInnerParenthesis(t); - } - if (parsedType.isPresent()) { - return new ParserResult<>(ParseError - .unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)); - } - Type type = parseLiteral(t.getText()); - // try parsing function type (see below) - this.parsedType = Optional.of(type); - return new ParserResult<>(this); - case ARROW: - if (state.isPresent()) { - return handleInner(t); - } - if (stateParenthesis.isPresent()) { - return handleInnerParenthesis(t); - } - if (parsedType.isEmpty()) { - 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()); - return new ParserResult<>(this); - case LEFT_PARENTHESIS: - openParens += 1; - if (state.isPresent()) { - return handleInner(t); - } - if (stateParenthesis.isPresent()) { - return handleInnerParenthesis(t); - } - stateParenthesis = Optional.of(new ParseTypeState1(typeVariableUniqueIndex)); - parenthesisInitial = openParens - 1; - 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); - } - if (stateParenthesis.isPresent()) { - if (openParens == parenthesisInitial) { - // inner state is done parsing - ParserResult result = handleInnerParenthesis( - new Token(TokenType.EOF, "", "", -1)); - if (result.isError()) { - return result - // replace dummy EOF token - .modifyError(err -> - err.withToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)) - .castError(); - } else { - parsedType = Optional.of(result.getResult()); - stateParenthesis = Optional.empty(); - } - } else { - return handleInnerParenthesis(t); - } - } - if (parsedType.isPresent()) { - return new ParserResult<>(this); // parenthesized part may be start of function - } - 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()) { - 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.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR) - .expectedInput(ExpectedInput.TYPE)); - default: - if (state.isPresent()) { - return handleInner(t); - } - 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)); - } + Result nextLexerToken = lexer.nextToken(); + if (nextLexerToken.isError()) { + return nextLexerToken.castError(); + } + currentToken = nextLexerToken.unwrap(); + + if (currentToken.getType() != Token.TokenType.COLON) { + return new Result<>(null, ParseError.unexpectedToken(currentToken, + ParseError.ErrorType.TYPE_ASSUMPTION_ERROR).expectedType(Token.TokenType.COLON)); } - private ParserResult handleInner(Token t) { - ParserState status = state.get(); - // already parsing right type of function - ParserResult result = status.handle(t); - if (result.isResult()) { - return new ParserResult(new FunctionType(parsedType.get(), result.getResult())).copyToken(result); - } else if (result.isError()) { - return result.castError(); - } else { - state = Optional.of(result.getState()); - return new ParserResult<>(this); - } - } - - private ParserResult handleInnerParenthesis(Token t) { - ParserState status = stateParenthesis.get(); - // already parsing right type of function - ParserResult result = status.handle(t); - if (result.isResult()) { - return new ParserResult<>(result.getResult()).copyToken(result); - } else if (result.isError()) { - return result.castError(); - } else { - stateParenthesis = Optional.of(result.getState()); - return new ParserResult<>(this); - } - } - - private Type parseLiteral(String text) { - Matcher typeVariableMatcher = TYPE_VARIABLE_PATTERN.matcher(text); - if (typeVariableMatcher.matches()) { - int typeVariableIndex = Integer.parseInt(typeVariableMatcher.group(1)); - TypeVariable var = new TypeVariable(TypeVariableKind.USER_INPUT, typeVariableIndex); - var.setUniqueIndex(typeVariableUniqueIndex); - return var; - } else { - return new NamedType(text); - } + Result result = parseType(); + if (result.isError()) { + return result.castError(); } + return new Result<>(new MapEntry<>(term, result.unwrap())); } - private static class ParseTypeStateExpectArrow implements ParserState { - private Optional> state = Optional.empty(); - - /** - * Attached to any parsed type variables. - */ - private final int typeVariableUniqueIndex; - - ParseTypeStateExpectArrow(int typeVariableUniqueIndex) { - this.typeVariableUniqueIndex = typeVariableUniqueIndex; + public Result parseType() { + Result nextLexerToken = lexer.nextToken(); + if (nextLexerToken.isError()) { + return nextLexerToken.castError(); } + currentToken = nextLexerToken.unwrap(); - @Override - public ParserResult handle(Token t) { - if (t.getType() == TokenType.ARROW && state.isEmpty()) { - // try parsing remainder as type - state = Optional.of(new ParseTypeState1(typeVariableUniqueIndex)); - return new ParserResult<>(this); - } - if (state.isPresent()) { - ParserState status = state.get(); - // already parsing type - ParserResult result = status.handle(t); - if (result.isResult()) { - return result; - } else if (result.isError()) { - return result.castError(); - } else { - state = Optional.of(result.getState()); - return new ParserResult<>(this); + TreeSet quantifiedVariables = new TreeSet<>(); + if (currentToken.getType() == Token.TokenType.UNIVERSAL_QUANTIFIER) { + while (true) { + nextLexerToken = lexer.nextToken(); + if (nextLexerToken.isError()) { + return nextLexerToken.castError(); + } + currentToken = nextLexerToken.unwrap(); + + if (currentToken.getType() != Token.TokenType.VARIABLE) { + return new Result<>(null, + ParseError.unexpectedToken(currentToken, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR) + .expectedType(Token.TokenType.VARIABLE)); + } + String input = currentToken.getText(); + if (!TYPE_VARIABLE_PATTERN.matcher(input).matches()) { + return new Result<>(null, + ParseError.unexpectedToken(currentToken, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)); + } + int i = Integer.parseInt(input.substring(1)); + TypeVariable v = new TypeVariable(TypeVariableKind.USER_INPUT, i); + v.setUniqueIndex(typeVariableUniqueIndex); + + for (TypeVariable var : quantifiedVariables) { + if (var.equals(v)) { + return new Result<>(null, + ParseError.unexpectedToken(currentToken, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)); + } + } + quantifiedVariables.add(v); + + nextLexerToken = lexer.nextToken(); + if (nextLexerToken.isError()) { + return nextLexerToken.castError(); + } + currentToken = nextLexerToken.unwrap(); + + if (currentToken.getType() != Token.TokenType.COMMA) { + if (currentToken.getType() != Token.TokenType.DOT) { + return new Result<>(null, + ParseError.unexpectedToken(currentToken, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR) + .expectedTypes(List.of(Token.TokenType.COMMA, Token.TokenType.DOT))); + } + nextLexerToken = lexer.nextToken(); + if (nextLexerToken.isError()) { + return nextLexerToken.castError(); + } + currentToken = nextLexerToken.unwrap(); + break; } - } else { - return new ParserResult<>(ParseError.unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)); } } + + if (currentToken.getType() != Token.TokenType.VARIABLE && currentToken.getType() + != Token.TokenType.LEFT_PARENTHESIS) { + return new Result<>(null, + ParseError.unexpectedToken(currentToken, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR) + .expectedInput(ExpectedInput.TYPE) + .expectedType(Token.TokenType.UNIVERSAL_QUANTIFIER)); + } + + Result result = parseSingleType(); + if (result.isError()) { + return result.castError(); + } + return new Result<>(new TypeAbstraction(result.unwrap(), quantifiedVariables)); + } + + public Result parseSingleType() { + + Result result = parseSimpleType(); + if (result.isError()) { + return result.castError(); + } + Type type1 = result.unwrap(); + + Result nextLexerToken = lexer.nextToken(); + if (nextLexerToken.isError()) { + return nextLexerToken.castError(); + } + currentToken = nextLexerToken.unwrap(); + + Result, ParseError> result2 = parseRest(); + if (result2.isError()) { + return result2.castError(); + } + Optional type2 = result2.unwrap(); + if (type2.isEmpty()) { + return new Result<>(type1); + } else { + return new Result<>(new FunctionType(type1, type2.get())); + } } - private static class ExpectingTypeVariables implements ParserState> { - private final Map alreadyParsed; - private final VarTerm var; - private final Set variables = new TreeSet<>(); - private boolean expectCommaOrDot = false; - - ExpectingTypeVariables(Map alreadyParsed, VarTerm var) { - this.alreadyParsed = alreadyParsed; - this.var = var; - } - - @Override - public ParserResult> handle(Token t) { - switch (t.getType()) { - case VARIABLE: - if (expectCommaOrDot) { - 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 - .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 - .unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)); - } - variable.setUniqueIndex(alreadyParsed.size()); - variables.add(variable); - expectCommaOrDot = true; - return new ParserResult<>(this); - case COMMA: - if (expectCommaOrDot) { - expectCommaOrDot = false; - return new ParserResult<>(this); - } else { - return new ParserResult<>(ParseError - .unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR) - .expectedType(TokenType.VARIABLE)); - } - case DOT: - if (expectCommaOrDot) { - // list of type variables is complete - // parse actual type - return new ParserResult<>(new ExpectingTypeDef(alreadyParsed, variables, var)); - } else { - return new ParserResult<>(ParseError - .unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR) - .expectedType(TokenType.VARIABLE)); - } - default: - if (expectCommaOrDot) { - return new ParserResult<>(ParseError - .unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR) - .expectedTypes(List.of(TokenType.COMMA, TokenType.DOT))); - } - return new ParserResult<>(ParseError - .unexpectedToken(t, ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)); + public Result parseSimpleType() { + if (currentToken.getType() == Token.TokenType.VARIABLE) { + Type type = parseLiteral(currentToken.getText()); + return new Result<>(type); + } else if (currentToken.getType() == Token.TokenType.LEFT_PARENTHESIS) { + Result nextLexerToken = lexer.nextToken(); + if (nextLexerToken.isError()) { + return nextLexerToken.castError(); } + currentToken = nextLexerToken.unwrap(); + + Result result = parseSingleType(); + if (result.isError()) { + return result.castError(); + } + Type type = result.unwrap(); + + if (currentToken.getType() != Token.TokenType.RIGHT_PARENTHESIS) { + return new Result<>(null, ParseError.unexpectedToken(currentToken, + ParseError.ErrorType.TYPE_ASSUMPTION_ERROR) + .expectedTypes(List.of(Token.TokenType.ARROW, Token.TokenType.RIGHT_PARENTHESIS))); + } + return new Result<>(type); + } + return new Result<>(null, ParseError.unexpectedToken(currentToken, + ParseError.ErrorType.TYPE_ASSUMPTION_ERROR).expectedInput(ExpectedInput.TYPE)); + } + + public Result, ParseError> parseRest() { + switch (currentToken.getType()) { + case ARROW: + Result nextLexerToken = lexer.nextToken(); + if (nextLexerToken.isError()) { + return nextLexerToken.castError(); + } + currentToken = nextLexerToken.unwrap(); + + Result result = parseSingleType(); + if (result.isError()) { + return result.castError(); + } + return new Result<>(Optional.of(result.unwrap()), null); + case VARIABLE: + case NUMBER: + return new Result<>(null, ParseError.unexpectedToken(currentToken, + ParseError.ErrorType.TYPE_ASSUMPTION_ERROR).expectedType(Token.TokenType.ARROW)); + default: + return new Result<>(Optional.empty(), null); } } } diff --git a/src/test/java/edu/kit/typicalc/model/parser/TypeAssumptionParserTest.java b/src/test/java/edu/kit/typicalc/model/parser/TypeAssumptionParserTest.java index 74243a5..4a78cd4 100644 --- a/src/test/java/edu/kit/typicalc/model/parser/TypeAssumptionParserTest.java +++ b/src/test/java/edu/kit/typicalc/model/parser/TypeAssumptionParserTest.java @@ -280,9 +280,11 @@ class TypeAssumptionParserTest { 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)); + ParseError.ErrorType.TYPE_ASSUMPTION_ERROR) + .expectedType(Token.TokenType.COMMA)); tests.put("x -> (x) )", ParseError.unexpectedToken(new Token(Token.TokenType.RIGHT_PARENTHESIS, ")", "type1:x -> (x) )", 15), - ParseError.ErrorType.TYPE_ASSUMPTION_ERROR)); + ParseError.ErrorType.TYPE_ASSUMPTION_ERROR) + .expectedType(Token.TokenType.COMMA)); for (Map.Entry entry : tests.entrySet()) { TypeAssumptionParser parser = new TypeAssumptionParser(); Result, ParseError> type = parser.parse("type1:" + entry.getKey());