From 04d01565daeb4bc06ce88b8c0e8f9b745e16356a Mon Sep 17 00:00:00 2001 From: Riccardo Azzolini Date: Mon, 11 Feb 2019 16:31:03 +0100 Subject: [PATCH] Correctly handle and report unterminated multiline comments in Lexer --- .../warppi/math/rules/dsl/frontend/Lexer.java | 5 ++- .../dsl/frontend/UnterminatedComment.java | 40 +++++++++++++++++++ .../math/rules/dsl/frontend/LexerTest.java | 16 ++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnterminatedComment.java 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 b013a02f..0119dfb2 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 @@ -139,8 +139,11 @@ public class Lexer { matchWhile(c -> c != '\n'); } - private void multiLineComment() { + private void multiLineComment() throws SyntaxException { while (!(matchChar('*') && matchChar('/'))) { + if (atEnd()) { + throw new SyntaxException(new UnterminatedComment(startOfLexeme)); + } popChar(); } } diff --git a/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnterminatedComment.java b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnterminatedComment.java new file mode 100644 index 00000000..2ff9ce12 --- /dev/null +++ b/core/src/main/java/it/cavallium/warppi/math/rules/dsl/frontend/UnterminatedComment.java @@ -0,0 +1,40 @@ +package it.cavallium.warppi.math.rules.dsl.frontend; + +import it.cavallium.warppi.math.rules.dsl.DslError; + +import java.util.Objects; + +/** + * Occurs when DSL source code contains a multiline comment which is never terminated (closed). + */ +public class UnterminatedComment implements DslError { + private final int position; + + public UnterminatedComment(final int position) { + this.position = position; + } + + @Override + public int getPosition() { + return position; + } + + @Override + public int getLength() { + return 2; // Length of comment start marker: "/*" + } + + @Override + public boolean equals(final Object o) { + if (!(o instanceof UnterminatedComment)) { + return false; + } + final UnterminatedComment other = (UnterminatedComment) o; + return this.position == other.position; + } + + @Override + public int hashCode() { + return Objects.hash(position); + } +} 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 7491eedc..1b29759a 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 @@ -127,6 +127,22 @@ public class LexerTest { assertEquals(expectedErrors, errors); } + @Test + public void unterminatedComment() { + final Lexer lexer = new Lexer("reduction /* test:\n x -> x", errors::add); + + final List expectedTokens = Arrays.asList( + new Token(REDUCTION, "reduction", 0), + new Token(EOF, "", 26) + ); + assertEquals(expectedTokens, lexer.lex()); + + final List expectedErrors = Collections.singletonList( + new UnterminatedComment(10) + ); + assertEquals(expectedErrors, errors); + } + @Test public void errorOrder() { final Lexer lexer = new Lexer(".2. @", errors::add);