This commit is contained in:
ucrhh 2021-03-11 14:55:36 +01:00
commit 0c2836a27f
12 changed files with 140 additions and 56 deletions

View File

@ -69,7 +69,7 @@ public class LambdaParser {
TokenType current = token.getType(); TokenType current = token.getType();
Optional<ParseError> error = nextToken(); Optional<ParseError> error = nextToken();
if (current != type) { if (current != type) {
return Optional.of(ParseError.UNEXPECTED_TOKEN.withToken(lastToken)); return Optional.of(ParseError.UNEXPECTED_TOKEN.withToken(lastToken).expectedType(type));
} }
return error; return error;
} }
@ -84,11 +84,15 @@ public class LambdaParser {
if (t.isError()) { if (t.isError()) {
return t; return t;
} }
Token last = token;
Optional<ParseError> next = expect(TokenType.EOF); Optional<ParseError> next = expect(TokenType.EOF);
if (next.isEmpty()) { if (next.isEmpty()) {
return t; return t;
} }
return new Result<>(null, next.get()); return new Result<>(null,
(last.getType() == TokenType.EOF ? ParseError.TOO_FEW_TOKENS : ParseError.UNEXPECTED_TOKEN)
.withToken(last)
.expectedTypes(ATOM_START_TOKENS));
} }
/** /**

View File

@ -1,7 +1,11 @@
package edu.kit.typicalc.model.parser; package edu.kit.typicalc.model.parser;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
/** /**
* Errors that can occur when parsing a lambda term. * Errors that can occur when parsing a lambda term or type assumption.
* *
* @see LambdaLexer * @see LambdaLexer
* @see LambdaParser * @see LambdaParser
@ -23,7 +27,8 @@ public enum ParseError {
*/ */
UNEXPECTED_CHARACTER; UNEXPECTED_CHARACTER;
private Token cause = new Token(Token.TokenType.EOF, "", -1); private Optional<Token> cause = Optional.empty();
private Optional<Collection<Token.TokenType>> needed = Optional.empty();
private char wrongChar = '\0'; private char wrongChar = '\0';
private int position = -1; private int position = -1;
@ -34,7 +39,29 @@ public enum ParseError {
* @return this object * @return this object
*/ */
public ParseError withToken(Token cause) { public ParseError withToken(Token cause) {
this.cause = cause; this.cause = Optional.of(cause);
return this;
}
/**
* Attach an expected token type to this error.
*
* @param needed the required token type
* @return this object
*/
public ParseError expectedType(Token.TokenType needed) {
this.needed = Optional.of(List.of(needed));
return this;
}
/**
* Attach expected token types to this error.
*
* @param needed the possible token types
* @return this object
*/
public ParseError expectedTypes(Collection<Token.TokenType> needed) {
this.needed = Optional.of(needed);
return this; return this;
} }
@ -52,16 +79,29 @@ public enum ParseError {
} }
/** /**
* @return the token associated with this error, or null if none * @return the token associated with this error
*/ */
public Token getCause() { public Optional<Token> getCause() {
return cause; return cause;
} }
/**
* @return the expected/possible token(s) if this error is UNEXPECTED_TOKEN
*/
public Optional<Collection<Token.TokenType>> getExpected() {
return needed;
}
/**
* @return the wrong character if this error is UNEXPECTED_CHARACTER ('\0' otherwise)
*/
public char getWrongCharacter() { public char getWrongCharacter() {
return wrongChar; return wrongChar;
} }
/**
* @return the character position if this error is UNEXPECTED_CHARACTER
*/
public int getPosition() { public int getPosition() {
return position; return position;
} }

View File

