From ebbf8b013a31cd14acdcd36e9f4346a04f4a2da7 Mon Sep 17 00:00:00 2001 From: Riccardo Azzolini Date: Thu, 31 Jan 2019 12:55:15 +0100 Subject: [PATCH] Replace DslException with the DslError interface and the SyntaxException wrapper --- .../math/rules/dsl/DslAggregateException.java | 16 ++--- .../dsl/{DslException.java => DslError.java} | 8 +-- .../warppi/math/rules/dsl/RulesDsl.java | 4 +- ...ception.java => UndefinedSubFunction.java} | 6 +- ...tion.java => IncompleteNumberLiteral.java} | 12 ++-- .../warppi/math/rules/dsl/frontend/Lexer.java | 43 +++++++++----- .../math/rules/dsl/frontend/Parser.java | 58 ++++++++++--------- .../rules/dsl/frontend/SyntaxException.java | 20 +++++++ ...ception.java => UnexpectedCharacters.java} | 16 ++--- ...kenException.java => UnexpectedToken.java} | 14 ++--- .../math/rules/dsl/frontend/LexerTest.java | 28 ++++----- .../math/rules/dsl/frontend/ParserTest.java | 36 ++++++------ 12 files changed, 148 insertions(+), 113 deletions(-) rename core/src/main/java/it/cavallium/warppi/math/rules/dsl/{DslException.java => DslError.java} (50%) rename core/src/main/java/it/cavallium/warppi/math/rules/dsl/{UndefinedSubFunctionException.java => UndefinedSubFunction.java} (73%) rename core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/{IncompleteNumberLiteralException.java => IncompleteNumberLiteral.java} (67%) create mode 100644 core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/SyntaxException.java rename core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/{UnexpectedCharactersException.java => UnexpectedCharacters.java} (59%) rename core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/{UnexpectedTokenException.java => UnexpectedToken.java} (70%) diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/DslAggregateException.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/DslAggregateException.java index 8b0481b6..1dcf7019 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/DslAggregateException.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/DslAggregateException.java @@ -5,23 +5,23 @@ import java.util.List; /** * Thrown when processing DSL code which contains one or more errors. * - * Contains a list of {@link DslException}s, which should not be empty. + * Contains a list of {@link DslError}s, which should not be empty. */ public class DslAggregateException extends Exception { - private final List exceptions; + private final List errors; /** - * Constructs a DslAggregateException containing the specified list of exceptions. - * @param exceptions The list of exceptions. Should not be empty. + * Constructs a DslAggregateException containing the specified list of errors. + * @param errors The list of errors. Should not be empty. */ - public DslAggregateException(final List exceptions) { - this.exceptions = exceptions; + public DslAggregateException(final List errors) { + this.errors = errors; } /** * @return The list of errors detected in the DSL code. */ - public List getExceptions() { - return exceptions; + public List getErrors() { + return errors; } } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/DslException.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/DslError.java similarity index 50% rename from core/src/main/java/it/cavallium/warppi/math/rules/dsl/DslException.java rename to core/src/main/java/it/cavallium/warppi/math/rules/dsl/DslError.java index 3fc1e0a6..a3c16ae6 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/DslException.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/DslError.java @@ -1,16 +1,16 @@ package it.cavallium.warppi.math.rules.dsl; /** - * The superclass of all exceptions which represent errors in DSL code. + * Represents an error in DSL code. */ -public abstract class DslException extends Exception { +public interface DslError { /** * @return The index at which the error starts in the source string. */ - public abstract int getPosition(); + int getPosition(); /** * @return The length of the error in the source string. */ - public abstract int getLength(); + int getLength(); } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/RulesDsl.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/RulesDsl.java index 9ef8aa4b..0c3a14f6 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/RulesDsl.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/RulesDsl.java @@ -11,7 +11,7 @@ public class RulesDsl { private RulesDsl() {} public static List makeRules(final String source) throws DslAggregateException { - final List errors = new ArrayList<>(); + final List errors = new ArrayList<>(); final Lexer lexer = new Lexer(source, errors::add); final Parser parser = new Parser(lexer.lex(), errors::add); @@ -20,7 +20,7 @@ public class RulesDsl { for (final PatternRule rule : rules) { undefinedSubFunctions(rule).stream() .flatMap(subFunc -> parser.getSubFunctionIdentifiers(rule.getRuleName(), subFunc).stream()) - .map(UndefinedSubFunctionException::new) + .map(UndefinedSubFunction::new) .forEach(errors::add); } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/UndefinedSubFunctionException.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/UndefinedSubFunction.java similarity index 73% rename from core/src/main/java/it/cavallium/warppi/math/rules/dsl/UndefinedSubFunctionException.java rename to core/src/main/java/it/cavallium/warppi/math/rules/dsl/UndefinedSubFunction.java index a4d79f54..8816bd47 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/UndefinedSubFunctionException.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/UndefinedSubFunction.java @@ -3,13 +3,13 @@ package it.cavallium.warppi.math.rules.dsl; import it.cavallium.warppi.math.rules.dsl.frontend.Token; /** - * Thrown when a sub-function is used in one of the replacement pattern of a PatternRule, + * Occurs when a sub-function is used in one of the replacement pattern of a PatternRule, * but not defined (captured) in the target pattern. */ -public class UndefinedSubFunctionException extends DslException { +public class UndefinedSubFunction implements DslError { private final Token identifier; - public UndefinedSubFunctionException(final Token identifier) { + public UndefinedSubFunction(final Token identifier) { this.identifier = identifier; } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/IncompleteNumberLiteralException.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/IncompleteNumberLiteral.java similarity index 67% rename from core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/IncompleteNumberLiteralException.java rename to core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/IncompleteNumberLiteral.java index 0414e8e3..fd9966d2 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/IncompleteNumberLiteralException.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/IncompleteNumberLiteral.java @@ -1,19 +1,19 @@ package it.cavallium.warppi.math.rules.dsl.frontend; -import it.cavallium.warppi.math.rules.dsl.DslException; +import it.cavallium.warppi.math.rules.dsl.DslError; import java.util.Objects; /** - * Thrown when DSL source code contains a number literal with a decimal separator which is not followed by digits. + * Occurs when DSL source code contains a number literal with a decimal separator which is not followed by digits. *

* An example of an incomplete literal is 2., while 2 and 2.2 are valid. */ -public class IncompleteNumberLiteralException extends DslException { +public class IncompleteNumberLiteral implements DslError { private final int position; private final String literal; - public IncompleteNumberLiteralException(final int position, final String literal) { + public IncompleteNumberLiteral(final int position, final String literal) { this.position = position; this.literal = literal; } @@ -37,10 +37,10 @@ public class IncompleteNumberLiteralException extends DslException { @Override public boolean equals(final Object o) { - if (!(o instanceof IncompleteNumberLiteralException)) { + if (!(o instanceof IncompleteNumberLiteral)) { return false; } - final IncompleteNumberLiteralException other = (IncompleteNumberLiteralException) o; + final IncompleteNumberLiteral other = (IncompleteNumberLiteral) o; return this.position == other.position && this.literal.equals(other.literal); } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/Lexer.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/Lexer.java index eea89648..b013a02f 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/Lexer.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/Lexer.java @@ -1,6 +1,6 @@ package it.cavallium.warppi.math.rules.dsl.frontend; -import it.cavallium.warppi.math.rules.dsl.DslException; +import it.cavallium.warppi.math.rules.dsl.DslError; import java.util.ArrayList; import java.util.List; @@ -27,14 +27,14 @@ public class Lexer { )); private final String source; - private final Consumer errorReporter; + private final Consumer errorReporter; private final List tokens = new ArrayList<>(); private int startOfLexeme = 0; private int curPosition = 0; - private UnexpectedCharactersException unexpectedCharacters = null; + private UnexpectedCharacters unexpectedCharacters = null; - public Lexer(final String source, final Consumer errorReporter) { + public Lexer(final String source, final Consumer errorReporter) { this.source = source; this.errorReporter = errorReporter; } @@ -55,16 +55,23 @@ public class Lexer { try { lexToken(); reportAndClearUnexpectedCharacters(); // After finding some expected characters - } catch (UnexpectedCharactersException e) { - if (unexpectedCharacters == null) { - unexpectedCharacters = e; + } catch (final SyntaxException e) { + final DslError error = e.getError(); + if (error instanceof UnexpectedCharacters) { + addUnexpectedCharacters((UnexpectedCharacters) error); } else { - unexpectedCharacters = unexpectedCharacters.concat(e); + // If there are multiple errors, report them in the order in which they occur in the source + reportAndClearUnexpectedCharacters(); + errorReporter.accept(error); } - } catch (IncompleteNumberLiteralException e) { - // If there are multiple errors, report them in the order in which they occur in the source - reportAndClearUnexpectedCharacters(); - errorReporter.accept(e); + } + } + + private void addUnexpectedCharacters(final UnexpectedCharacters unexpected) { + if (unexpectedCharacters == null) { + unexpectedCharacters = unexpected; + } else { + unexpectedCharacters = unexpectedCharacters.concat(unexpected); } } @@ -76,7 +83,7 @@ public class Lexer { unexpectedCharacters = null; } - private void lexToken() throws UnexpectedCharactersException, IncompleteNumberLiteralException { + private void lexToken() throws SyntaxException { char current = popChar(); switch (current) { case ':': emitToken(COLON); break; @@ -121,7 +128,9 @@ public class Lexer { } else if (Character.isJavaIdentifierStart(current)) { keywordOrIdentifier(); } else if (!Character.isWhitespace(current)) { - throw new UnexpectedCharactersException(curPosition - 1, String.valueOf(current)); + throw new SyntaxException( + new UnexpectedCharacters(curPosition - 1, String.valueOf(current)) + ); } } } @@ -136,10 +145,12 @@ public class Lexer { } } - private void number() throws IncompleteNumberLiteralException { + private void number() throws SyntaxException { matchWhile(Lexer::isAsciiDigit); if (matchChar('.') && matchWhile(Lexer::isAsciiDigit) == 0) { - throw new IncompleteNumberLiteralException(startOfLexeme, currentLexeme()); + throw new SyntaxException( + new IncompleteNumberLiteral(startOfLexeme, currentLexeme()) + ); } emitToken(NUMBER); } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/Parser.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/Parser.java index 8349f453..b45a7163 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/Parser.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/Parser.java @@ -2,7 +2,7 @@ package it.cavallium.warppi.math.rules.dsl.frontend; import it.cavallium.warppi.math.MathematicalSymbols; import it.cavallium.warppi.math.rules.RuleType; -import it.cavallium.warppi.math.rules.dsl.DslException; +import it.cavallium.warppi.math.rules.dsl.DslError; import it.cavallium.warppi.math.rules.dsl.Pattern; import it.cavallium.warppi.math.rules.dsl.PatternRule; import it.cavallium.warppi.math.rules.dsl.patterns.*; @@ -27,14 +27,14 @@ public class Parser { ); private final List tokens; - private final Consumer errorReporter; + private final Consumer errorReporter; private int current = 0; // For error reporting private String currentRuleName; private final Map>> subFunctionIdentifiers = new HashMap<>(); - public Parser(final List tokens, final Consumer errorReporter) { + public Parser(final List tokens, final Consumer errorReporter) { this.tokens = tokens; this.errorReporter = errorReporter; } @@ -53,8 +53,8 @@ public class Parser { while (!atEnd()) { try { rules.add(rule()); - } catch (UnexpectedTokenException e) { - errorReporter.accept(e); + } catch (final SyntaxException e) { + errorReporter.accept(e.getError()); synchronizeTo(ruleTypes.keySet()); // Skip to the next rule to minimize "false" errors } } @@ -64,7 +64,7 @@ public class Parser { // rule = rule header , rule body ; // rule header = rule type , IDENTIFIER , COLON ; // rule body = pattern , ARROW , replacements ; - private PatternRule rule() throws UnexpectedTokenException { + private PatternRule rule() throws SyntaxException { final RuleType type = ruleType(); final String name = matchOrFail(IDENTIFIER).lexeme; currentRuleName = name; // This field must be set before calling pattern() and replacements() @@ -76,23 +76,25 @@ public class Parser { } // rule type = REDUCTION | EXPANSION | CALCULATION | EXISTENCE ; - private RuleType ruleType() throws UnexpectedTokenException { + private RuleType ruleType() throws SyntaxException { final Token curToken = pop(); if (!ruleTypes.containsKey(curToken.type)) { - throw new UnexpectedTokenException(curToken, ruleTypes.keySet()); + throw new SyntaxException( + new UnexpectedToken(curToken, ruleTypes.keySet()) + ); } return ruleTypes.get(curToken.type); } // pattern = equation ; - private Pattern pattern() throws UnexpectedTokenException { + private Pattern pattern() throws SyntaxException { return equation(); } // replacements = pattern // | LEFT_BRACKET , patterns , RIGHT_BRACKET ; // patterns = [ pattern , { COMMA , pattern } , [ COMMA ] ] ; - private List replacements() throws UnexpectedTokenException { + private List replacements() throws SyntaxException { if (match(LEFT_BRACKET) == null) { return Collections.singletonList(pattern()); } @@ -110,7 +112,7 @@ public class Parser { } // equation = sum , [ EQUALS , sum ] ; - private Pattern equation() throws UnexpectedTokenException { + private Pattern equation() throws SyntaxException { Pattern pat = sum(); if (match(EQUALS) != null) { pat = new EquationPattern(pat, sum()); @@ -119,7 +121,7 @@ public class Parser { } // sum = product , { ( PLUS | MINUS | PLUS_MINUS ) product } ; - private Pattern sum() throws UnexpectedTokenException { + private Pattern sum() throws SyntaxException { return matchLeftAssoc(this::product, Map.ofEntries( Map.entry(PLUS, SumPattern::new), Map.entry(MINUS, SubtractionPattern::new), @@ -128,7 +130,7 @@ public class Parser { } // product = unary , { ( TIMES | DIVIDE ) unary } ; - private Pattern product() throws UnexpectedTokenException { + private Pattern product() throws SyntaxException { return matchLeftAssoc(this::unary, Map.ofEntries( Map.entry(TIMES, MultiplicationPattern::new), Map.entry(DIVIDE, DivisionPattern::new) @@ -137,7 +139,7 @@ public class Parser { // unary = ( PLUS | MINUS ) unary // | power ; - private Pattern unary() throws UnexpectedTokenException { + private Pattern unary() throws SyntaxException { if (match(PLUS) != null) { return unary(); } else if (match(MINUS) != null) { @@ -148,7 +150,7 @@ public class Parser { } // power = ( function | primary ) , [ POWER , power ] ; - private Pattern power() throws UnexpectedTokenException { + private Pattern power() throws SyntaxException { Pattern pat = functionOrPrimary(); if (match(POWER) != null) { pat = new PowerPattern(pat, power()); @@ -156,14 +158,14 @@ public class Parser { return pat; } - private Pattern functionOrPrimary() throws UnexpectedTokenException { + private Pattern functionOrPrimary() throws SyntaxException { final Pattern function = tryFunction(); return function != null ? function : primary(); } // function = ( ARCCOS | ARCSIN | ARCTAN | COS | SIN | SQRT | TAN ) , LEFT_PAREN , sum , RIGHT_PAREN // | ( LOG | ROOT ) LEFT_PAREN , sum , COMMA , sum , RIGHT_PAREN ; - private Pattern tryFunction() throws UnexpectedTokenException { + private Pattern tryFunction() throws SyntaxException { final Map> oneArg = Map.ofEntries( Map.entry(ARCCOS, ArcCosinePattern::new), Map.entry(ARCSIN, ArcSinePattern::new), @@ -190,14 +192,14 @@ public class Parser { return null; } - private Pattern oneArgFunction(final Function constructor) throws UnexpectedTokenException { + private Pattern oneArgFunction(final Function constructor) throws SyntaxException { matchOrFail(LEFT_PAREN); final Pattern arg = pattern(); matchOrFail(RIGHT_PAREN); return constructor.apply(arg); } - private Pattern twoArgFunction(final BiFunction constructor) throws UnexpectedTokenException { + private Pattern twoArgFunction(final BiFunction constructor) throws SyntaxException { matchOrFail(LEFT_PAREN); final Pattern firstArg = pattern(); matchOrFail(COMMA); @@ -209,7 +211,7 @@ public class Parser { // primary = NUMBER | constant | IDENTIFIER | UNDEFINED // | LEFT_PAREN sum RIGHT_PAREN ; // constant = PI | E ; - private Pattern primary() throws UnexpectedTokenException { + private Pattern primary() throws SyntaxException { final Token curToken = pop(); switch (curToken.type) { case PI: @@ -229,7 +231,7 @@ public class Parser { matchOrFail(RIGHT_PAREN); return grouped; } - throw new UnexpectedTokenException(curToken); + throw new SyntaxException(new UnexpectedToken(curToken)); } private void saveSubFunctionIdentifier(final SubFunctionPattern subFunction, final Token curToken) { @@ -247,7 +249,7 @@ public class Parser { private Pattern matchLeftAssoc( final PatternParser operandParser, final Map> operators - ) throws UnexpectedTokenException { + ) throws SyntaxException { Pattern pat = operandParser.parse(); while (operators.containsKey(peek().type)) { final Token operatorToken = pop(); @@ -257,10 +259,12 @@ public class Parser { return pat; } - private Token matchOrFail(final TokenType expectedType) throws UnexpectedTokenException { + private Token matchOrFail(final TokenType expectedType) throws SyntaxException { final Token matched = match(expectedType); if (matched == null) { - throw new UnexpectedTokenException(tokens.get(current), expectedType); + throw new SyntaxException( + new UnexpectedToken(tokens.get(current), expectedType) + ); } return matched; } @@ -280,10 +284,10 @@ public class Parser { } } - private Token pop() throws UnexpectedTokenException { + private Token pop() throws SyntaxException { final Token curToken = tokens.get(current); if (atEnd()) { - throw new UnexpectedTokenException(curToken); // Avoid popping EOF + throw new SyntaxException(new UnexpectedToken(curToken)); // Avoid popping EOF } current++; return curToken; @@ -299,6 +303,6 @@ public class Parser { @FunctionalInterface private interface PatternParser { - Pattern parse() throws UnexpectedTokenException; + Pattern parse() throws SyntaxException; } } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/SyntaxException.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/SyntaxException.java new file mode 100644 index 00000000..3a5c448b --- /dev/null +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/SyntaxException.java @@ -0,0 +1,20 @@ +package it.cavallium.warppi.math.rules.dsl.frontend; + +import it.cavallium.warppi.math.rules.dsl.DslError; + +/** + * Thrown when DSL source code contains a syntax error. + *

+ * Used for error reporting and recovery in the implementation of {@link Lexer} and {@link Parser}. + */ +class SyntaxException extends Exception { + private final DslError error; + + SyntaxException(final DslError error) { + this.error = error; + } + + public DslError getError() { + return error; + } +} diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnexpectedCharactersException.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnexpectedCharacters.java similarity index 59% rename from core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnexpectedCharactersException.java rename to core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnexpectedCharacters.java index 2c989112..1d9e1b06 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnexpectedCharactersException.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnexpectedCharacters.java @@ -1,17 +1,17 @@ package it.cavallium.warppi.math.rules.dsl.frontend; -import it.cavallium.warppi.math.rules.dsl.DslException; +import it.cavallium.warppi.math.rules.dsl.DslError; import java.util.Objects; /** - * Thrown when DSL source code contains one or more (consecutive) characters which are not expected by the lexer. + * Occurs when DSL source code contains one or more (consecutive) characters which are not expected by the lexer. */ -public class UnexpectedCharactersException extends DslException { +public class UnexpectedCharacters implements DslError { private final int position; private final String unexpectedCharacters; - public UnexpectedCharactersException(final int position, final String unexpectedCharacters) { + public UnexpectedCharacters(final int position, final String unexpectedCharacters) { this.position = position; this.unexpectedCharacters = unexpectedCharacters; } @@ -33,16 +33,16 @@ public class UnexpectedCharactersException extends DslException { return unexpectedCharacters; } - UnexpectedCharactersException concat(UnexpectedCharactersException other) { - return new UnexpectedCharactersException(this.position, this.unexpectedCharacters + other.unexpectedCharacters); + UnexpectedCharacters concat(UnexpectedCharacters other) { + return new UnexpectedCharacters(this.position, this.unexpectedCharacters + other.unexpectedCharacters); } @Override public boolean equals(final Object o) { - if (!(o instanceof UnexpectedCharactersException)) { + if (!(o instanceof UnexpectedCharacters)) { return false; } - final UnexpectedCharactersException other = (UnexpectedCharactersException) o; + final UnexpectedCharacters other = (UnexpectedCharacters) o; return this.position == other.position && this.unexpectedCharacters.equals(other.unexpectedCharacters); } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnexpectedTokenException.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnexpectedToken.java similarity index 70% rename from core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnexpectedTokenException.java rename to core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnexpectedToken.java index 04f6363d..17a35e67 100644 --- a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnexpectedTokenException.java +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnexpectedToken.java @@ -1,23 +1,23 @@ package it.cavallium.warppi.math.rules.dsl.frontend; -import it.cavallium.warppi.math.rules.dsl.DslException; +import it.cavallium.warppi.math.rules.dsl.DslError; import java.util.Objects; import java.util.Set; /** - * Thrown when DSL source code contains a token which doesn't match the grammar. + * Occurs when DSL source code contains a token which doesn't match the grammar. */ -public class UnexpectedTokenException extends DslException { +public class UnexpectedToken implements DslError { private final Token unexpected; private final Set suggested; - public UnexpectedTokenException(final Token unexpected, final Set suggested) { + public UnexpectedToken(final Token unexpected, final Set suggested) { this.unexpected = unexpected; this.suggested = suggested; } - public UnexpectedTokenException(final Token unexpected, final TokenType... suggested) { + public UnexpectedToken(final Token unexpected, final TokenType... suggested) { this.unexpected = unexpected; this.suggested = Set.of(suggested); } @@ -50,10 +50,10 @@ public class UnexpectedTokenException extends DslException { @Override public boolean equals(final Object o) { - if (!(o instanceof UnexpectedTokenException)) { + if (!(o instanceof UnexpectedToken)) { return false; } - final UnexpectedTokenException other = (UnexpectedTokenException) o; + final UnexpectedToken other = (UnexpectedToken) o; return this.unexpected.equals(other.unexpected) && this.suggested.equals(other.suggested); } diff --git a/core/src/test/java/it/cavallium/warppi/math/rules/dsl/frontend/LexerTest.java b/core/src/test/java/it/cavallium/warppi/math/rules/dsl/frontend/LexerTest.java index 06458ea0..7491eedc 100644 --- a/core/src/test/java/it/cavallium/warppi/math/rules/dsl/frontend/LexerTest.java +++ b/core/src/test/java/it/cavallium/warppi/math/rules/dsl/frontend/LexerTest.java @@ -1,6 +1,6 @@ package it.cavallium.warppi.math.rules.dsl.frontend; -import it.cavallium.warppi.math.rules.dsl.DslException; +import it.cavallium.warppi.math.rules.dsl.DslError; import org.junit.Before; import org.junit.Test; @@ -13,7 +13,7 @@ import static it.cavallium.warppi.math.rules.dsl.frontend.TokenType.*; import static org.junit.Assert.*; public class LexerTest { - private final List errors = new ArrayList<>(); + private final List errors = new ArrayList<>(); @Before public void setUp() { @@ -87,8 +87,8 @@ public class LexerTest { ); assertEquals(expectedTokens, lexer.lex()); - final List expectedErrors = Collections.singletonList( - new IncompleteNumberLiteralException(0, "2.") + final List expectedErrors = Collections.singletonList( + new IncompleteNumberLiteral(0, "2.") ); assertEquals(expectedErrors, errors); } @@ -102,8 +102,8 @@ public class LexerTest { ); assertEquals(expectedTokens, lexer.lex()); - final List expectedErrors = Collections.singletonList( - new IncompleteNumberLiteralException(0, "2.") + final List expectedErrors = Collections.singletonList( + new IncompleteNumberLiteral(0, "2.") ); assertEquals(expectedErrors, errors); } @@ -119,10 +119,10 @@ public class LexerTest { ); assertEquals(expectedTokens, lexer.lex()); - final List expectedErrors = Arrays.asList( - new UnexpectedCharactersException(10, "@|"), - new UnexpectedCharactersException(13, "."), - new UnexpectedCharactersException(16, "{}") + final List expectedErrors = Arrays.asList( + new UnexpectedCharacters(10, "@|"), + new UnexpectedCharacters(13, "."), + new UnexpectedCharacters(16, "{}") ); assertEquals(expectedErrors, errors); } @@ -136,10 +136,10 @@ public class LexerTest { ); assertEquals(expectedTokens, lexer.lex()); - final List expectedErrors = Arrays.asList( - new UnexpectedCharactersException(0, "."), - new IncompleteNumberLiteralException(1, "2."), - new UnexpectedCharactersException(4, "@") + final List expectedErrors = Arrays.asList( + new UnexpectedCharacters(0, "."), + new IncompleteNumberLiteral(1, "2."), + new UnexpectedCharacters(4, "@") ); assertEquals(expectedErrors, errors); } diff --git a/core/src/test/java/it/cavallium/warppi/math/rules/dsl/frontend/ParserTest.java b/core/src/test/java/it/cavallium/warppi/math/rules/dsl/frontend/ParserTest.java index 6a0a6a7d..c2687541 100644 --- a/core/src/test/java/it/cavallium/warppi/math/rules/dsl/frontend/ParserTest.java +++ b/core/src/test/java/it/cavallium/warppi/math/rules/dsl/frontend/ParserTest.java @@ -2,7 +2,7 @@ package it.cavallium.warppi.math.rules.dsl.frontend; import it.cavallium.warppi.math.MathematicalSymbols; import it.cavallium.warppi.math.rules.RuleType; -import it.cavallium.warppi.math.rules.dsl.DslException; +import it.cavallium.warppi.math.rules.dsl.DslError; import it.cavallium.warppi.math.rules.dsl.Pattern; import it.cavallium.warppi.math.rules.dsl.PatternRule; import it.cavallium.warppi.math.rules.dsl.patterns.*; @@ -19,7 +19,7 @@ import static it.cavallium.warppi.math.rules.dsl.frontend.TokenType.*; import static org.junit.Assert.*; public class ParserTest { - private final List errors = new ArrayList<>(); + private final List errors = new ArrayList<>(); @Before public void setUp() { @@ -312,7 +312,7 @@ public class ParserTest { assertTrue(parser.parse().isEmpty()); - final List expectedErrors = Collections.singletonList(new UnexpectedTokenException( + final List expectedErrors = Collections.singletonList(new UnexpectedToken( new Token(EOF, "", 0) )); assertEquals(expectedErrors, errors); @@ -328,7 +328,7 @@ public class ParserTest { assertTrue(parser.parse().isEmpty()); - final List expectedErrors = Collections.singletonList(new UnexpectedTokenException( + final List expectedErrors = Collections.singletonList(new UnexpectedToken( new Token(IDENTIFIER, "test", 0), REDUCTION, EXPANSION, CALCULATION, EXISTENCE )); @@ -353,7 +353,7 @@ public class ParserTest { assertTrue(parser.parse().isEmpty()); - final List expectedErrors = Collections.singletonList(new UnexpectedTokenException( + final List expectedErrors = Collections.singletonList(new UnexpectedToken( new Token(CALCULATION, "calculation", 0) )); assertEquals(expectedErrors, errors); @@ -370,7 +370,7 @@ public class ParserTest { assertTrue(parser.parse().isEmpty()); - final List expectedErrors = Collections.singletonList(new UnexpectedTokenException( + final List expectedErrors = Collections.singletonList(new UnexpectedToken( new Token(COLON, ":", 0), IDENTIFIER )); @@ -391,7 +391,7 @@ public class ParserTest { assertTrue(parser.parse().isEmpty()); - final List expectedErrors = Collections.singletonList(new UnexpectedTokenException( + final List expectedErrors = Collections.singletonList(new UnexpectedToken( new Token(IDENTIFIER, "x", 0), COLON )); @@ -412,7 +412,7 @@ public class ParserTest { assertTrue(parser.parse().isEmpty()); - final List expectedErrors = Collections.singletonList(new UnexpectedTokenException( + final List expectedErrors = Collections.singletonList(new UnexpectedToken( new Token(IDENTIFIER, "y", 0), ARROW )); @@ -435,7 +435,7 @@ public class ParserTest { assertTrue(parser.parse().isEmpty()); - final List expectedErrors = Collections.singletonList(new UnexpectedTokenException( + final List expectedErrors = Collections.singletonList(new UnexpectedToken( new Token(EOF, "", 0), RIGHT_BRACKET )); @@ -460,7 +460,7 @@ public class ParserTest { assertTrue(parser.parse().isEmpty()); - final List expectedErrors = Collections.singletonList(new UnexpectedTokenException( + final List expectedErrors = Collections.singletonList(new UnexpectedToken( new Token(IDENTIFIER, "x", 0), LEFT_PAREN )); @@ -485,7 +485,7 @@ public class ParserTest { assertTrue(parser.parse().isEmpty()); - final List expectedErrors = Collections.singletonList(new UnexpectedTokenException( + final List expectedErrors = Collections.singletonList(new UnexpectedToken( new Token(ARROW, "->", 0), RIGHT_PAREN )); @@ -512,7 +512,7 @@ public class ParserTest { assertTrue(parser.parse().isEmpty()); - final List expectedErrors = Collections.singletonList(new UnexpectedTokenException( + final List expectedErrors = Collections.singletonList(new UnexpectedToken( new Token(IDENTIFIER, "x", 0), LEFT_PAREN )); @@ -539,7 +539,7 @@ public class ParserTest { assertTrue(parser.parse().isEmpty()); - final List expectedErrors = Collections.singletonList(new UnexpectedTokenException( + final List expectedErrors = Collections.singletonList(new UnexpectedToken( new Token(IDENTIFIER, "y", 0), COMMA )); @@ -566,7 +566,7 @@ public class ParserTest { assertTrue(parser.parse().isEmpty()); - final List expectedErrors = Collections.singletonList(new UnexpectedTokenException( + final List expectedErrors = Collections.singletonList(new UnexpectedToken( new Token(ARROW, "->", 0), RIGHT_PAREN )); @@ -590,7 +590,7 @@ public class ParserTest { assertTrue(parser.parse().isEmpty()); - final List expectedErrors = Collections.singletonList(new UnexpectedTokenException( + final List expectedErrors = Collections.singletonList(new UnexpectedToken( new Token(ARROW, "->", 0), RIGHT_PAREN )); @@ -640,9 +640,9 @@ public class ParserTest { )); assertEquals(expectedRules, parser.parse()); - final List expectedErrors = Arrays.asList( - new UnexpectedTokenException(new Token(ARROW, "->", 0)), - new UnexpectedTokenException(new Token(IDENTIFIER, "x", 0), COLON) + final List expectedErrors = Arrays.asList( + new UnexpectedToken(new Token(ARROW, "->", 0)), + new UnexpectedToken(new Token(IDENTIFIER, "x", 0), COLON) ); assertEquals(expectedErrors, errors); }