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 bfcd7c8..3d9dca0 100644 --- a/src/main/java/edu/kit/typicalc/model/parser/TypeAssumptionParser.java +++ b/src/main/java/edu/kit/typicalc/model/parser/TypeAssumptionParser.java @@ -46,6 +46,7 @@ public class TypeAssumptionParser { } public Result parseType(String type) { + // this parser is using the same lexer as the LambdaParser (to avoid types named "let" etc.) LambdaLexer lexer = new LambdaLexer(type); Result, ParseError> parsedType = parseType(lexer, 0); if (parsedType.isError()) { @@ -66,11 +67,13 @@ public class TypeAssumptionParser { Result typeResult = null; switch (t.getType()) { case LEFT_PARENTHESIS: + // recursive call, set number of open parentheses to 1 Result, ParseError> type2 = parseType(lexer, 1); typeResult = type2.map(Pair::getLeft); removedParens += type2.map(Pair::getRight).unwrapOr(1) - 1; break; case VARIABLE: + // named type or type variable type = parseLiteral(t.getText()); break; case RIGHT_PARENTHESIS: @@ -78,8 +81,10 @@ public class TypeAssumptionParser { break; case ARROW: if (type == null) { + // there was no type in front of the arrow return new Result<>(null, ParseError.UNEXPECTED_TOKEN.withToken(t)); } + // recursive call, keep open parentheses count Result, ParseError> nextType = parseType(lexer, parenCount); final Type left = type; typeResult = nextType.map(Pair::getLeft).map(right -> new FunctionType(left, right)); @@ -90,19 +95,26 @@ public class TypeAssumptionParser { default: return new Result<>(null, ParseError.UNEXPECTED_TOKEN.withToken(t)); } + // update type based on Result if (typeResult != null && typeResult.isError()) { return new Result<>(typeResult); } type = typeResult != null ? typeResult.unwrap() : type; + // after fully processing one token / a type in parenthesis, + // some type should have been parsed if (type == null) { return new Result<>(null, ParseError.TOO_FEW_TOKENS); } if (parenCount - removedParens < 0) { + // too many closing parenthesis return new Result<>(null, ParseError.UNEXPECTED_TOKEN.withToken(t)); } else if (END_TOKENS.contains(t.getType())) { + // potential end of type if (parenCount - removedParens == 0) { + // opening and closing parentheses match return new Result<>(new ImmutablePair<>(type, removedParens)); } else { + // missing closing parenthesis return new Result<>(null, ParseError.TOO_FEW_TOKENS); } } diff --git a/src/main/java/edu/kit/typicalc/view/main/TypeAssumptionField.java b/src/main/java/edu/kit/typicalc/view/main/TypeAssumptionField.java index 1f3f597..1428a1d 100644 --- a/src/main/java/edu/kit/typicalc/view/main/TypeAssumptionField.java +++ b/src/main/java/edu/kit/typicalc/view/main/TypeAssumptionField.java @@ -48,10 +48,10 @@ public class TypeAssumptionField extends HorizontalLayout implements LocaleChang private final transient TypeAssumptionParser parser = new TypeAssumptionParser(); private final TextField variableInputField; private final TextField typeInputField; - + private final Binder varBinder = new Binder<>(); private final Binder typeBinder = new Binder<>(); - + /** * Creates a new TypeAssumptionField with initial values and a callback to remove this * type assumption from the {@link TypeAssumptionsArea}. @@ -87,7 +87,7 @@ public class TypeAssumptionField extends HorizontalLayout implements LocaleChang variableInputField.addBlurListener(event -> typeBinder.validate()); typeInputField.addBlurListener(event -> varBinder.validate()); - addValidatior(); + addValidator(); add(variableInputField, typeInputField, deleteButton); setId(ASSUMPTIONS_FIELD_ID); } @@ -112,7 +112,7 @@ public class TypeAssumptionField extends HorizontalLayout implements LocaleChang return parser.parseType(parseBackType(type)).isOk(); } - private void addValidatior() { + private void addValidator() { varBinder.forField(variableInputField) .withValidator(var -> (hasCorrectVariable(var) || isEmpty()), StringUtils.EMPTY) .bind(o -> variableInputField.getEmptyValue(), null); @@ -133,10 +133,10 @@ public class TypeAssumptionField extends HorizontalLayout implements LocaleChang } return new String(rawTypeArray); } - + /** * Checks if both text fields of this type assumption are empty. - * + * * @return true if both text fields are empty, false if not */ protected boolean isEmpty() {