diff --git a/pom.xml b/pom.xml index 65684a2..1b207e9 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ jar - 1.8 + 11 UTF-8 UTF-8 @@ -116,6 +116,19 @@ 5.7.0 test + + + org.junit.platform + junit-platform-launcher + 1.7.0 + test + + + org.junit.vintage + junit-vintage-engine + 5.7.0 + test + com.vaadin.componentfactory tooltip diff --git a/src/main/java/edu/kit/typicalc/model/parser/LambdaParser.java b/src/main/java/edu/kit/typicalc/model/parser/LambdaParser.java index b0642d9..64d693c 100644 --- a/src/main/java/edu/kit/typicalc/model/parser/LambdaParser.java +++ b/src/main/java/edu/kit/typicalc/model/parser/LambdaParser.java @@ -37,7 +37,6 @@ public class LambdaParser { */ public LambdaParser(String term) { this.lexer = new LambdaLexer(term); - nextToken(); } /** @@ -58,10 +57,13 @@ public class LambdaParser { * Returns false otherwise. * @param type the token type to compare the current token type to */ - private boolean expect(TokenType type) { + private Optional expect(TokenType type) { TokenType current = token.getType(); - nextToken(); // TODO: Fehlerbehandlung - return current == type; + Optional error = nextToken(); + if (current != type) { + return Optional.of(ParseError.UNEXPECTED_TOKEN.withToken(token)); + } + return error; } /** @@ -69,9 +71,13 @@ public class LambdaParser { * @return the term given by the String */ public Result parse() { - Result t = parseTerm(); - if (!expect(TokenType.EOF)) { - return new Result<>(null, ParseError.TOO_MANY_TOKENS); + Result t = parseTerm(true); + if (t.isError()) { + return t; + } + Optional next = expect(TokenType.EOF); + if (next.isPresent()) { + return new Result<>(null, next.get()); } return t; } @@ -80,7 +86,13 @@ public class LambdaParser { * Parses a term. * @return the term, or an error */ - private Result parseTerm() { + private Result parseTerm(boolean next) { + if (next) { + Optional error = nextToken(); + if (error.isPresent()) { + return new Result<>(null, error.get()); + } + } switch (token.getType()) { case LAMBDA: Result abs = parseAbstraction(); @@ -98,10 +110,11 @@ public class LambdaParser { private Result parseAbstraction() { nextToken(); Result var = parseVar(); - if (!expect(TokenType.DOT)) { - return new Result<>(null, ParseError.UNEXPECTED_TOKEN); + Optional next = expect(TokenType.DOT); + if (next.isPresent()) { + return new Result<>(null, next.get()); } - Result body = parseTerm(); + Result body = parseTerm(false); // TODO: Fehlerbehandlung return new Result<>(new AbsTerm(var.unwrap(), body.unwrap())); } @@ -111,22 +124,37 @@ public class LambdaParser { * @return the term, or an error */ private Result parseApplication() { - LambdaTerm left = parseAtom().unwrap(); // TODO: Fehlerbehandlung - while (ATOM_START_TOKENS.contains(token.getType())) { - LambdaTerm atom = parseAtom().unwrap(); // TODO: Fehlerbehandlung - left = new AppTerm(left, atom); + Result left = parseAtom(); + if (left.isError()) { + return left; } - return new Result<>(left); + while (ATOM_START_TOKENS.contains(token.getType())) { + Result atom = parseAtom(); + if (atom.isError()) { + return atom; + } + left = new Result<>(new AppTerm(left.unwrap(), atom.unwrap())); + } + return left; } private Result parseLet() { // TODO: Fehlerbehandlung - expect(TokenType.LET); + Optional error = expect(TokenType.LET); + if (error.isPresent()) { + return new Result<>(null, error.get()); + } VarTerm var = parseVar().unwrap(); - expect(TokenType.EQ); - LambdaTerm def = parseTerm().unwrap(); - expect(TokenType.IN); - LambdaTerm body = parseTerm().unwrap(); + error = expect(TokenType.EQ); + if (error.isPresent()) { + return new Result<>(null, error.get()); + } + LambdaTerm def = parseTerm(false).unwrap(); + error = expect(TokenType.IN); + if (error.isPresent()) { + return new Result<>(null, error.get()); + } + LambdaTerm body = parseTerm(false).unwrap(); return new Result<>(new LetTerm(var, def, body)); } @@ -145,7 +173,7 @@ public class LambdaParser { try { n = Integer.parseInt(number); } catch (NumberFormatException e) { - return new Result<>(null, ParseError.UNEXPECTED_CHARACTER); + return new Result<>(null, ParseError.UNEXPECTED_CHARACTER.withToken(token)); } nextToken(); return new Result<>(new IntegerTerm(n)); @@ -157,7 +185,7 @@ public class LambdaParser { return new Result<>(new BooleanTerm(b)); default: expect(TokenType.LP); - Result term = parseTerm(); + Result term = parseTerm(false); expect(TokenType.RP); return term; } @@ -165,8 +193,9 @@ public class LambdaParser { private Result parseVar() { String s = token.getText(); - if (!expect(TokenType.VARIABLE)) { - return new Result<>(null, ParseError.UNEXPECTED_TOKEN); + Optional next = expect(TokenType.VARIABLE); + if (next.isPresent()) { + return new Result<>(null, next.get()); } return new Result<>(new VarTerm(s)); } diff --git a/src/main/java/edu/kit/typicalc/model/parser/ParseError.java b/src/main/java/edu/kit/typicalc/model/parser/ParseError.java index dc0f6bb..24bfe7e 100644 --- a/src/main/java/edu/kit/typicalc/model/parser/ParseError.java +++ b/src/main/java/edu/kit/typicalc/model/parser/ParseError.java @@ -7,11 +7,6 @@ public enum ParseError { */ UNEXPECTED_TOKEN, - /** - * some tokens were remaining after parsing a full lambda term - */ - TOO_MANY_TOKENS, - /** * some tokens were required, but not provided */ @@ -20,5 +15,23 @@ public enum ParseError { /** * the string contained a character not allowed in that context */ - UNEXPECTED_CHARACTER + UNEXPECTED_CHARACTER; + + private Token cause; + + public ParseError withToken(Token cause) { + this.cause = cause; + return this; + } + + /** + * @return the token associated with this error, or null if none + */ + public Token getCause() { // TODO: document + return cause; + } + + ParseError() { + + } } diff --git a/src/test/java/edu/kit/typicalc/model/parser/LambdaParserTest.java b/src/test/java/edu/kit/typicalc/model/parser/LambdaParserTest.java index dbe7f74..c2f104c 100644 --- a/src/test/java/edu/kit/typicalc/model/parser/LambdaParserTest.java +++ b/src/test/java/edu/kit/typicalc/model/parser/LambdaParserTest.java @@ -85,5 +85,14 @@ class LambdaParserTest { void miscellaneousTerms() { LambdaParser parser = new LambdaParser(""); assertEquals(ParseError.TOO_FEW_TOKENS, parser.parse().unwrapError()); + parser = new LambdaParser("x)"); + assertEquals(ParseError.UNEXPECTED_TOKEN, parser.parse().unwrapError()); + System.out.println("parsing ??"); + parser = new LambdaParser("??"); + assertEquals(ParseError.UNEXPECTED_CHARACTER, parser.parse().unwrapError()); + parser = new LambdaParser("123333333333333"); + assertEquals(ParseError.UNEXPECTED_CHARACTER, parser.parse().unwrapError()); + parser = new LambdaParser("x 123333333333333"); + assertEquals(ParseError.UNEXPECTED_CHARACTER, parser.parse().unwrapError()); } }