@ -12,7 +12,7 @@ public class Token {
* VARIABLE and NUMBER have a regular expression associated with them. * VARIABLE and NUMBER have a regular expression associated with them.
* EOF is a special token to indicate that the end of file is reached. * EOF is a special token to indicate that the end of file is reached.
*/ */
enum TokenType { public enum TokenType {
LAMBDA, // λ or a backslash LAMBDA, // λ or a backslash
VARIABLE, // [a-z][a-zA-Z0-9]* except "let" or "in" or constants VARIABLE, // [a-z][a-zA-Z0-9]* except "let" or "in" or constants
LET, // let LET, // let
@ -25,7 +25,7 @@ public class Token {
DOT, // . DOT, // .
EQUALS, // = EQUALS, // =
ARROW, // -> ARROW, // ->
EOF // pseudo token if end of file is reached EOF // pseudo token if end of input is reached
} }
/** /**

View File

@ -38,16 +38,22 @@ public class TypicalcI18NProvider implements I18NProvider {
public String getTranslation(String key, Locale locale, Object... params) { public String getTranslation(String key, Locale locale, Object... params) {
ResourceBundle bundle = ResourceBundle.getBundle(LANGUAGE_BUNDLE_PREFIX, locale); ResourceBundle bundle = ResourceBundle.getBundle(LANGUAGE_BUNDLE_PREFIX, locale);
String result;
if (bundle.containsKey(key)) { if (bundle.containsKey(key)) {
return bundle.getString(key); result = bundle.getString(key);
} else { } else {
try { try {
return this.generalBundle.getString(key); result = this.generalBundle.getString(key);
} catch (MissingResourceException exception) { } catch (MissingResourceException exception) {
// this is only the case for untranslated texts // this is only the case for untranslated texts
return "?[" + key + "]?"; return "?[" + key + "]?";
} }
} }
// replace placeholders {0} ...
for (int i = 0; i < params.length; i++) {
result = result.replace(String.format("{%d}", i), params[i].toString());
}
return result;
} }
} }

View File

@ -2,7 +2,6 @@ package edu.kit.typicalc.view.content.errorcontent;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.dependency.CssImport; import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.details.Details;
import com.vaadin.flow.component.html.Div; import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.H3; import com.vaadin.flow.component.html.H3;
import com.vaadin.flow.component.html.Paragraph; import com.vaadin.flow.component.html.Paragraph;
@ -11,8 +10,12 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.i18n.LocaleChangeEvent; import com.vaadin.flow.i18n.LocaleChangeEvent;
import com.vaadin.flow.i18n.LocaleChangeObserver; import com.vaadin.flow.i18n.LocaleChangeObserver;
import edu.kit.typicalc.model.parser.ParseError; import edu.kit.typicalc.model.parser.ParseError;
import edu.kit.typicalc.model.parser.Token;
import edu.kit.typicalc.view.main.InfoContent; import edu.kit.typicalc.view.main.InfoContent;
import java.util.Collection;
import java.util.Optional;
@CssImport("./styles/view/error-view.css") @CssImport("./styles/view/error-view.css")
public class ErrorView extends VerticalLayout implements LocaleChangeObserver { public class ErrorView extends VerticalLayout implements LocaleChangeObserver {
private static final long serialVersionUID = 239587L; private static final long serialVersionUID = 239587L;
@ -21,8 +24,6 @@ public class ErrorView extends VerticalLayout implements LocaleChangeObserver {
private static final String ADDITIONAL_INFO_ID = "errorAdditionalInfo"; private static final String ADDITIONAL_INFO_ID = "errorAdditionalInfo";
private static final String ERROR_SUMMARY_ID = "errorSummary"; private static final String ERROR_SUMMARY_ID = "errorSummary";
private static final int NO_ADDITIONAL_INFO = -1;
private final H3 heading; private final H3 heading;
private final Div errorMessage; private final Div errorMessage;
private final ParseError error; private final ParseError error;
@ -44,26 +45,48 @@ public class ErrorView extends VerticalLayout implements LocaleChangeObserver {
Paragraph summary = new Paragraph(getTranslation("root." + error.toString())); Paragraph summary = new Paragraph(getTranslation("root." + error.toString()));
summary.setId(ERROR_SUMMARY_ID); summary.setId(ERROR_SUMMARY_ID);
if (error == ParseError.TOO_FEW_TOKENS) { switch (error) {
additionalInformation.add(new Span(getTranslation("root.tooFewTokensHelp"))); case TOO_FEW_TOKENS:
} else if (error == ParseError.UNEXPECTED_CHARACTER) { additionalInformation.add(new Span(getTranslation("root.tooFewTokensHelp")));
char c = error.getWrongCharacter(); break;
if (c != '\0') { case UNEXPECTED_TOKEN:
additionalInformation.add(new Span(getTranslation("root.wrongCharacter") + c)); Optional<Token> cause = error.getCause();
additionalInformation.add(new Span(getTranslation("root.position") + error.getPosition())); if (cause.isPresent()) {
} else { additionalInformation.add(new Span(getTranslation("root.wrongCharacter") + cause.get().getText()));
return summary; additionalInformation.add(new Span(getTranslation("root.position") + cause.get().getPos()));
} }
} else { break;
if (error.getCause().getPos() == NO_ADDITIONAL_INFO) { case UNEXPECTED_CHARACTER:
return summary; char c = error.getWrongCharacter();
} else { if (c != '\0') {
additionalInformation.add(new Span(getTranslation("root.wrongCharacter") + error.getCause().getText())); additionalInformation.add(new Span(getTranslation("root.wrongCharacter") + c));
additionalInformation.add(new Span(getTranslation("root.position") + error.getCause().getPos())); additionalInformation.add(new Span(getTranslation("root.position") + error.getPosition()));
} } else {
return summary;
}
break;
default:
throw new IllegalStateException(); // delete when updating to Java 12+
} }
return new Details(summary, additionalInformation); // add expected tokens, if available
Optional<Collection<Token.TokenType>> expected = error.getExpected();
if (expected.isPresent()) {
Collection<Token.TokenType> possible = expected.get();
StringBuilder sb = new StringBuilder();
for (Token.TokenType t : possible) {
if (sb.length() > 0) {
sb.append(' ');
sb.append(getTranslation("root.or"));
sb.append(' ');
}
sb.append(getTranslation("tokentype." + t));
}
additionalInformation.add(new Span(
getTranslation("error.expectedToken", sb.toString())));
}
return new Div(summary, additionalInformation);
} }
@Override @Override

View File

@ -55,12 +55,13 @@ public class InputBar extends HorizontalLayout implements LocaleChangeObserver {
protected InputBar(Consumer<Pair<String, Map<String, String>>> callback) { protected InputBar(Consumer<Pair<String, Map<String, String>>> callback) {
this.callback = callback; this.callback = callback;
setId(INPUT_BAR_ID);
infoIcon = new Button(new Icon(VaadinIcon.INFO_CIRCLE)); infoIcon = new Button(new Icon(VaadinIcon.INFO_CIRCLE));
infoIcon.addClickListener(event -> onInfoIconClick()); infoIcon.addClickListener(event -> onInfoIconClick());
inputField = new TextField(); inputField = new TextField();
inputField.getElement().setAttribute("autofocus", ""); inputField.getElement().setAttribute("autofocus", ""); // focus on page load
inputField.setPlaceholder(getTranslation("root.inputFieldPlaceholder"));
inputField.setId(INPUT_FIELD_ID); inputField.setId(INPUT_FIELD_ID);
inputField.setClearButtonVisible(true); inputField.setClearButtonVisible(true);
inputField.setMaxLength(MAX_INPUT_LENGTH); inputField.setMaxLength(MAX_INPUT_LENGTH);
@ -72,10 +73,11 @@ public class InputBar extends HorizontalLayout implements LocaleChangeObserver {
Button lambdaButton = new Button(getTranslation("root.lambda")); Button lambdaButton = new Button(getTranslation("root.lambda"));
lambdaButton.setId(LAMBDA_BUTTON_ID); lambdaButton.setId(LAMBDA_BUTTON_ID);
UI.getCurrent().getPage().executeJs("window.lambdaButtonListener($0, $1);", LAMBDA_BUTTON_ID, INPUT_FIELD_ID); UI.getCurrent().getPage().executeJs("window.lambdaButtonListener($0, $1);", LAMBDA_BUTTON_ID, INPUT_FIELD_ID);
typeAssumptions = new Button("", event -> onTypeAssumptionsButton()); typeAssumptions = new Button("", event -> onTypeAssumptionsButton());
typeAssumptions.setId(ASS_BUTTON_ID); typeAssumptions.setId(ASS_BUTTON_ID);
typeAssumptionsArea = new TypeAssumptionsArea(); typeAssumptionsArea = new TypeAssumptionsArea();
exampleButton = new Button(VaadinIcon.PAPERCLIP.create(), event -> onExampleButtonClick()); exampleButton = new Button(getTranslation("root.exampleButton"), event -> onExampleButtonClick());
exampleButton.setId(EXAMPLE_BUTTON_ID); exampleButton.setId(EXAMPLE_BUTTON_ID);
inferTypeButton = new Button("", event -> onTypeInferButtonClick()); inferTypeButton = new Button("", event -> onTypeInferButtonClick());
inferTypeButton.addClickShortcut(Key.ENTER).listenOn(this); inferTypeButton.addClickShortcut(Key.ENTER).listenOn(this);
@ -83,7 +85,6 @@ public class InputBar extends HorizontalLayout implements LocaleChangeObserver {
inferTypeButton.setId(INFER_BUTTON_ID); inferTypeButton.setId(INFER_BUTTON_ID);
add(infoIcon, typeAssumptions, lambdaButton, inputField, exampleButton, inferTypeButton); add(infoIcon, typeAssumptions, lambdaButton, inputField, exampleButton, inferTypeButton);
setId(INPUT_BAR_ID);
} }
/** /**

View File

@ -53,7 +53,6 @@ public class MainViewImpl extends AppLayout
* Creates a new MainViewImpl. * Creates a new MainViewImpl.
*/ */
public MainViewImpl() { public MainViewImpl() {
setDrawerOpened(false);
MainViewListener presenter = new Presenter(new ModelImpl(), this); MainViewListener presenter = new Presenter(new ModelImpl(), this);
upperBar = new UpperBar(presenter, this::processInput); upperBar = new UpperBar(presenter, this::processInput);
addToNavbar(upperBar); addToNavbar(upperBar);

View File

@ -1,6 +1,5 @@
package edu.kit.typicalc.view.main; package edu.kit.typicalc.view.main;
import com.vaadin.flow.component.applayout.DrawerToggle;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dependency.CssImport; import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.html.Anchor; import com.vaadin.flow.component.html.Anchor;
@ -36,7 +35,6 @@ public class UpperBar extends HorizontalLayout implements LocaleChangeObserver {
private static final String UPPER_BAR_ID = "header"; private static final String UPPER_BAR_ID = "header";
private final InputBar inputBar; private final InputBar inputBar;
private final Button toggle;
private final Button helpButton; private final Button helpButton;
private final transient MainViewListener presenter; private final transient MainViewListener presenter;
@ -45,7 +43,7 @@ public class UpperBar extends HorizontalLayout implements LocaleChangeObserver {
/** /**
* Initializes a new UpperBar with the provided mainViewListener. * Initializes a new UpperBar with the provided mainViewListener.
* *
* @param presenter the listener used to communicate with the model * @param presenter the listener used to communicate with the model
* @param inputConsumer function to handle user input * @param inputConsumer function to handle user input
*/ */
protected UpperBar(MainViewListener presenter, Consumer<Pair<String, Map<String, String>>> inputConsumer) { protected UpperBar(MainViewListener presenter, Consumer<Pair<String, Map<String, String>>> inputConsumer) {
@ -53,7 +51,6 @@ public class UpperBar extends HorizontalLayout implements LocaleChangeObserver {
this.presenter = presenter; this.presenter = presenter;
this.inputConsumer = inputConsumer; this.inputConsumer = inputConsumer;
toggle = new DrawerToggle();
H1 viewTitle = new H1(new Anchor("/", getTranslation("root.typicalc"))); H1 viewTitle = new H1(new Anchor("/", getTranslation("root.typicalc")));
viewTitle.setId(VIEW_TITLE_ID); viewTitle.setId(VIEW_TITLE_ID);
this.inputBar = new InputBar(this::typeInfer); this.inputBar = new InputBar(this::typeInfer);
@ -62,7 +59,7 @@ public class UpperBar extends HorizontalLayout implements LocaleChangeObserver {
helpButton.addClickListener(event -> new HelpDialog().open()); helpButton.addClickListener(event -> new HelpDialog().open());
helpButton.setId(HELP_ICON_ID); helpButton.setId(HELP_ICON_ID);
add(/*toggle, */viewTitle, inputBar, helpButton); add(viewTitle, inputBar, helpButton);
setId(UPPER_BAR_ID); setId(UPPER_BAR_ID);
getThemeList().set("dark", true); getThemeList().set("dark", true);
setSpacing(false); setSpacing(false);
@ -96,7 +93,6 @@ public class UpperBar extends HorizontalLayout implements LocaleChangeObserver {
@Override @Override
public void localeChange(LocaleChangeEvent event) { public void localeChange(LocaleChangeEvent event) {
toggle.getElement().setAttribute("title", getTranslation("root.drawerToggleTooltip"));
helpButton.getElement().setAttribute("title", getTranslation("root.helpIconTooltip")); helpButton.getElement().setAttribute("title", getTranslation("root.helpIconTooltip"));
} }
} }

View File

@ -1,6 +1,7 @@
root.close=Schließen root.close=Schließen
root.save=Speichern root.save=Speichern
root.copied=LaTeX-Code in Zwischenablage kopiert. root.copied=LaTeX-Code in Zwischenablage kopiert.
root.exampleButton=📂 Beispiele
root.selectExample=Beispiel auswählen: root.selectExample=Beispiel auswählen:
root.typeInfer=Typisieren root.typeInfer=Typisieren
root.operatingHelp=Hilfe root.operatingHelp=Hilfe
@ -100,6 +101,21 @@ root.UNEXPECTED_CHARACTER=Die Eingabe enthält ein Zeichen, welches an dieser St
error.heading=Syntaktisch falsche Eingabe! error.heading=Syntaktisch falsche Eingabe!
root.wrongCharacter=Falsches Zeichen: \u0020 root.wrongCharacter=Falsches Zeichen: \u0020
root.position=An Position: \u0020 root.position=An Position: \u0020
error.expectedToken=Erwartet: {0}
tokentype.LAMBDA=λ
tokentype.VARIABLE=Variable
tokentype.LET=let
tokentype.IN=in
tokentype.TRUE=true
tokentype.FALSE=false
tokentype.NUMBER=Zahl
tokentype.LEFT_PARENTHESIS=(
tokentype.RIGHT_PARENTHESIS=)
tokentype.DOT=.
tokentype.EQUALS==
tokentype.ARROW=->
tokentype.EOF=Ende der Eingabe
root.or=oder
root.slideExp=Typicalc ist eine Anwendung zur Visualisierung von Typinferenz. In der folgenden Slideshow wird ein \ root.slideExp=Typicalc ist eine Anwendung zur Visualisierung von Typinferenz. In der folgenden Slideshow wird ein \
Beispielszenario mit den wichtigsten Funktionen der Website vorgeführt. Das relevante Bedienelement ist jeweils mit \ Beispielszenario mit den wichtigsten Funktionen der Website vorgeführt. Das relevante Bedienelement ist jeweils mit \
einem roten Rahmen hervorgehoben. Zwischen einzelnen Slides kann mithilfe der Knöpfe am unteren Ende der Seite \ einem roten Rahmen hervorgehoben. Zwischen einzelnen Slides kann mithilfe der Knöpfe am unteren Ende der Seite \
@ -129,7 +145,6 @@ verwendeten Pakete aufgelistet.
root.correctAssumptions=Korrigiere oder lösche die ungültigen Typannahmen (rot hinterlegt) \ root.correctAssumptions=Korrigiere oder lösche die ungültigen Typannahmen (rot hinterlegt) \
vor dem Schließen des Dialogs. vor dem Schließen des Dialogs.
root.copyLatexTooltip=Kopiere LaTeX-code root.copyLatexTooltip=Kopiere LaTeX-code
root.drawerToggleTooltip=Ableitungsregeln
root.helpIconTooltip=Hilfe und Sprachwechsel root.helpIconTooltip=Hilfe und Sprachwechsel
root.exampleTooltip=Beispielterme root.exampleTooltip=Beispielterme
root.shareButtonTooltip=LaTeX-Code und Permalink root.shareButtonTooltip=LaTeX-Code und Permalink

View File

@ -1,6 +1,7 @@
root.close=Close root.close=Close
root.save=Save root.save=Save
root.copied=LaTeX code copied to clipboard. root.copied=LaTeX code copied to clipboard.
root.exampleButton=📂 Examples
root.selectExample=Select example: root.selectExample=Select example:
root.typeInfer=Type root.typeInfer=Type
root.operatingHelp=Help root.operatingHelp=Help
@ -121,7 +122,6 @@ root.text8=The dialog contains a permalink to the current page, the LaTeX-code o
to compile the code. to compile the code.
root.correctAssumptions=Correct or delete the invalid type assumptions (red background) before closing the dialog. root.correctAssumptions=Correct or delete the invalid type assumptions (red background) before closing the dialog.
root.copyLatexTooltip=Copy LaTeX code root.copyLatexTooltip=Copy LaTeX code
root.drawerToggleTooltip=Type inference rules
root.helpIconTooltip=Help and language switch root.helpIconTooltip=Help and language switch
root.exampleTooltip=Example terms root.exampleTooltip=Example terms
root.shareButtonTooltip=LaTeX code and permalink root.shareButtonTooltip=LaTeX code and permalink

View File

@ -98,7 +98,7 @@ class LambdaParserTest {
parser = new LambdaParser("x)"); parser = new LambdaParser("x)");
ParseError error = parser.parse().unwrapError(); ParseError error = parser.parse().unwrapError();
assertEquals(ParseError.UNEXPECTED_TOKEN, error); assertEquals(ParseError.UNEXPECTED_TOKEN, error);
assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", 1), error.getCause()); assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", 1), error.getCause().get());
parser = new LambdaParser("??"); parser = new LambdaParser("??");
assertEquals(ParseError.UNEXPECTED_CHARACTER, parser.parse().unwrapError()); assertEquals(ParseError.UNEXPECTED_CHARACTER, parser.parse().unwrapError());
parser = new LambdaParser(""); parser = new LambdaParser("");
@ -110,39 +110,39 @@ class LambdaParserTest {
parser = new LambdaParser("x 123333333333333"); parser = new LambdaParser("x 123333333333333");
error = parser.parse().unwrapError(); error = parser.parse().unwrapError();
assertEquals(ParseError.UNEXPECTED_CHARACTER, error); assertEquals(ParseError.UNEXPECTED_CHARACTER, error);
assertEquals(new Token(TokenType.NUMBER, "123333333333333", 2), error.getCause()); assertEquals(new Token(TokenType.NUMBER, "123333333333333", 2), error.getCause().get());
parser = new LambdaParser("λ)"); parser = new LambdaParser("λ)");
error = parser.parse().unwrapError(); error = parser.parse().unwrapError();
assertEquals(ParseError.UNEXPECTED_TOKEN, error); assertEquals(ParseError.UNEXPECTED_TOKEN, error);
assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", 1), error.getCause()); assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", 1), error.getCause().get());
parser = new LambdaParser("λx="); parser = new LambdaParser("λx=");
error = parser.parse().unwrapError(); error = parser.parse().unwrapError();
assertEquals(ParseError.UNEXPECTED_TOKEN, error); assertEquals(ParseError.UNEXPECTED_TOKEN, error);
assertEquals(new Token(TokenType.EQUALS, "=", 2), error.getCause()); assertEquals(new Token(TokenType.EQUALS, "=", 2), error.getCause().get());
parser = new LambdaParser("λx.."); parser = new LambdaParser("λx..");
error = parser.parse().unwrapError(); error = parser.parse().unwrapError();
assertEquals(ParseError.UNEXPECTED_TOKEN, error); assertEquals(ParseError.UNEXPECTED_TOKEN, error);
assertEquals(new Token(TokenType.DOT, ".", 3), error.getCause()); assertEquals(new Token(TokenType.DOT, ".", 3), error.getCause().get());
parser = new LambdaParser("let ) ="); parser = new LambdaParser("let ) =");
error = parser.parse().unwrapError(); error = parser.parse().unwrapError();
assertEquals(ParseError.UNEXPECTED_TOKEN, error); assertEquals(ParseError.UNEXPECTED_TOKEN, error);
assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", 4), error.getCause()); assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", 4), error.getCause().get());
parser = new LambdaParser("let x ."); parser = new LambdaParser("let x .");
error = parser.parse().unwrapError(); error = parser.parse().unwrapError();
assertEquals(ParseError.UNEXPECTED_TOKEN, error); assertEquals(ParseError.UNEXPECTED_TOKEN, error);
assertEquals(new Token(TokenType.DOT, ".", 6), error.getCause()); assertEquals(new Token(TokenType.DOT, ".", 6), error.getCause().get());
parser = new LambdaParser("let x = )"); parser = new LambdaParser("let x = )");
error = parser.parse().unwrapError(); error = parser.parse().unwrapError();
assertEquals(ParseError.UNEXPECTED_TOKEN, error); assertEquals(ParseError.UNEXPECTED_TOKEN, error);
assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", 8), error.getCause()); assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", 8), error.getCause().get());
parser = new LambdaParser("let x = y )"); parser = new LambdaParser("let x = y )");
error = parser.parse().unwrapError(); error = parser.parse().unwrapError();
assertEquals(ParseError.UNEXPECTED_TOKEN, error); assertEquals(ParseError.UNEXPECTED_TOKEN, error);
assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", 10), error.getCause()); assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", 10), error.getCause().get());
parser = new LambdaParser("let x = y in )"); parser = new LambdaParser("let x = y in )");
error = parser.parse().unwrapError(); error = parser.parse().unwrapError();
assertEquals(ParseError.UNEXPECTED_TOKEN, error); assertEquals(ParseError.UNEXPECTED_TOKEN, error);
assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", 13), error.getCause()); assertEquals(new Token(TokenType.RIGHT_PARENTHESIS, ")", 13), error.getCause().get());
} }
@Test @Test

View File

@ -210,7 +210,7 @@ class TypeAssumptionParserTest {
Result<Map<VarTerm, TypeAbstraction>, ParseError> type = parser.parse(Map.of("type1", entry.getKey())); Result<Map<VarTerm, TypeAbstraction>, ParseError> type = parser.parse(Map.of("type1", entry.getKey()));
assertTrue(type.isError()); assertTrue(type.isError());
assertEquals(entry.getValue(), type.unwrapError()); assertEquals(entry.getValue(), type.unwrapError());
if (entry.getValue().getCause().getPos() != -1) { if (entry.getValue().getCause().isPresent()) {
assertEquals(entry.getValue().getCause(), type.unwrapError().getCause()); assertEquals(entry.getValue().getCause(), type.unwrapError().getCause());
} }
} }